平時我們使用 requests 時, 通過兩種方法拿到響應的內容:
import requests
response = requests.get(
'')a = response.content # type: bytes
b = response.text # type: str
其中response.text
是我們常用的.
requests 的作者在注釋中這樣寫道:
意思是說,response.text
是以response.content
(位元組碼) 和 encoding (編碼) 為根據, 將位元組碼轉換成 str 返還給我們的.
換句話說就是,response.text
自動幫我們把從伺服器獲得的位元組流轉換成 str 返還給我們, 為我們減去了各種網頁編碼帶來的 「亂碼」 的問題.
那麼為什麼response.text
仍然有時候會出現亂碼的問題呢?
這就是本文要解釋的問題, 接下來我會乙個例子說明.
這是乙個有 「問題」 的網頁:
在瀏覽器中開啟它, 顯示的是正常的:
而通過response.text
檢視就會出現亂碼.
首先, requests 在計算response.text
的時候, 會先看響應的 http header 中是否提供了 encoding 資訊. 我們通過response.encoding
可以拿到這個值. 可以看到, 確實是有的, 是 「iso-8859-1」.
按理來說, 網頁已經告訴我們, 它用的是 「iso-8859-1」 編碼, 於是 requests 就信以為真, 拿 「iso-8859-1」 來解析位元組流, 轉換為字串, 於是我們就看到 response.text 的亂碼了 - 問題就出在,網頁告訴了爬蟲乙個錯誤的編碼資訊.
那麼我們提出新的思路, 如果我們不使用 http header 提供的 encoding, 而採用其他方法獲知 encoding 有沒有可能呢?
requests 確實有此方法, 不過是在 http header 提供的 encoding 為 none 時才會用. 它通過 chardet (乙個 python 第三方模組, 用來**檔案編碼) 來檢測網頁最可能用的是哪種編碼. 注意這裡是 「可能用的」, 因為 chardet 的原理就是用各種編碼來試, 直到找出乙個看起來不像是亂碼的情況.
這裡給乙個小提示, gb2312 的字符集實在是太小了, 我們最好使用它的超集 gbk 來替代, 以避免某些生僻字解碼不出來:
# result = response.content.decode(encoding='gb2312') # abandoned
result = response.content.decode(encoding=
'gbk'
)# suggest
另外還要注意的是, 在解碼的過程中, 可能會遇到字符集以外的未知標識導致解碼中斷並報錯, 新增乙個 errors 引數可以避免此問題:
result = response.content.decode(encoding=
'gbk'
, errors=
"ignore"
)# result = response.content.decode(encoding='gbk', errors="replace")
errors='ignore'
的效果如下:
erros='replace'
的效果如下:
總結一下,response.text
造成亂碼的原因不外乎兩種: 要麼是網頁提供了錯誤的編碼 (比如上例中的網頁, 明明是中文網頁卻提供了乙個純西文字符集 「iso-8859-1」), 要麼是 chardet **的編碼不當 (比如取了某個編碼的子集, 導致大量生僻字顯示為亂碼).
了解了這些以後, 我們就有辦法自己動手, 解決亂碼了.
import requests
defget_text
(resp)
:# 優先使用 chardet **的 encoding, 其次使用 http header 提供的 encoding
if source_encoding is
none
:# 說明是二進位制檔案, 比如 pdf, jpg 之類的
raise exception
elif source_encoding ==
'gb2312'
: source_encoding =
'gbk'
return resp.content.decode(source_encoding, errors=
"ignore"
)# 測試 "問題" 網頁
url =
''response = requests.get(url)
text = get_text(response)
# | text = response.text # 不用這個了
# 儲存為檔案
with
open
('result.html'
,'w'
, encoding=
'utf-8'
)as f:
f.write(text)
爬蟲編碼問題
在獲取網頁時會遇到各種各樣的編碼問題,我們有不同的編碼方式,但是在使用beautifulsoup時,他有自動檢測編碼的功能,但是這樣遍歷一遍,知道編碼也是乙個很慢的過程。而且依然有可能出錯。因此我們可以在例項化beautifulsoup時,加上編碼規則,這樣就可避免錯誤。首先我們先檢視爬蟲的頁面的編...
Python爬蟲request庫出現問題如何解決?
1 requests異常情況 在進行網路訪問時,經常會遇到各種錯誤的情況發生,requests庫的主要異常情況如下 requests.urlrequired url缺失異常 requests.toomanyredirects 超過最大重定向次數,產生重定向異常 requests.connection...
Python爬蟲 Request模組
文章說明了request模組的意義,且強調了request模組使用更加方便。接下來介紹幾種常用的request操作,並且會在後續補充說明一些特定用法。匯入檔案 import requests一 請求 右邊為請求語句,返回值為response回應 r requests.get r requests.p...