python代码解析

Python代码解析入门
这篇博客主要解析了Python的基础语法,包括import、reload()、def、变量定义、数组、循环、time模块、异常处理、格式化输出、strip()、sorted()、open()、__main__与__init__、文件头声明、openpyxl库、range()与len()函数、数据类型转换、None、raw_input()与input()、with...as...结构以及yield关键字,适合初学者了解Python编程。

最近准备好好学学python爬虫,从网上找了个例子,爬取豆瓣读书的信息,原文地址:http://blog.youkuaiyun.com/lanbing510/article/details/45887075

代码地址:

https://raw.githubusercontent.com/lanbing510/DouBanSpider/master/doubanSpider.py

因为以前基本没接触过python,所以对代码做个简单的解析,先贴下代码如下:

#-*- coding: UTF-8 -*-

import sys
import time
import urllib
import urllib2
import requests
import numpy as np
from bs4 import BeautifulSoup
from openpyxl import Workbook

reload(sys)
sys.setdefaultencoding('utf8')


def book_spider(book_tag):
    page_num=0;
    count=1
    book_list=[]
    try_times=0
    
    #Some User Agents
    hds=[{'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'},\
         {'User-Agent':'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11'},\
         {'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'}]
         
    while(1):
        url="http://www.douban.com/tag/"+urllib.quote(book_tag)+"/book?start="+str(page_num*15)
        time.sleep(np.random.rand()*2)
        
        #Last Version
        try:
            req = urllib2.Request(url, headers=hds[page_num%len(hds)])
            source_code = urllib2.urlopen(req).read()
            plain_text=str(source_code)   
        except (urllib2.HTTPError, urllib2.URLError), e:
            print e
            continue
  
        ##Previous Version, IP is easy to be Forbidden
        #source_code = requests.get(url) 
        #plain_text = source_code.text  
        
        soup = BeautifulSoup(plain_text)
        list_soup = soup.find('div', {'class': 'mod book-list'})
        
        try_times+=1;
        if list_soup==None and try_times<200:
            continue
        elif list_soup==None or len(list_soup)<=1:
            break # Break when no informatoin got after 200 times requesting
        
        for book_info in list_soup.findAll('dd'):
            title = book_info.find('a', {'class':'title'}).string.strip()
            desc = book_info.find('div', {'class':'desc'}).string.strip()
            desc_list = desc.split('/')
            
            try:
                author_info = '作者/译者: ' + '/'.join(desc_list[0:-3])
            except:
                author_info='作者/译者: 暂无'
            try:
                pub_info = '出版信息: ' + '/'.join(desc_list[-3:])
            except:
                pub_info='出版信息: 暂无'
            try:
                rating = book_info.find('span', {'class':'rating_nums'}).string.strip()
            except:
                rating='0.0'
            try:
                people_num = book_info.findAll('span')[2].string.strip()
                people_num=people_num.strip('人评价')
            except:
                people_num='0'
            
            book_list.append([title,rating,people_num,author_info,pub_info])
            try_times=0 #set 0 when got valid information
        page_num+=1
        print "Downloading Information From Page %d" % page_num
    return book_list


def do_spider(book_tag_lists):
    book_lists=[]
    for book_tag in book_tag_lists:
        book_list=book_spider(book_tag)
        book_list=sorted(book_list,key=lambda x:x[1],reverse=True)
        book_lists.append(book_list)
    return book_lists


def print_book_lists_excel(book_lists,book_tag_lists):
    wb=Workbook(optimized_write=True)
    ws=[]
    for i in range(len(book_tag_lists)):
        ws.append(wb.create_sheet(title=book_tag_lists[i].decode())) #utf8->unicode
    for i in range(len(book_tag_lists)): 
        ws[i].append(['序号','书名','评分','评价人数','作者','出版社'])
        count=1
        for bl in book_lists[i]:
            ws[i].append([count,bl[0],float(bl[1]),int(bl[2]),bl[3],bl[4]])
            count+=1
    save_path='book_list'
    for i in range(len(book_tag_lists)):
        save_path+=('-'+book_tag_lists[i].decode())
    save_path+='.xlsx'
    wb.save(save_path)



if __name__=='__main__':
    #book_tag_lists = ['心理','判断与决策','算法','数据结构','经济','历史']
    #book_tag_lists = ['传记','哲学','编程','创业','理财','社会学','佛教']
    #book_tag_lists=['思想','科技','科学','web','股票','爱情','两性']
    book_tag_lists=['计算机','机器学习','linux','android','数据库','互联网']
    book_lists=do_spider(book_tag_lists)
    print_book_lists_excel(book_lists,book_tag_lists)
    

代码解析:

1、import

引入其他模块的代码,有两种引入的方式 一种是import xxx,另外一种是from  xxx import yyy,第一种针对单个的文件,第二种针对包,第二种意思是从yyy包里引入xxx,python引入的模块有多种形式,可以是python脚本、dll文件等等,具体见: python import

2、reload()

当需要重新载入某个模块的时候,可以使用reload载入某个模块,如reload(sys)意思就是重新载入某个模块,意思是将之前导入的模块再加载一次,这样允许在不退出解释器的情况下重新加载已经更改的模块,不过一般不建议这样做。

2、def

def定义一个模块的变量或者类的变量,它本身是一个函数对象。如def aaa():  就定义了一个叫做aaa()的函数

3、变量定义

count=1  这句话就定义了一个叫count的变量,并将其赋值为1,非常直观。

4、数组

python的数组分为三种类型:

list 普通的链表,初始化后可通过特定的方法动态增加元素

定义方式 arr=[元素]


Tuple固定的数据,一旦定义后不可改变:

定义方式:arr=(元素)


Dictionary类型的数组,即Hash数组,

定义方式 arr={k:v}

5、循环

python支持常用的所有循环,包括while,for等,

如while(1):代表无限循环,除非内部跳出,for循环为foreash形式,形如

for ele in elements:循环遍历elements里的所有元素

6、time模块

time模块为python内建模块,比如我们可以用time.sleep(seconds)让程序休眠一段时间

7、异常处理

python中的异常处理格式为:

try:

     语句1

     语句2

     。。。

except a,b:

     处理异常语句...

finally:

    清理工作...

其中的a和b分别是异常类型和异常对象,值得注意的是这里的异常类型可以是多个,如下:

except (urllib2.HTTPError, urllib2.URLError), e:
8、str()

将一个python的对象转化为对象,注意还有一个函数repr()也是这个功能,不过是它在转化为字符串之后还能转化为之前的对象

9、格式化输出

print "Downloading Information From Page %d" % page_num
看起来是不是很熟悉 ,很类似c语言的风格,其实也很好理解,实用最多的还是c实现的python,当然和C会有一些借鉴

10、strip(xxx)

删除一个字符串首位的xxx字符,如果什么都不传就是删除首位的空格

11、sorted()

排序

11、open()

打开文件,open(name[,mode[,buffering]])

其中name表示需要打开的文件名字,mode是打开模式,第三个参数用来控制是否缓冲,默认是0表示不缓冲,1表示缓冲。

其中mode才是open()的灵魂,

  
  1. 参数 描述
  2.  
  3. r 读取模式打开文件
  4.  
  5. w 读写模式打开文件
  6.  
  7. a 写入模式打开文件
  8.  
  9. b 二进制模式打开文件(可以和其他模式并用)
  10.  
  11. + /写模式(可以和其他模式并用)
  12.  
  13. U 支持换行符(例如:\n\r \n\r )
我们在使用open函数时,首先会函数的文件名称然后才是模式,文件模式是一个相当重要的参数,默认模式参数为'r',用只读的方式打开文件,如读取特殊文件如视频或者图片文件,必须使用'b'模式。

  • o=open('index.txt','w');
  • o.write("大家好,欢迎光临坤子的博客(www.xuyukun.com)!")
  • o.close();

上面的代表表示将字符串写入到index.txt文件中

12、__main__    __init__

在c/c++/java中main是程序执行 的起点,python中也有类似的运行机制,不过方式有所不同,python使用缩进对齐组织代码的执行,所有没有缩进的代码(非函数定义和类定义)都会在载入时自动执行,这些代码可以认为是python的main函数。

python引入__main__变量是为了区分主执行文件还是被调用的文件,当文件是被调用时,__name__的值是模块名字,当文件被直接执行时,__name__的值是__main__,这个特性为测试驱动的开发提供了极好的支持,我们可以在每个模块中写上测试代码,这些测试代码只有在python文件被直接执行的时候才会运行,代码和测试完美的结合在一起。

13、#!/usr/bin/env python 和 #!/usr/bin/python

首先这两行的作用都是为了在运行python文件的时候不需要用python xxx.py这种方式而是可以直接./xxx.py来运行,因为这个头指定了python解释器的位置。接下来说说这两者的区别:

通常认为#!/usr/bin/env python 要比 #!/usr/bin/python要好  因为有的时候python并不是安装在默认路径下面的,例如在virtualenv中。

而#!/usr/bin/python表示是写死了你要这个目录下的python来执行你的脚本,但通常这不是明智的选择。

这种写法在你机器上安装了多个版本的python的时候有意义,这样声明的时候,会去取你机器的 PATH 中指定的第一个 python 来执行你的脚本。如果这时候你又配置了虚拟环境的话,那么这样写可以保证脚本会使用你虚拟环境中的 python 来执行。

所以这样看来,只有第二种方法才是正确的写法。

14、openpyxl

python有好几个包都是用来处理excel的,比如xlrd xlwt  xlutils,但是

  1. 它们都比较老,xlwt甚至不支持07版以后的excel
  2. 它们的文档不太友好,都可能需要去读源代码
openpyxl,支持07+的excel,一直有人在维护,文档清晰易读,参照Tutorial和API文档很快就能上手


15、range(xxx) 和len()函数

range由字面意思可见代表一个范围,

函数原型:range(start, end, scan):

先列几个range()函数的几个用法

            

参数含义:start:计数从start开始。默认是从0开始。例如range(5)等价于range(0, 5);

              end:技术到end结束,但不包括end.例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5

              scan:每次跳跃的间距,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)

for i in range(5):
    print i
    i += 2
    print i
    print '一轮结束'

结果:

   

为什么不是下面的结果?

而不是:

    

原因:每次for时i都被重新赋值了  这点在使用的时候需要注意,和c/c++/java里的for虚幻稍有不同


len()

描述

Python len() 方法返回字符串、列表、字典、元组等长度

语法

len()方法语法:

len( xxx )

16、float()\int()

转化为float和int类型

17、None

None是一个特殊的常量。

None和False不同。

None不是0。

None不是空字符串。

None和任何其他的数据类型比较永远返回False。

None有自己的数据类型NoneType。

你可以将None复制给任何变量,但是你不能创建其他NoneType对象。

Python代码   收藏代码
  1. >>> type(None)  
  2. <class 'NoneType'>  
  3. >>> None == 0  
  4. False  
  5. >>> None == ''  
  6. False  
  7. >>> None == None  
  8. True  
  9. >>> None == False  
  10. False 

None是一个空的对象,代表什么都没有

18、raw_input() 和 input()

两个都是读取用户输入不同点在于raw_input在处理输入时候总将输入作为字符串来处理,而input在遇到数字的时候会将其作为数字处理,如raw_input(3+4)返回字符串'3+4',input(3+4)返回7

而对于 input() ,它希望能够读取一个合法的 python 表达式,即你输入字符串的时候必须使用引号将它括起来,否则它会引发一个 SyntaxError

19、with。。。。as。。。。

简单的来说这个语法是用来代替传统的try。。。finally。。。语法的

with是从Python 2.5 引入的一个新的语法,更准确的说,是一种上下文的管理协议,用于简化try…except…finally的处理流程。with通过__enter__方法初始化,然后在__exit__中做善后以及处理异常。对于一些需要预先设置,事后要清理的一些任务,with提供了一种非常方便的表达。

在Python有2种方式来实现with语法:class-based和decorator-based,2种方式在原理上是等价的,可以根据具体场景自己选择

with最初起源于一种block…as…的语法,但是这种语法被很多人所唾弃,最后诞生了with,关于这段历史依然可以去参考PEP-343和PEP-340

20、yield

带有 yield 的函数在 Python 中被称之为 generator(生成器)

具体参考:http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/



---------------未完待续-------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值