2017-09-16 112 views
2

我解析這個網站的一個問題:http://fm4-archiv.at/files.php?cat=106刮用正確的字符編碼(蟒蛇請求+ beautifulsoup)

它含有特殊字符,如變音符號。看到這裏:enter image description here

我的鉻瀏覽器顯示的變音器正確,你可以在上面的截圖看到。然而在其他頁面(例如:http://fm4-archiv.at/files.php?cat=105)的變音符號顯示不正常,如可以在下面的截圖中可以看出: enter image description here

元HTML標記定義頁面上的下列字符集:

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

我使用python requests包獲取HTML,然後使用Beautifulsoup來刮取所需的數據。我的代碼如下:

r = requests.get(URL) 
soup = BeautifulSoup(r.content,"lxml") 

如果我打印的編碼(print(r.encoding)的結果是UTF-8。如果我通過調用r.encoding = ISO-8859-1手動將編碼更改爲ISO-8859-1cp1252當我在控制檯上輸出數據時,沒有任何更改。這也是我的主要問題。

r = requests.get(URL) 
r.encoding = 'ISO-8859-1' 
soup = BeautifulSoup(r.content,"lxml") 

仍然導致了我的Python IDE上的控制檯輸出顯示以下字符串:

Der Wildlöwenpfleger 

相反,它應該是

Der Wildlöwenpfleger 

我怎樣才能改變我的代碼來解析變音器正確嗎?

回答

1

通常,使用r.text而不是使用r.content這是接收到的字節字符串,它是使用由requests確定的編碼的解碼內容。

在這種情況下requests將使用UTF-8到到來的字節串進行解碼,因爲這是由服務器在Content-Type頭報告的編碼:然而

import requests 

r = requests.get('http://fm4-archiv.at/files.php?cat=106') 

>>> type(r.content) # raw content 
<class 'bytes'> 
>>> type(r.text)  # decoded to unicode 
<class 'str'>  
>>> r.headers['Content-Type'] 
'text/html; charset=UTF-8' 
>>> r.encoding 
'UTF-8' 

>>> soup = BeautifulSoup(r.text, 'lxml') 

這將修復「Wildlöwenpfleger」的問題, ,頁面的其他部分,然後開始打破,例如:

>>> soup = BeautifulSoup(r.text, 'lxml')  # using decoded string... should work 
>>> soup.find_all('a')[39] 
<a href="details.php?file=1882">Der Wildlöwenpfleger</a> 
>>> soup.find_all('a')[10] 
<a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon �bergeben. Auf Streifz�gen durch die Popliteratur st��t Hermes auf deren gro�e Themen und h�rt mit euch quer. In der heutige">Salon Hermes (6 files) 

顯示,「Wildlöwenpfleger」是固定的,但現在「übergeben」等人在第二個鏈接被打破。

似乎在一個HTML文檔中使用了多種編碼。第一個環節使用UTF-8編碼:

>>> r.content[8013:8070].decode('iso-8859-1') 
'<a href="details.php?file=1882">Der Wildlöwenpfleger</a>' 

>>> r.content[8013:8070].decode('utf8') 
'<a href="details.php?file=1882">Der Wildlöwenpfleger</a>' 

但第二個鏈接使用ISO-8859-1編碼:

>>> r.content[2868:3132].decode('iso-8859-1') 
'<a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon übergeben. Auf Streifzügen durch die Popliteratur stößt Hermes auf deren große Themen und hört mit euch quer. In der heutige">Salon Hermes (6 files)\r\n</a>' 

>>> r.content[2868:3132].decode('utf8', 'replace') 
'<a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon �bergeben. Auf Streifz�gen durch die Popliteratur st��t Hermes auf deren gro�e Themen und h�rt mit euch quer. In der heutige">Salon Hermes (6 files)\r\n</a>' 

顯然,這是不正確相同的HTML文檔中使用多種編碼。除了聯繫文檔的作者並要求更正外,您無法輕鬆地處理混合編碼。也許你可以在處理數據時對數據運行chardet.detect(),但這並不令人愉快。

0

我剛剛發現兩個解決方案。你可否確認?

Soup = BeautifulSoup(r.content.decode('utf-8','ignore'),"lxml") 

Soup = BeautifulSoup(r.content,"lxml", fromEncoding='utf-8') 

在下面的例子中輸出兩個結果:

Der Wildlöwenpfleger 

編輯: 我只是奇怪,爲什麼這些工作,因爲r.encoding導致UTF-8反正。這告訴我,請求無論如何處理的數據爲UTF-8數據。因此,我不知道爲什麼.decode('utf-8','ignore')fromEncoding='utf-8'導致所需的輸出?

編輯2: 好吧,我想我現在明白了。 .decode('utf-8','ignore')fromEncoding='utf-8'表示實際數據被編碼爲UTF-8,並且Beautifulsoup應該解析它,將其作爲UTF-8編碼的數據處理,實際上是這種情況。

我假設requests正確處理它爲UTF-8,但BeautifulSoup沒有。因此,我必須做這個額外的解碼。