3

我正在使用 Scrapy 和 Python(作为 Django 项目的一部分)来抓取包含德语内容的网站。我已经libxml2安装为 Scrapy 选择器的后端。

如果我通过选择器提取单词'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设置为的 Python shell 上测试上述内容UTF-8。使用将来自 XPath 选择器的数据写入具有UTF-8字符集的 MySQL 数据库的 Django 应用程序,我看到了相同的行为。

我在这里忽略了一些明显的东西吗?任何线索或帮助将不胜感激。

4

3 回答 3

3

u'\ufffd' 是 “unicode 替换字符”,通常打印为黑色三角形内的问号。不是 au umlaut。所以问题一定出在上游的某个地方。检查返回的网页标题所说的编码,并验证它实际上是什么,它所说的是什么。

插入 unicode 替换字符通常是为了替换非法或无法识别的字符,这可能是由多种原因引起的,但最有可能的是编码不是它声称的那样。

于 2011-04-11T21:50:27.920 回答
3

非常感谢您的回答,约翰和史蒂文。你的回答让我有了不同的想法,这让我找到了问题的根源,也找到了一个可行的解决方案。

我正在使用以下测试代码:

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 shell 中,当我提取描述数据时,结果很好。这让我有理由怀疑我的代码有问题,因为在pdb提示符下,我在提取的数据中看到了替换字符。

我浏览了Response 类的 Scrapy 文档,并将上面的代码调整为:

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).replace(body=response)html_response = HtmlResponse(URL, body=response). 据我了解,该replace()方法从编码的角度以某种方式破坏了特殊字符。

如果有人想详细说明该方法到底出了什么replace()问题,我将非常感谢您的努力。

再一次感谢你。

于 2011-04-12T06:52:31.790 回答
1

U+FFFD 是您执行此操作时获得的替换字符,some_bytes.decode('some-encoding', 'replace')并且某些子字符串some_bytes无法解码。

你有两个:u'H\ufffd\ufffdftsitz'...这表明 u-umlaut 被表示为两个字节,每个字节都未能解码。最有可能的是,该站点以 UTF-8 编码,但该软件正试图将其解码为 ASCII。当意外转换为 Unicode 时,通常会尝试解码为 ASCII,并且使用 ASCII 作为默认编码。但是,在这种情况下,人们不会期望使用'replace'arg。代码更有可能采用编码并且由认为“不引发异常”与“有效”相同的人编写。

编辑您的问题以提供 URL,并显示生成u'H\ufffd\ufffdftsitz'.

于 2011-04-11T22:02:27.677 回答