Python爬虫总结(二)常见数据类型
上一篇我们简单介绍了如何用Python发送 http/https 请求获取网上数据,从web上采集回来的数据的数据类型有很多种,主要有:
- 放在HTML里.
- 直接放在javascript里.
- 放在JSON里.
- 放在XML里.
注意:这里很多概念都是web前端开发里的,因为我们采集的大多数数据都来自web,因此了解一些前端知识还是挺有必要的.
下面我简单介绍下各种数据类型,并结合一些实例介绍它们的解析方法.
数据类型
放在HTML里
HTML即超文本标记语言,目前大多数网页都是HTML写的,自然很多数据被存放在HTML中.
直接放在javascript里
javascript 作为最主要的前端开发脚本被广泛使用,很多关键数据被直接放到javascript 脚本里.
放在JSON里
json即JavaScript 对象表示法.它其实是独立于语言的,常常在javascript存储或异步传输(后面我们会详细讨论这个)的时候被用到.因为javascript 在web前端开发中的大量运用,json也成了web主要数据类型之一.
放在XMl里
XML指可扩展标记语言,被设计用来传输和存储数据。很多javascript 程序员喜欢用xml传输数据,而且有的网页是直接用XML编写的(而不是HTML).
实例
实例1-豆瓣电影"正在热映"信息采集
访问豆瓣电影的热门电影(图1)https://movie.douban.com/:
图1
在浏览器上右击->查看源代码(view page source):
图2
上一篇文章的爬虫程序爬取的豆瓣电影的页面就是图2这些HTML标签.
现在假如我们要采集"正在热播"的电影的电影名称,上映年份和电影评分信息.首先就要定位这些信息.定位的方法主要有:正则表达式法,xpath定位法和Beautifulsoup定位法.
正则表达式法:
.对正则表达式不太了解的同学可以查看这里:正则表达式.该定位方法是最万能的方法,不仅可以定位豆瓣电影这种"中规中矩"的把信息放到HTML内的数据,而且对其它一些:放在javascript里的,放在json里的,放在xml里的,注释信息等等也都可以处理.但缺点是写一个能正确的正则表达式较为困难,一般需要反复调试.
下面是我用正则表达式定位电影名称,上映年份,电影评分信息(图3是运行结果).
import urllib2,re url ="https://movie.douban.com/" page = urllib2.urlopen(url).read() result = re.findall(‘<li class="ui-slide-item" data-title="(.+?)" data-release="(\d+?)" data-rate="([0-9.]+?)"‘,page) for item in result: print ‘Movie:‘,item[0],‘Date:‘,item[1],‘Score:‘,item[2]
图3:运行结果
XPath定位法:
XPath 是一门在 XML 文档中查找信息的语言,但其实它也可以用来查找HTML信息.它可以借助XPth强大的语法很方便的定位元素,而且现在很多浏览器都有插件让你很容易的就得到元素的XPath路径,如firefox的firebug插件.
下面是用XPath定位的代码:
import urllib2,re from lxml import etree url ="https://movie.douban.com/" page = urllib2.urlopen(url).read() temp = etree.HTML(page) results = temp.xpath("//li[@class=‘ui-slide-item‘]") for item in results: print ‘Movie:‘,item.get(‘data-title‘),‘Date:‘,item.get(‘data-release‘),‘Score:‘,item.get(‘data-rate‘)
BeautifulSoup定位法:
BeautifulSoup是一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖析树(parse tree)。 它提供简单又常用的导航(navigating),搜索以及修改剖析树的操作。它可以大大节省你定位信息的时间。因为它是第三方库,因此它需要用专门安装.它的安装方法和文档见:https://www.crummy.com/software/BeautifulSoup/bs4/doc/
下面是用BeautifulSoup定位的代码:
import urllib2,re from bs4 import BeautifulSoup url ="https://movie.douban.com/" page = urllib2.urlopen(url).read() soup = BeautifulSoup(page,"html.parser") results = soup.find_all("li",class_=‘ui-slide-item‘) for item in results: print ‘Movie:‘,item.get(‘data-title‘),‘Date:‘,item.get(‘data-release‘),‘Score:‘,item.get(‘data-rate‘)
XPath方法和BeautifulSoup方法定位元素相当方便,但是它们不能定位直接放在在javascript中的数据,注释数据等不在XML HTML内的信息.实际解析定位过程中往往采取上面几种方法结合的方式.如:先用正则表达式从js代码中匹配出html数据,然后再用XPath或BeautifulSoup 解析处理.
注意:BeautifulSoup输出是unicode编码,如果你希望结果是utf-8编码,记得转码.
实例2-采集微信公众号人民日报最近所发文章的标题
链接:
如图3 ,它下面所列的文章信息并不在HTML标签里,而是以Json数据类型放在js 代码里了.
图4
这种情况也非常常见.解决思路是先用正则表达式把json数据取出来,然后在用python 的json库解析json数据.下面是代码:
import urllib2,json,re url ="http://mp.weixin.qq.com/profile?src=3×tamp=1469945371&ver=1&signature=bSSQMK1LY77M4O22qTi37cbhjhwNV7C9V4aor9HLhAsvBDAQSoh7EBJeIvjGvbRZ7ic-eOFX2Fq4BSZtCO0Syg==" page = urllib2.urlopen(url).read() result = re.findall("var msgList = ‘(\{\S+\})‘;",page) temp = re.sub(""", ‘"‘,result[0]) json_data = json.loads(temp,encoding=‘utf-8‘) for item in json_data[‘list‘]: print item[‘app_msg_ext_info‘][‘title‘]
运行结果:
图4
其它说明
存在XML中的数据类型的处理方法和存在HTML中的处理方法相同,可以参考实例1的操作步骤这里就不在赘述.
下面主要提醒大家一定要注意解析过程中的编码问题.
编码问题
在解析的过程中要注意编码问题,因为网页有UTF-8 编码的,也有GBK编码的,还有GB2312等等. 如果编码问题没有处理好,很有可能会导致输入输出异常,正则表达式匹配错误等问题.我的解决办法是坚持一个中心思想: "不管你是什么编码来的,到解析程序统一换成utf-8编码".比如有的网页是GBK编码,在处理之前我会先对它进行一个转码操作:
utf8_page = GBK_page.decode("GBK").encode("utf8")
同时在代码的初始化位置(或者是最开始部分)我一般会加上以下代码:
import sys reload(sys) sys.setdefaultencoding(‘utf8‘)
同时代码文件的编码方式也要保证是utf-8.
这样处理调理比较清晰,统一.不会出现一个utf-8的正则表达式和一个GBK的字符串做匹配最后啥也匹配不出来.或者输出的数据即有utf8编码的字符串,又有GBK编码的字符串导致IO错误.
如果事先不知道网页是什么编码,建议使用python 的第三方包 chardet:https://pypi.python.org/pypi/chardet/它可以自动帮你识别出网页的编码.用法是:
import chardet import urllib2 #可根据需要,选择不同的数据 TestData = urllib2.urlopen(‘http://www.baidu.com/‘).read() print chardet.detect(TestData)
运行结果是:
准确的判断出百度的编码方式是utf-8.
总结
今天介绍了常见的数据类型,并结合实例介绍了:正则表达式法,XPath定位法,BeautifulSoup定位法三种定位方法.最后还介绍了爬虫初学者经常头疼的编码问题,介绍了Chardet 工具.下一篇我准备介绍一下AJAX异步加载的处理办法和常见的反爬虫策略及其应对方法.