Python пишет странные символы после загрузки веб-страницы с помощью Mechanize

У меня проблема с загрузкой веб-страниц и их обработкой. Что я хочу сделать:

  • использование Mechanize для загрузки веб-страниц в переменную
  • распечатать эту веб-страницу (перед записью в файл для дальнейшей обработки)
  • искать заданные слова на веб-странице (это будет дальнейшее исследование) и посчитать их, сколько я нашел.

Моя проблема в кодировке символов, потому что я получаю

<title>csonthãᄅjas termãᄅsek - wikipãᄅdia</title>

вместо

<title>csonthéjas termések - wikipédia</title>

Проблема существует почти со всеми акцентированными и «странными» символами, такими как _3 _... Когда я просто записываю его в виде строки, это работает.

print 'csonthéjas termések - wikipédia'

Chardet говорит, что он имеет кодировку символов ISO-8859-2, но ничего не меняется, когда я меняю кодировку скрипта. Когда я пытаюсь кодировать или декодировать веб-страницу как любую кодировку, я получаю сообщение об ошибке («недопустимый байт продолжения» или «порядковый номер не в диапазоне (128)»

Я пробовал много кодировок, разных агентов браузера, обнаруживая кодировку с помощью chardet, а затем используя эту информацию, но ничто не решило мою проблему. Я знаю, что это простой вопрос, но я не смог найти на него правильного ответа. Я использую Windows 8.1 и Python 2.7.6

Мой код следующий (я пытался сократить его настолько просто, насколько мог):

#!/usr/bin/python
# -*- coding: ISO-8859-2 -*-

def url_get(url_input): #Get the webpage
    "Get the webpage"
    import mechanize
    url = url_input
    br = mechanize.Browser()
    br.set_handle_equiv(True)
    br.set_handle_redirect(True)
    br.set_handle_referer(True)
    br.set_handle_robots(False)
    #User-agent','Mozilla/1.22 (compatible; MSIE 10.0; Windows 3.1)
    br.addheaders = [('user-agent', '   Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3'),
('accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')]
    result = br.open(url).read().lower()
    print result

    import chardet    
    rawdata = result
    detection = chardet.detect(rawdata)
    charenc = detection['encoding']
    print charenc

    return result

text = url_get('http://hu.wikipedia.org/wiki/Csonth%C3%A9jas_term%C3%A9sek')

print 'csonthéjas termések - wikipédia'

person Károly Szommer    schedule 01.06.2014    source источник
comment
Вам не нужно менять кодировку файла сценария, вам нужно декодировать данные, которые вы загружаете.   -  person BrenBarn    schedule 01.06.2014
comment
Спасибо, я думал, что кодировка скрипта влияет на всю программу, а не только на сам скрипт.   -  person Károly Szommer    schedule 01.06.2014


Ответы (1)


Страница отображается в кодировке UTF-8. Возьмите свой text и распечатайте text.decode('utf-8'). У меня это работает, когда я читаю содержимое страницы с помощью модуля requests.

Вам необходимо удалить вызов lower(), поскольку преобразование в нижний регистр может повредить текст в кодировке UTF-8. Если вы хотите преобразовать в нижний регистр, вызовите lower() после декодирования.

Когда вы используете строку # -*- coding, вы устанавливаете кодировку файла сценария. Это не влияет на данные, которые читает ваш файл сценария. Чтобы иметь дело с текстовыми данными в разных кодировках, вам необходимо декодировать данные после их чтения.

person BrenBarn    schedule 01.06.2014
comment
Я попытался print text.decode('utf-8'), но получил ошибку UnicodeDecodeError: кодек 'utf8' не может декодировать байты в позиции 108-109: недопустимый байт продолжения. Затем я попытался изменить строку на result = br.open(url).read().lower().decode('utf-8'), но у меня возникла та же проблема. Пока все пробовал, случайно удалил раздел .lower(), и это сработало как чудо: я везде вижу правильные символы. Должен ли я написать решение где-нибудь еще? - person Károly Szommer; 01.06.2014
comment
@ KárolySzommer: Я не заметил, что у тебя там lower() звонок. Вам нужно убрать это, потому что в тексте могут быть символы верхнего регистра, которые не являются настоящими символами, а являются лишь частью двухбайтового символа в кодировке UTF-8. Если вы хотите преобразовать в нижний регистр, вызовите lower() после декодирования. - person BrenBarn; 01.06.2014