python以gzip header請求html資料時,response內容亂碼無法解碼的解決方案
阿新 • • 發佈:2019-01-05
1. 問題背景
在使用urllib2 module抓取web資料時,如果希望使用如何request header,減少傳輸時資料量。返回的資料,是經過gzip壓縮的。直接按照 content.decode(“utf8”), 解碼會出現異常,並且也無法檢測網頁資料的實際編碼型別。
2. 問題分析
因為http請求中,如果在request header包含”Accept-Encoding”:”gzip, deflate”, 並且web伺服器端支援,返回的資料是經過壓縮的,這個好處是減少了網路流量,由客戶端根據header,在客戶端層解壓,再解碼。urllib2 module,獲取的http response資料是原始資料,沒有經過解壓,所以這是亂碼的根本原因。
3. 解決方案
3.1 Request header移除”Accept-Encoding”:”gzip, deflate”
最快的方案,能直接得到可解碼的資料,缺點是,傳輸流量會增加很多。
3.2 使用zlib module,解壓縮,然後解碼,得到可讀的明文資料。
這也是本文使用的方案
4. 原始碼解析
程式碼如下, 這是一個典型的模擬form表單,post方式提交請求資料的程式碼,基於python 2.7
,
程式碼塊
程式碼塊語法遵循標準markdown程式碼
#! /usr/bin/env python2.7
import sys
import zlib
import chardet
import urllib
import urllib2
import cookielib
def main():
reload( sys )
sys.setdefaultencoding('utf-8')
url = 'http://xxx.yyy.com/test'
values = {
"form_field1":"value1",
"form_field2":"TRUE",
}
post_data = urllib.urlencode(values)
cj=cookielib.CookieJar()
opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
headers ={"User-agent" :"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0",
"Referer":"http://xxx.yyy.com/test0",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language":"en-US,en;q=0.5",
"Accept-Encoding":"gzip, deflate",
"Connection":"keep-alive",
# "Cookie":"QSession=",
"Content-Type":"application/x-www-form-urlencoded",
}
req = urllib2.Request(url,post_data,headers)
response = opener.open(req)
content = response.read()
gzipped = response.headers.get('Content-Encoding')
if gzipped:
html = zlib.decompress(content, 16+zlib.MAX_WBITS)
else:
html = content
result = chardet.detect(html)
print(result)
print html.decode("utf8")
if __name__ == '__main__':
main()
使用本指令碼需要以下環境
- Mac OS 10.9+
- Python 2.7.x
目錄
用 [TOC]
來生成目錄: