爬蟲編碼問題詳解 requests

2021-09-27 09:26:45 字數 2921 閱讀 3889

平時我們使用 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...