參考:https://segmentfault.com/q/1010000003042693
使用python的urllib2抓取得到的網頁時,有時會遇到這樣尷尬的情況:
原因是返回的網頁進行了壓縮,這裏是gzip壓縮。
要正確獲取網頁內容,就要對它進行解壓處理即可。解壓處理可使用python的gzip和StringIO庫解決:
headers = {'User-agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36',
'Referer': urlparse.urlparse(url).netloc,
'Accept-encoding':'gzip'} #加入用戶代理頭部,應對一些網站的反爬蟲機制
request = urllib2.Request(url,headers=headers)#去除url中‘#’後的內容
htmlbody = urllib2.urlopen(request).read()
html = gzip.GzipFile(fileobj = StringIO.StringIO(htmlbody),mode = "r").read()
這樣經過gzip壓縮過的網頁就能正確讀取了。
這裏需要了解的是:
在瀏覽器中 Accept-Encoding:gzip,
deflate, sdch
在告訴網站瀏覽器支持 gzip
, deflate
, sdch
這三種壓縮方式。也就是說這不代表網站支持的壓縮方式,而是代表瀏覽器支持的壓縮方式。
網站會選擇其中一種支持的壓縮方式返回,壓縮方式爲 Content-Encoding
的值。瀏覽器會根據這個值來選擇對應的解壓方式。
也就是說:
用戶代理頭部設置了‘Accept-encoding’爲gzip,則支持該壓縮的網站會將網頁進行該壓縮返回壓縮過的網頁,而不支持的網頁就不會進行壓縮。
通過分析HTTP的響應頭中是否存在'Content-Encoding'=gzip,就可得知該網址是否支持,從而確定對應的網頁讀取方式,即讀取時是否要進行解壓。
改進後的代碼如下:
headers = {'User-agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36',
'Referer': urlparse.urlparse(url).netloc,
'Accept-encoding':'gzip'} #加入用戶代理頭部,應對一些網站的反爬蟲機制
request = urllib2.Request(url,headers=headers)#去除url中‘#’後的內容
html = urllib2.urlopen(request).read()
fEncode = urllib2.urlopen(request).info().get('Content-Encoding')
if fEncode == 'gzip':
html = gzip.GzipFile(fileobj = StringIO.StringIO(html),mode = "r").read()
return html