Парсинг веб-сайта с кодировкой iso-8859-1 вместо utf-8: как мне сохранить правильный юникод в моей базе данных?

Я хотел бы очистить веб-сайт с помощью Python, который полон ужасных проблем, одной из которых является неправильная кодировка вверху:

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

Это неправильно, потому что страница полна вхождений, подобных следующему:

Nell’ambito

вместо

Nell'ambito (обратите внимание, что ’ заменяет ')

Если я правильно понимаю, это происходит потому, что байты utf-8 (вероятно, кодировка базы данных) интерпретируются как байты iso-8859-1 (вынужденные кодировкой в ​​метатеге). Я нашел некоторые начальные объяснения по этой ссылке http://www.i18nqa.com/debug/utf8-debug.html

Я использую BeautifulSoup для навигации по странице, urfetch Google App Engine для выполнения запросов, однако все, что мне нужно, это понять, как правильно хранить в моей базе данных строку, которая исправляет ’, кодируя строку в '.


person Alessandro P.    schedule 09.05.2012    source источник
comment
Вы имеете в виду, что когда вы на самом деле посещаете страницу, вы видите неправильные символы или что вы получаете неправильные символы, когда отображаете данные в своем собственном приложении или просматриваете их в базе данных? Как ты его сейчас расчесываешь? Как вы расшифровываете и перекодируете символы? Вы уверены, что страница действительна в кодировке UTF-8, хотя утверждает, что это не так?   -  person Wooble    schedule 09.05.2012
comment
Да, на странице отображаются неправильные символы. Когда я очищаю страницу, она получает именно то, что есть на странице. BeautifulSoup конвертирует все в utf-8, за исключением того, что я явно не кодирую и не декодирую символы.   -  person Alessandro P.    schedule 09.05.2012


Ответы (1)


Я использую BeautifulSoup для навигации по странице, URL-адрес Google App Engine для запросов

Вы вводите кодировку из HTTP-заголовка Content-Type в BeautifulSoup?

Если HTML-страница имеет и заголовок Content-Type, и метатег, заголовок должен «выиграть», поэтому, если вы используете только метатег, вы можете получить неправильную кодировку.

В противном случае вы можете либо передать фиксированную кодировку 'utf-8' в Beautiful, либо исправить каждую строку по отдельности.

Раздражающее примечание: на самом деле это не ISO-8859-1. Когда веб-страницы указывают ISO-8859-1, браузеры на самом деле воспринимают это как кодовую страницу Windows 1252, которая похожа на 8859-1, но не совпадает с ней. может указывать на cp1252, потому что его нет в 8859-1.

u'Nell’ambito'.encode('cp1252').decode('utf-8')

Если содержимое закодировано несовместимо с некоторыми UTF-8 и некоторыми cp1252 на той же странице (обычно из-за плохой обработки содержимого базы данных), это будет единственный способ восстановить его, поймав UnicodeError и вернув исходную строку, когда это не так. перекодировать.

person bobince    schedule 09.05.2012
comment
Я передаю это в BeautifulSoup: BeautifulSoup(r.content, from_encoding='utf-8') - это неправильно? Заголовок accept-charset: Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3. - person Alessandro P.; 09.05.2012
comment
Ваше решение работает, за исключением того, что по какой-то причине это 'latin1' вместо 'cp1252'. - person Alessandro P.; 09.05.2012
comment
Вам нужна кодировка из заголовка ответа Content-Type: text/html;charset=..., из headers в объекте ответа urlfetch. За исключением того, что для text/html iso-8859-1 вводит в заблуждение, как указано выше. Нечетное: latin1 является синонимом iso-8859-1, и в этой кодировке нет знака евро, поэтому данный пример не должен работать. - person bobince; 10.05.2012
comment
в scala, который я предпочитаю для большинства задач в наши дни, вы можете использовать Charset из nio и функцию String через new String. Scala так же компактна, как Python, но позволяет легко использовать потоки наряду с процессами. - person Andrew Scott Evans; 11.07.2016