使用bs4和urllib2抓取网页,都是坑


今天折腾了一天使用python抓取新浪门户上的新闻,其实难倒是不难,关键就是在下面三个问题上卡住了。

问题一:新浪新闻返回gzip格式的数据

一开始read data之后,希望使用decode将读取到的字符串转化为unicode字符串,显然这是python处理乱七八糟字符串的常用套路。但是一上午都在各种encode error,以为是返回的数据中包含了乱七八糟的字符导致的。后来想起来自己在实习的时候用过别人的代码抓取网页内容,经过了一个gzip的过程,于是才想起来很有可能是服务器返回的数据使用gzip格式进行压缩。

于是当你接收到服务器返回的数据后,你判断一下”Content-Encoding”是否为’gzip’格式,如果是的话就要用gzip进行解压;否则的话则直接读取response的数据即可。可以参见下面的代码。

#coding=utf8
import urllib2
from StringIO import StringIO
from bs4 import BeautifulSoup
import gzip

def loadData(url):
    request = urllib2.Request(url)
    request.add_header('Accept-encoding', 'gzip')
    response = urllib2.urlopen(request)
    print response.info().get('Content-Encoding')
    if response.info().get('Content-Encoding') == 'gzip':
        print 'response data is in gzip format.'
        buf = StringIO(response.read())
        f = gzip.GzipFile(fileobj=buf)
        data = f.read()
    else:
        data = response.read()
    return data
    
if __name__ == '__main__':
    page = loadData('http://news.sina.com.cn/')
    soup = BeautifulSoup(page, from_encoding='GB18030')
    print soup.prettify().encode('GB18030')

问题二:字符串编码问题

通常来说包含中文的网页,我们大都可以认为采用了GB系列的编码,其主要有三种分别是GB2312、GBK和GB18030三种,从时间发展先后来说GB2312 < GBK <GB18030,通常来说包含的字符的个数也是这个关系。如果说在使用GB2312时用到了属于GBK中的字符,那么我们可以在创建BeautifulSoup的时候指定from_encoding=’GBK’,当然由于GB18030中可编码的字符最多,可以不管网页使用的是GB2312或者是GBK编码,都可以一律在构造BeautifulSoup的时候指定from_encoding=’GB18030’。

另外在python中处理字符编码的时候,我们通常的套路是读入的时候要先将字符串decode到unicode,输出的时候我们进行encode,这样保证在内存中处理的都是unicode类型的字符串。

 

问题三:BeautifulSoup的使用

BeautifulSoup是方便高效的处理HTML或XML格式的内容的package,具体只会用一点点。可以参考Beautiful Soup的官方文档http://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html


吐槽一下,人生不如意十有八九,希望现在的不如意是为以后的生活攒人品吧。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。