2011-04-11 41 views
3

我正在使用Scrapy和Python(作爲Django項目的一部分)使用德語內容刮取網站。我已經安裝了libxml2作爲Scrapy選擇器的後端。Scrapy XPath選擇器文本的Unicode和UTF-8編碼問題

如果我通過選擇器提取字'Hüftsitz'(這是它如何顯示在網站上),我得到:u'H\ufffd\ufffdftsitz'(Scrapy XPath選擇器返回Unicode字符串)。

如果我把它編碼成UTF-8,我得到:'H\xef\xbf\xbd\xef\xbf\xbdftsitz'。如果我打印,我得到'H??ftsitz'這是不正確的。我想知道爲什麼會發生這種情況。網站上的character-set設置爲UTF-8。我正在用sys.getdefaultencoding設置爲UTF-8的Python外殼測試上述內容。使用Django應用程序將來自XPath選擇器的數據寫入具有UTF-8字符集的MySQL數據庫,我看到了相同的行爲。

我可以忽略一些明顯的東西嗎?任何線索或幫助將不勝感激。

回答

3

非常感謝您的回答,John和Steven。你的回答讓我思考不同,這使我找到了問題的根源,也是一個可行的解決方案。

我是用下面的測試代碼的工作:

import urllib 
import urllib2 
from scrapy.selector import HtmlXPathSelector 
from scrapy.http import HtmlResponse 

URL = "http://jackjones.bestsellershop.com/DE/jeans/clark-vintage-jos-217-sup/37246/37256" 

url_handler = urllib2.build_opener() 
urllib2.install_opener(url_handler) 

handle = url_handler.open(URL) 
response = handle.read() 
handle.close() 

html_response = HtmlResponse(URL).replace(body=response) # Problematic line 
hxs = HtmlXPathSelector(html_response) 

desc = hxs.select('//span[@id="attribute-content"]/text()') 
desc_text = desc.extract()[0] 
print desc_text 
print desc_text.encode('utf-8') 

的Scrapy外殼內,當我提取的描述數據,就出來罰款。它讓我有理由懷疑我的代碼中出現了問題,因爲在pdb提示符下,我看到了提取數據中的替換字符。

我通過Scrapy文檔拍得Response class和調整上面這個代碼:

import urllib 
import urllib2 
from scrapy.selector import HtmlXPathSelector 
from scrapy.http import HtmlResponse 

URL = "http://jackjones.bestsellershop.com/DE/jeans/clark-vintage-jos-217-sup/37246/37256" 

url_handler = urllib2.build_opener() 
urllib2.install_opener(url_handler) 

handle = url_handler.open(URL) 
response = handle.read() 
handle.close() 

#html_response = HtmlResponse(URL).replace(body=response) 
html_response = HtmlResponse(URL, body=response) 
hxs = HtmlXPathSelector(html_response) 

desc = hxs.select('//span[@id="attribute-content"]/text()') 
desc_text = desc.extract()[0] 
print desc_text 
print desc_text.encode('utf-8') 

我所做的更改與html_response = HtmlResponse(URL, body=response)更換線html_response = HtmlResponse(URL).replace(body=response)。這是我的理解,replace()方法是從編碼的角度以某種方式改變特殊字符。

如果有人想要詳細說明replace()方法做錯了什麼細節,我非常感謝這一努力。

再次感謝您。

3

u'\ ufffd'是"unicode replacement character",通常在黑色三角形內打印爲問號。不是變音符號。所以這個問題一定在上游的某個地方。檢查網頁頭文件返回的編碼是什麼,並確認它實際上是它所說的。

unicode替換字符通常插入作爲一個非法或無法識別的字符,這可能是由幾件事情引起的替代品,但最有可能的是, 編碼是不是它聲稱是。

1

U + FFFD是替換字符,當您執行some_bytes.decode('some-encoding', 'replace')時,某些子字符串some_bytes無法解碼。

其中有兩個:u'H\ufffd\ufffdftsitz' ...這表示這個U變音符表示爲兩個字節,每個字節都未能解碼。該網站很可能以UTF-8編碼,但該軟件試圖將其解碼爲ASCII。嘗試以ASCII格式解碼時,通常會在意外轉換爲Unicode時發生,並將ASCII用作默認編碼。但是在那種情況下,人們不會指望使用'replace' arg。更可能的代碼需要編碼,並且由某人認爲「不會引發異常」的人編寫的意思與「作品」相同。

編輯您的問題提供的URL,並顯示最低代碼產生u'H\ufffd\ufffdftsitz'

+0

非常感謝您的回覆,約翰。我找到了問題並提供瞭解釋它的答案。 – ayaz 2011-04-12 06:53:15