码迷,mamicode.com
首页 > 编程语言 > 详细

[python]乱码:python抓取脚本

时间:2014-08-26 17:07:06      阅读:284      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   io   ar   数据   

参考:

http://www.zhxl.me/1409.html

使用 python urllib2 抓取网页时出现乱码的解决方案
发表回复
这里记录的是一个门外汉解决使用 urllib2 抓取网页时遇到乱码、崩溃、求助、解决和涨经验的过程。这类问题,事后看来只是个极小极小的坑,不过竟然花去很多时间,也值得记录一下。过程如下:
目标:

抓取 http://sports.sina.com.cn/g/premierleague/index.shtml
代码:

1
2
3
4
5
6
# coding: u8
import urllib2
url = "http://sports.sina.com.cn/g/premierleague/index.shtml"
response = urllib2.urlopen(url)
html = response.read()
print html
输出:

w?83′?L/J
.uV?[w5;:S煝{7l!Zp8-y?=ePUs?;__Zj
::]K?
eY?kV%IBUVY”*’)?S.
JT>”TTZk+!x*)ld2I,kUU?/kXjjkHI U0n2}jUS?”>!pj^[?go^=Nq?7n|57yy\ul
j=9T,g/t0?7^o|v}>8=7?!tp??gFS?zd~`MuC%U2\ f?Vq?7~2~?lE=}M}Xwo}us>?*zpS:7O?~чb=
HK!s?inQR}@TsY|,#b\d+#yM@qaRTPVNw
?[((tGP,A$O/EXP)oNgA\`Z
4
eL7?Vn+
?eR fT`&W?bV
f{
j_p@-@[Ib_?CZ!4O1C,?hy b0W(?Z?V5-?X)5{EkvXÝN (PPUCk?? j(
V3{Z!LOOP+LP%WPL!\=! @XD8?jpT,W+#we~? {CBo@_Y+ijp;^,=(h :NxH|Ar]-|Bkq<
?+}.?lt.)cptRXJ4CJ?Bv@BXdP&6dógsR^=/fb@s#m} uZh.V80_)$.1W
hS*zQJÑ|?{nIPa±a#?L<SA
%^yg2*\fxJhQh_FBK(c%cBKwaHeRB 8w6<?K @.k*[k|^_¹BV;,pu]24Y
Bw?Cm3`>5#FzFG-%?
W0A{T?#u4@e24?*:*6?t&XGe@dc%c?h|?y$HhGv3s$(Y)sYMvE@lC(.tk?6K(E;Op1?:
D6wО?fO&zqZ3Z>0MC{?i#.
tP?u-u-t38X Wt2h!.>9;TVKrj_$yABZ?6.?I\yK:¬
s#lhsxzb=INse/FUad4H3lnHo0T^”j*]yfrMY!?-#I(YVaΡ@1kE?2=qRt?h@y@(GX)I-Z$lNX,vg^~cE
/虬&jz=АUdY__\FGA} …
首先想到编码问题,参考了《也谈Python的中文编码处理》一文 ,感觉基本明白怎么回事儿了,按理说

1
isinstance(html, str) == True
并且页面的编码确定为 GBK,那么

1
html.decode(gbk).encode(utf-8)
就可以将机器码以 gbk 解码,再重新以 utf-8 编码,就可以得到正确的文本。可是收到这样的提示:

UnicodeDecodeError: ‘gbk’ codec can’t decode bytes in position 1-2: illegal multibyte sequence
经过在 v2ex 求助,以及反复折腾了一下发现得到的果然是 gzip 过的乱码,于是尝试通过 zlib 解压缩

1
2
import zlib
html = zlib.decompress(html)
可是却得到下面的错误

zlib.error: Error -3 while decompressing data: incorrect header check
无奈,只得用 gzip 库和 StringIO 库绕路解决

1
2
3
import gzip, StringIO
html = gzip.GzipFile(fileobj=StringIO.StringIO(html), mode="r")
html = html.read().decode(gbk).encode(utf-8’)
终于得到了正确的内容和正确的编码~ ^^

问题到这里就解决了,可是对于不能直接使用简洁的 zlib 库表示很不甘心,毕竟根据 python 的文档 gzip 库也是调用 zlib 来解压的,为什么不直接用 zlib 呢?功夫不负有心人,最后终于在 StackOverflow 上找到了答案。于是最终代码如下:

1
2
3
4
5
6
7
8
request = urllib2.Request(url)
request.add_header(Accept-encoding, gzip)
opener = urllib2.build_opener()
response = opener.open(request)html = response.read()
gzipped = response.headers.get(Content-Encoding)
if gzipped:
    html = zlib.decompress(html, 16+zlib.MAX_WBITS)
print html
代码里在 request header 中默认加入了接受 gzip,服务器会优先返回 gzip 后的页面,这样极大减少数据流的大小,绝大多数服务器都是支持 gzip 的。之后对于意外情况,也加入了对 response header 的判断,对于不包含“Content-Encoding”的数据流就不会去对其解压缩。这样看上去妥妥的了,但其实还是会有很多意外状况,超出这篇的范围,这里就不涉及了。

后记,后来才知道这是一个很常见的坑,出于对防止抓取的考虑,部分网站采取了各种措施。例如:对于没有指定 Accept-Encoding 的请求也会返回 gzip 过的内容;会验证 Request Header 的 User-Agent 和 Referer 甚至 cookies 之类的。对于抓取感兴趣的可以继续阅读《用Python抓取网页的注意事项》,网页抓取虽然是个很成熟的领域,但门外汉面临诸多未知的挑战,唯有多读多做多积累才好。

 

[python]乱码:python抓取脚本

标签:style   blog   http   color   os   使用   io   ar   数据   

原文地址:http://www.cnblogs.com/silenceli/p/3937504.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!