Проблема кодировки Unicode и UTF-8 с текстом селектора Scrapy XPath - PullRequest
3 голосов
/ 12 апреля 2011

Я использую 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. Я тестирую вышеописанное на оболочке Python с sys.getdefaultencoding, установленным на UTF-8. Используя приложение Django, где данные из селекторов XPath записываются в базу данных MySQL с набором символов UTF-8, я вижу то же поведение.

Я пропускаю что-то очевидное здесь? Любые подсказки или помощь будут с благодарностью.

Ответы [ 3 ]

3 голосов
/ 12 апреля 2011

Большое спасибо за ваши ответы, Джон и Стивен.Ваши ответы заставили меня задуматься по-другому, что привело меня к поиску источника проблемы, а также рабочего решения.

Я работал со следующим тестовым кодом:

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 и скорректировал приведенный выше код так:

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() сделал неправильно,Я был бы очень признателен за усилия.

Еще раз спасибо.

3 голосов
/ 12 апреля 2011

u '\ ufffd' - это «символ замены Юникода» , который обычно печатается в виде знака вопроса внутри черного треугольника.НЕ ау умлаут.Так что проблема должна быть где-то вверх по течению.Проверьте, какую кодировку возвращают заголовки веб-страницы, и убедитесь, что это действительно так.

Символ замены юникода обычно вставляется в качестве замены недопустимого или нераспознанного символа, что может быть вызвано несколькими причинами, но наиболее вероятным является то, что кодировка не соответствует заявленной.

1 голос
/ 12 апреля 2011

U + FFFD - это символ замены, который вы получаете, когда вы делаете some_bytes.decode('some-encoding', 'replace'), а некоторая подстрока some_bytes не может быть декодирована.

У вас ДВА из них: u'H\ufffd\ufffdftsitz' ... это означает, что u-umlaut был представлен в виде ДВУХ байтов, каждый из которых не удалось декодировать. Скорее всего, сайт кодируется в UTF-8, но программное обеспечение пытается декодировать его как ASCII. Попытка декодирования как ASCII обычно происходит, когда происходит непредвиденное преобразование в Unicode, и ASCII используется в качестве кодировки по умолчанию. Однако в этом случае не следует ожидать использования аргумента 'replace'. Скорее всего, код принимает кодировку и был написан кем-то, кто думает, что «не вызывает исключение» означает то же самое, что и «работает».

Отредактируйте свой вопрос, указав URL, и покажите минимальный код, который выдает u'H\ufffd\ufffdftsitz'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...