網站爬取時出現亂碼-強行轉碼第二招

wangchunbo發表於2020-09-10
# 這裡因為亂碼太強. 只能先get 再去執行 encoding

    # 強行轉碼第二招

    doc = get('http://localhost/tiyu/詳情頁/馬拉松跑全程是多少千米(公里)_馬拉松跑全程大約要用多長時間%20-陽光直播吧.html','')

    # 強行指定返回的資料的型別

    doc.encoding = 'GB2312' 

    # 然後再進行 beautiful 即可中文

    doc = BeautifulSoup(doc.text, 'lxml')

    print('doc: ', doc)

    if doc is None:

        return '請求當前頁面是空'+ url

ps:注意,強行指定,你可以用下面的方法,來看看你自己識別的是什麼字符集

print(resp.encoding) #檢視網頁返回的字符集型別 這裡返回ISO-8859 
print(resp.apparent_encoding) #自動判斷字符集型別 發現這裡返回 GB2312! 我們進行轉換gbk 

requests和BeautifulSoup中文編碼轉換

最近在自學用python進行網頁資料抓取,結果被中文亂碼的問題折騰了好久。網上google了各種解決方案都無法解決我遇到的問題,索性自己深入的研究了下,終於把這難題給解決了。在此梳理下整個分析過程。

一開始我的程式碼是這樣寫的:

response = requests.get('http://www.jjwxc.net/fenzhan/noyq/')soup = bs4.BeautifulSoup(response.text, "html.parser")print soup.title

執行後返回的結果中文部分都變成了亂碼。很顯然,是中文編碼在轉換過程中出現了問題。

檢視jjwxc.net的原始碼,可以得知該網站的中文編碼是gb18030

<meta http-equiv="Content-Type" content="text/html; charset=gb18030" />

查閱requestes以及BeautifulSoup的相關文件,可知requests會自動將從伺服器端獲取到的內容自動轉換成unicode, 而beauifulsoup也會將獲取到內容自動解碼成unicode。既然response.text已經是unicode形式,那麼再傳遞給beautifulsoup,是unicode->unicode之間的直接傳遞,應該不存在編碼轉換錯誤的情況,那麼為什麼最後print出來的會是亂碼呢?

於是進一步查閱requests和bs4的官方文件,發現了這樣兩段描述:

When you make a request, Requests makes educated guesses about the encoding of the response based on the HTTP headers. The text encoding guessed by Requests is used when you access r.text. You can find out what encoding Requests is using, and change it, using the r.encoding property.

Beautiful Soup uses a sub-library called Unicode, Dammit to detect a document’s encoding and convert it to Unicode. The autodetected encoding is available as the .original_encoding attribute of the BeautifulSoup object.Unicode, Dammit guesses correctly most of the time, but sometimes it makes mistakes. Sometimes it guesses correctly, but only after a byte-by-byte search of the document that takes a very long time. If you happen to know a document’s encoding ahead of time, you can avoid mistakes and delays by passing it to the BeautifulSoup constructor as from_encoding.

大意是requests和beautifulsoup都會自行猜測原文的編碼方式,然後用猜測出來的編碼方式進行解碼轉換成unicode。大多數時候猜測出來的編碼都是正確的,但也有猜錯的情況,如果猜錯了可以指定原文的編碼。
OK,那讓我們看一下requests和beautifulsoup是否猜對了原文編碼。

response = requests.get('http://www.jjwxc.net/fenzhan/noyq/')print response.encodingsoup = bs4.BeautifulSoup(response.text, "html.parser")print soup.original_encoding 執行結果:ISO-8859-1None

可以發現是由於requests這裡對原文的編碼猜錯了導致亂碼的出現,所以我們需要在response.text傳給beautifulsoup之前指定編碼:

response = requests.get('http://www.jjwxc.net/fenzhan/noyq/')response.encoding = 'gb18030'soup = bs4.BeautifulSoup(response.text, "html.parser")print soup.title

但是執行後發現輸出的結果還是亂碼。
繼續查閱上述語句的相關官方文件,發現beautifulsoup對於輸出內容的編碼方式有這樣一段介紹:

BS_encoding.png

意即beautifulsoup在輸出文字時預設以UTF-8的方式編碼,無論原文是否以它進行編碼的。如果你不希望以UTF-8的方式編碼,可以用prettify()或則encode()方式來指定編碼。
所以我們將程式碼更改下:

response = requests.get('http://www.jjwxc.net/fenzhan/noyq/')response.encoding = 'gb18030'soup = bs4.BeautifulSoup(response.text, "html.parser")print soup.title.prettify('gb18030')print soup.title.encode('gb18030') 執行結果:

可以看到兩種指定方式都可以獲得無亂碼的中文內容。
這裡再介紹下prettify()的功能,prettify()除了可以制定輸出的編碼方式,它的最主要功能是對beautifulsoup的k語法分析樹重新排版,使輸出的內容整潔易讀。這裡用一段程式碼說明:

BS_prettify.png

至此,中文亂碼的問題解決了。在查詢解決方案的過程中,我另外查了下unicode、byte、以及編碼和解碼方面的知識點。這一塊的東西解釋起來一時半會兒說不完,而且有些細節的地方我也沒完全搞懂,暫時就不賣弄了。對這塊內容感興趣的可以先看下下面這兩位大牛的文章,寫得非常通俗易懂:

blog.csdn.net/he_and/article/detai...

本作品採用《CC 協議》,轉載必須註明作者和本文連結
感謝關注 上海PHP自學中心-免費程式設計視訊教學|

相關文章