Headers設置之Accept-Encoding

本文是headers系列文章第三篇

前兩篇如下

  • Headers之User-Agent設置
  • Headers之Referer設置

我們請求網頁時,伺服器返回給我們的信息有時是經過壓縮的,只有解壓才能獲取我們想要的數據。我們先來看下面兩張圖

關註上面兩個值

  • response headers中的content-encoding
  • request headers 中的accept-encoding

content-encoding是指網頁使用了哪種壓縮方式傳輸數據給你,accept-encoding表示你發送請求時告訴伺服器,我可以解壓這些格式的數據。

二者的關係是,對方網頁會根據你發送的accept-encoding來決定用什麼格式(content-encoding)傳給你。

accept-encoding而無法獲取數據的情況我個人是沒有遇到過的,只是看到網上一些文章提到了這一點,於是研究了一下。我發現那些文章多是基於urllib庫進行的請求,而我使用requests庫請求他們請求的網頁,並不會出現他們遇到的問題。

他們的問題在於:用urllib請求時如果帶有accept-encoding,則返回的內容是經過壓縮的,而urllib還不會自動解壓縮,此時我們如果以為獲得的是源代碼本身然後去解碼、處理,就會報錯。所以這種情況下,拿到的是壓縮數據,可以使用python庫進行解壓,然後再解碼、解析網頁。另一種方法是請求時將headers中的accept-encoding欄位去除掉,即告訴網頁我不支持壓縮數據,於是網頁就會把源代碼本身的數據傳送給你,這樣不涉及解壓的問題,但是網路傳輸消耗的流量就會比傳輸壓縮內容消耗的流量大得多。

而requests與urllib的區別在於,即使返回的是壓縮數據,requests也會自動解壓縮。

接下來,為了讓讀者對此有一個更直觀的認識,我們用requests庫來演示一下content-encoding和accept-encoding值的變化情況

首先,默認情況

import requestsheaders = { user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36}r = requests.get(https://zhuanlan.zhihu.com/python-programming, headers = headers)

來看看沒有設置Accept-Encoding時默認兩個值分別是什麼

>>> r.request.headers[Accept-Encoding]gzip, deflate>>> r.headers[Content-Encoding]gzip

說明默認情況下,requests告訴對方網頁,我支持gzip和deflate這兩種壓縮方式,於是網頁響應時使用gzip方式壓縮數據傳輸給我們。

這時我們來看一下返回的數據是否正確

>>> r.text[:300]<!doctype html>
<html lang="zh" data-theme="light"><head><meta charset="utf-8"/><title data-react-helmet="true">python編程</title><meta name="renderer" content="webkit"/><meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/><meta name="force-renderi

數據是正確的,說明requests內部自己解壓了。

現在改一下請求

headers = { Accept-Encoding: , user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36}r = requests.get(https://zhuanlan.zhihu.com/python-programming, headers = headers)>>> r.headers[Content-Encoding]Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:Program FilesAnaconda3libsite-packages
equestsstructures.py", line 54, in __getitem__ return self._store[key.lower()][1]KeyError: content-encoding

我們可以看到響應里沒有content-encoding欄位了,說明返回數據時沒有經過壓縮

源代碼返回正常

>>> r.text[:300]<!doctype html>
<html lang="zh" data-theme="light"><head><meta charset="utf-8"/><title data-react-helmet="true">python編程</title><meta name="renderer" content="webkit"/><meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/><meta name="force-renderi

那些因為解壓縮而報錯,並用python解壓的文章可以看下面

  • Python 筆記六:入門爬蟲坑--網頁數據壓縮(python deflate gzip)
  • Python爬取網頁Utf-8解碼錯誤及gzip壓縮問題的解決辦法
  • 如何確定一個python爬取得網頁是否是被壓縮的?
  • python以gzip header請求html數據時,response內容亂碼無法解碼的解決方案

專欄信息

專欄主頁:python編程

專欄目錄:目錄

爬蟲目錄:爬蟲系列目錄

版本說明:軟體及包版本說明


推薦閱讀:

python爬蟲——下載ted視頻
beautifulsoup+json抓取stackoverflow實戰
使用requests+beautifulsoup爬取你想要的數據
python爬取QQ音樂

TAG:Python | 爬蟲計算機網路 | python爬蟲 |