Python 爬虫
python版本2.7,操作系统ubuntu12.04,我是在eclipse实验的。下面是爬互联网网页数据的一些经验。
爬取网页数据核心就是解析网页源文件,思路就是先把网页所有源代码缓存到本地,然后通过软件包或者自己使用正则表达式提取想要找的东西。核心包就是urllib2,主要工具是re(正则表达式)+各种解析网页源代码的python包(beautifulsoup4 ),并行工具使用gevent.monkey包。更主要的工具是google+baidu,大概无论想要实现什么都会找到了。
闲话不多说,以爬 http://military.people.com.cn/n/2013/0705/c1011-22087628.html 为例:
- <!-- lang: python -->
- import urllib2
- f=urllib2.urlopen('http://military.people.com.cn/n/2013/0705/c1011-22087628.html')
- print f.read().lower()
urllib2包里面的urlopen方法打开了一个网址,返回一个socket类型,然后用.read()方法就可以读出url里面的文本,变成一个字符串类型,.lower()方法把所有英文字母变成小写,方便处理。
print之后,应该可以看到控制台输出了网页的源代码,不过会出现乱码。引出先面的编码问题: 看上面这个网页的源代码的头部文件
可以看到编码是GB2312,常用的还有GBK GB18030 这些好像是亚洲地区语言的编码,详细了解自己百度吧,反正都不一样。windows下的简体中文是GBK编码的,这三个之间貌似可以兼容,不过有区别。 同时,有的网页编码是UTF8 比如 http://www.douban.com/note/285271214/ (PS.貌似豆瓣整个就是python写的)。linux中的汉字的UTF-8编码的。 下面说一下汉字在内存中的表示 GBK类的编码中 一个汉字是这么表示的 /A1/8D/HA 这种东西 utf8 是 /u8fe1 这种东西
下面我们来解决编码问题,这也是我认为爬取中文网页的最麻烦的步骤。 首先,需要在源代码的第一行加入
- <!-- lang: python -->
- # -*- coding: utf-8 -*-
这一行,来保证你的程序可以认识中文,否则,像 print “你好” 这类的语句无法编译通过。 其次,由于屏幕输出和写入文件的原理不同,我有一次就是在控制台可以得到正确结果,但是输出到文件就有问题,所以需要在文件头部加入下面三句话
- <!-- lang: python -->
- import sys
- reload(sys)
- sys.setdefaultencoding('utf8')
汉字就是以字母和数字形式存在字符串中,用字符串的 .decode() 函数就可以实现解码,.encode()函数实现编码 重新输出 <!-- lang: python --> print f.read().lower().decode('gbk')
即可得到正确的汉字,同理,UTF-8编码的就 .decode('utf8')即可
如果我们爬的不是同一个网站下的网页,网址列表中有UTF8编码的,也有GBK编码的怎么办?使用try函数 try:
print s.decode('utf8')
except:
print s.decode('gb2312')
try和except 与 if else 的区别是,try不成功不会报错跳出,会转向执行except,而if else没有这个功能
现在网页的全部信息我们已经得到,下面的任务就是提取一些东西。 比较简单的,提取全部中文
- <!-- lang: python -->
- s=f.read().lower().decode('gbk')
- zs=''
- for item in s:
- if item in r'''0123456789{}%abcdefghijklmnopqrstuvwxyz'<>()?$+:&;|#!/"=-_.''':
- continue
- zs+=item
- print zs
三个单引号中的字符串表示要去掉的东西。不过有很多行,乱七八糟的。 当然这是非常粗暴的方法。
利器就是正则表达式,http://www.jb51.net/tools/zhengze.html 这是非茶馆你有名的一篇教程。python中用re包,正则表达式非常厉害,功能也很多,我只举一个简单的例子 在头部加入import re
- <!-- lang: python -->
- p=re.compile("\s+")
- ns=re.sub(p,'',s)
- print ns
这段话执行的是去掉所有空白字符 \t \n等 在这段话的基础上找所有汉字就是都连一起的了。 re.compile 是漏斗,起过滤的功能 <!-- lang: python --> ptitle="<title>.*?</title>" title=re.search(ptitle,ns) try: print title.group().decode("gb2312").strip("</title>") except: try: print title.group().decode("utf-8").strip("</title>") except: print ' None'
ptitle就是正则表达式, re.search是查询 这段话执行的结果是找到源文件中title标签中的内容。同理也可以找到其他标签中的内容。正则表达式的具体写法请参看上面的链接。
正则表达式的功能十分强大,可以提取出来任何你想要的东西,但是缺点就是太麻烦了。 我们使用beautifulsoup包来代替自己手写的正则表达式的操作。
在头部加入 <!-- lang: python --> from bs4 import BeautifulSoup 导入 beautifulsoup包 下面是一个完整的程序
- <!-- lang: python -->
- # -*- coding: utf-8 -*-
- import urllib2
- import sys,re
- from bs4 import BeautifulSoup
- reload(sys)
- sys.setdefaultencoding('utf8')
- f=urllib2.urlopen('http://military.people.com.cn/n/2013/0705/c1011-22087628.html')
- s=f.read().lower().decode('gbk')
- soup = BeautifulSoup(s)
- print soup.title
- newstext=soup.find(id="p_content")
- ss=''
- for item in str(newstext):
- if item in r'''0123456789{}%abcdefghijklmnopqrstuvwxyz'<>()?$+:&;|#!/"=-_.''':
- continue
- ss+=item
- print ss
beautifulsoup返回的是一个soup类型, 输出soup.title 即可提取出title标签,同理,也可以输出soup.description soup.keywords 详情参见beautiful的官方网站 soup.find(id="p_content")是按照标签id查找。
beautifulsoup的功能也非常强大,绝不是一篇博客能讲完的。
mechanize 是一个python模拟浏览器操作的包
下面一个程序通过使用mechanize包来完成在豆瓣电影搜索电影名字,抓取电影类型,演员,导演之类的任务。
- <!-- lang: python -->
- # -*- coding: utf-8 -*-
- import sys,string,types
- import mechanize
- #sys.stdout=open('look','w')
- file= open('list',"rb");
- for name in file:
- br = mechanize.Browser() #br是模拟的浏览器
- br.open('http://movie.douban.com/') #打开豆瓣电影页面
- br.select_form(nr=0) #选一个表
- br.form['search_text']=name.decode('utf-8') #输入要查询的电影的名字
- br.submit() #提交
- result = br.response() #返回结果
- linkss = [l for l in br.links()] #把浏览器链接加入linkss列表中
- rr = br.follow_link(linkss[21]) #点击搜索结果的第一条 这个21是尝试出来的,因为上面还有注册等等链接
- #print rr.read()
- ttt='<span class="pl">类型:</span> ' #手动找标签,也可以返回的源文件,用beautifulsoup解析
- #print br.title()
- ss=rr.read().split('\n')
- for line in ss:
- if line.find(ttt)>0:
- print line
- br.close()
输出的结果需要进一步处理,这里就不赘述了。 上面写的都只是普通网页的文本爬取,爬新浪微博之类的需要API,或者有其他的黑科技,那些都是等待钻研的东西了。
另外提供两个参考链接
http://www.pythonclub.org/python-network-application/observer-spider 是一篇写的挺详细的博客
http://www.oschina.net/project/tag/64/spider?lang=25 是oschina上的一个框架(不过我觉得都太高端了,供以进一步的参考)