Python urllib возвращает два символа 0xfffd вместо ожидаемых символов Юникода - PullRequest
1 голос
/ 16 сентября 2011

Я очищаю какой-то веб-сайт, кодировка Unicode:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Для этого я использую urllib:

html = unicode(urllib.openurl(url).read(), 'utf-8')

Иногда некоторые символы Unicode будут заменены двумя0xFFFD символов в случайном порядке.Я предполагаю, что один символ, закодированный с 4 байтами, сломан, и заменен двумя 0xFFFD для каждой из двух 2-байтовых половин.Вероятность такой замены довольно низкая - возможно, заменен один символ из 500 000, что-то в этом роде.Кажется, что повреждены только не-ascii символы.

Я не наблюдаю ни одной из этих замен, когда одна и та же страница отображается в браузере.

Как определить, какая часть представляетпроблема?Это сервер, который отправляет поврежденные байты, или клиент, который не читает их правильно?

@ Джон Мачин:

  1. Версия Python - 2.7.1
  2. Это наблюдается во всех браузерах, а также в большинстве http-клиентов (libcurl, wget, python)
  3. Я действительно ошибался - иногда эти ошибки появляются в браузерах на отображаемой странице.Ошибки отображаются в виде двух символов ромба с вопросительными знаками.
  4. Ошибки случайные.Иногда они появляются, иногда нет.Чем больше страница, тем больше вероятность появления ошибки.

Так что я думаю, что ошибка возникает на стороне веб-сервера.Я просто попытаюсь их игнорировать.

Ответы [ 3 ]

0 голосов
/ 16 сентября 2011

Я вижу две возможности.

  1. Если вызов .read() возвращает только часть многобайтовой последовательности в конце, тогда частичная последовательность будет заменена на U + FFFD.См. это объяснение кодировки UTF-8.Частичные байтовые последовательности могут быть легко обнаружены с использованием числа старших 1 бит в первом байте кодированной кодовой точки, так что вы можете декодировать все, кроме частичной последовательности, и возобновить со следующим чтением.Кодовые точки U + 007F и ниже кодируются одним байтом, поэтому эта проблема никогда не сможет повлиять на эти кодовые точки.
  2. Возможно, документ содержит объявление charset=utf-8, но фактически не кодируется с помощью UTF-8.Любые байты, которые не являются действительной последовательностью UTF-8, будут заменены на U + FFFD.

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

0 голосов
/ 17 сентября 2011

Вполне возможно, что сервер и клиент точно воспроизводят результаты более ранней проверки. Сценарий: у кого-то есть текст, закодированный в cp1252 (обычный подозреваемый). Они декодируют его с помощью UTF-8 с опцией «replace» - вводя u «\ ufffd» - и затем кодируют результат.

Пример исходного текста: Seine Füße sind wund.

>>> original = "Seine F\xfc\xdfe sind wund." # encoded in cp1252
>>> ucode1 = original.decode('utf8', 'replace')
>>> ucode1
u'Seine F\ufffd\ufffde sind wund.'
>>> input_to_server = ucode1.encode('utf8')
>>> input_to_server
'Seine F\xef\xbf\xbd\xef\xbf\xbde sind wund.'
>>> observed_result = unicode(input_to_server, 'utf8')
>>> observed_result
u'Seine F\ufffd\ufffde sind wund.'
>>>

В любом случае все ответы будут основаны на догадках, если вы не предоставите больше информации, например:

  • Какая версия Python (точно, например, 2.7.1)

  • В каких браузерах вы просматриваете URL-адрес? Что значит "посмотреть" текст "сказать вам?

  • Вы говорите: «Я не наблюдаю ни одной из этих замен, когда та же страница отображается в браузере. "ОК, значит, вы получаете rhubarb \ufffd\ufffd artichoke из своего кода, а в браузере вы видите rhubarb PLEASE-TELL-US-WHAT-YOU-SEE-HERE artichoke - пожалуйста, разглашайте.

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

0 голосов
/ 16 сентября 2011

Браузеры делают много магии, чтобы исправить недопустимые символы.Попробуйте посмотреть необработанные байты, возвращаемые .read(), и проверьте, нет ли на исходной странице недопустимых символов.Например, иногда страницы будут кодировать буквы с ударением на латинском-1 или аналогичные, а другие символы - на utf-8.

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