2010-12-22 19 views
12

我感到有點驚訝,它是如此複雜,以獲得與Python的網頁字符集。我錯過了一個方法嗎? HTTPMessage具有負載功能,但不是這樣。什麼是一個很好的,可靠的簡單方法來獲取網頁的字符集?

>>> google = urllib2.urlopen('http://www.google.com/') 
>>> google.headers.gettype() 
'text/html' 
>>> google.headers.getencoding() 
'7bit' 
>>> google.headers.getcharset() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: HTTPMessage instance has no attribute 'getcharset' 

因此,您必須獲取標題並將其拆分。兩次。

>>> google = urllib2.urlopen('http://www.google.com/') 
>>> charset = 'ISO-8859-1' 
>>> contenttype = google.headers.getheader('Content-Type', '') 
>>> if ';' in contenttype: 
...  charset = contenttype.split(';')[1].split('=')[1] 
>>> charset 
'ISO-8859-1' 

對於這樣一個基本功能,這是一個令人驚訝的數量的步驟。我錯過了什麼嗎?

+2

由RFC 2616(HTTP1.1)`的「字符集」參數與某些媒體類型一起使用來定義數據的字符集(3.4節)。當發件人未提供明確的字符集參數時,「文本」類型的媒體子類型在通過HTTP接收時定義爲具有默認字符集值「ISO-8859-1」。「作爲默認的旁註是ASCII。 – plundra 2010-12-22 15:05:21

+0

@plundra:嗯,ISO-8859-1是ASCII的超集,但你是對的 - 它是一種不同的編碼。 – Piskvor 2010-12-22 15:07:10

+0

@Piskvor:如果有人使用s上面的charset。解碼()例如,事情將中斷(與頁面發送ISO-8859-1,並依靠隱式) – plundra 2010-12-22 15:11:21

回答

0

您不會錯過任何東西。它正在做正確的事情 - HTTP響應的編碼是Content-Type的子部分。

還請注意,有些頁面可能只發送Content-Type: text/html,然後通過<meta http-equiv="Content-Type" content="text/html; charset=utf-8">設置編碼 - 這是一個醜陋的黑客,雖然(在頁面作者的一部分),並不太常見。

0

我會去chardet通用編碼檢測器。

>>> import urllib 
>>> urlread = lambda url: urllib.urlopen(url).read() 
>>> import chardet 
>>> chardet.detect(urlread("http://google.cn/")) 
{'encoding': 'GB2312', 'confidence': 0.99} 

你正在做正確的,但你的做法會失敗,其中的charset宣佈meta標籤或根本未聲明的頁面。
如果你仔細觀察Chardet的來源,它有一個charsetprober/charsetgroupprober模塊可以很好地處理這個問題。

3

我做了一些研究,並用此溶液想出了:

response = urllib.request.urlopen(url) 
encoding = response.headers.get_content_charset() 

這是我會怎麼做它在Python 3。我沒有在Python 2測試,但我猜,你將不得不使用urllib2.request而不是urllib.request

這是它是如何工作的,因爲官方的Python文檔沒有很好地解釋它:urlopen的結果是一個http.client.HTTPResponse對象。該對象的headers屬性是一個http.client.HTTPMessage對象,該對象根據文檔「使用email.message.Message類實現」,該類具有名爲get_content_charset的方法,該方法嘗試確定並返回響應的字符集。

默認情況下,這個方法返回None如果無法確定字符集,但你可以通過傳遞一個failobj參數,而不是覆蓋此行爲:

encoding = response.headers.get_content_charset(failobj="utf-8") 
相關問題