Python爬虫总结(二)常见数据类型及其解析方法

Python爬虫总结(二)常见数据类型

上一篇我们简单介绍了如何用Python发送 http/https 请求获取网上数据,从web上采集回来的数据的数据类型有很多种,主要有:

  1. 放在HTML里.
  2. 直接放在javascript里.
  3. 放在JSON里.
  4. 放在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-采集微信公众号人民日报最近所发文章的标题

链接:

http://mp.weixin.qq.com/profile?src=3&timestamp=1469945371&ver=1&signature=bSSQMK1LY77M4O22qTi37cbhjhwNV7C9V4aor9HLhAsvBDAQSoh7EBJeIvjGvbRZ7ic-eOFX2Fq4BSZtCO0Syg==

如图3 ,它下面所列的文章信息并不在HTML标签里,而是以Json数据类型放在js 代码里了.

图4

 

这种情况也非常常见.解决思路是先用正则表达式把json数据取出来,然后在用python 的json库解析json数据.下面是代码:

import urllib2,json,re

url ="http://mp.weixin.qq.com/profile?src=3&timestamp=1469945371&ver=1&signature=bSSQMK1LY77M4O22qTi37cbhjhwNV7C9V4aor9HLhAsvBDAQSoh7EBJeIvjGvbRZ7ic-eOFX2Fq4BSZtCO0Syg=="
page = urllib2.urlopen(url).read()
result = re.findall("var msgList = '(\{\S+\})';",page)
temp = re.sub("&quot;", '"',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异步加载的处理办法和常见的反爬虫策略及其应对方法.

posted @ 2016-07-31 19:00  sfeiqiang  阅读(3748)  评论(0编辑  收藏  举报