
很多乱码问题是编码造成的,一般对于中文网站基本是UTF-8,GB2312,可以GB18030通吃。
另一个造成乱码的原因是压缩格式,很多规模较大的网站都是以gzip的压缩格式输出页面的,所以在用BS解析之前需要先判断该网页是否经过压缩,如果经过压缩则先进行解压操作。
相关推荐:《Python教程》
代码:
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
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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^[LJg’o^=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} …
|
首先想到编码问题
1 | isinstance(html, str) == True
|
并且页面的编码确定为 GBK,那么
1 | html.decode( 'gbk' ).encode( 'utf-8' )
|
就可以将机器码以 gbk 解码,再重新以 utf-8 编码,就可以得到正确的文本。可是收到这样的提示:
1 | UnicodeDecodeError: ‘gbk’ codec can’t decode bytes in position 1-2: illegal multibyte sequence
|
可能是以 gzip 压缩格式输出造成的乱码,于是尝试通过 zlib 解压缩。
1 2 | import zlib
html = zlib.decompress(html)
|
可是却得到下面的错误:
1 | 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 呢?最终代码如下:
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”的数据流就不会去对其解压缩。