Невозможно записать текст как UTF-8 в файл, используя python - PullRequest
1 голос
/ 02 октября 2011

Я работаю над программой, которая читает загруженную веб-страницу (хранящуюся как «нечто» .html) и анализирует ее соответствующим образом.У меня возникли проблемы с корректным кодированием и декодированием для этой программы.Насколько я понимаю, большинство веб-страниц закодировано в ISO-8859-1, и я проверил ответ с этой страницы, и это кодировка, которую мне дали:

>>> print r.info()
Content-Type: text/html; charset=ISO-8859-1
Connection: close
Cache-Control: no-cache
Date: Sun, 20 Feb 2011 15:16:31 GMT
Server: Apache/2.0.40 (Red Hat Linux)
X-Accel-Cache-Control: no-cache

Однако в метатегах страницы, которую он объявляет'utf-8' в качестве установленной кодировки:

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

Итак, в python я попробовал несколько подходов, чтобы прочитать эти страницы, разобрать их и написать utf-8, включая чтение файла в обычном режиме.и запись в обычном режиме:

with open('../results/1.html','r') as f:                                   
    page = f.read()
...
with open('../parsed.txt','w') as f:
    for key in fieldD:
        f.write(key+'\t'+fieldD[key]+'\n')

Я пытался явно указать файлу, какую кодировку использовать в процессе чтения и записи:

with codecs.open('../results/1.html','r','utf-8') as f:                                
    page = f.read()
...
with codecs.open('../parsed.txt','w','utf-8') as f:                                  
    for key in fieldD:
        f.write(key+'\t'+fieldD[key]+'\n')

Явно указывает файлу для чтения из 'iso-8849-1 'и напишите в' utf-8 ':

with codecs.open('../results/1.html','r','iso_8859_1') as f:
    page = f.read()
...
with codecs.open('../parsed.txt','w','utf-8') as f:                        
    for key in fieldD:
        f.write(key+'\t'+fieldD[key]+'\n')

А также все варианты этих идей, включая запись как utf-16, кодирование каждой строки отдельно перед их добавлением в словарьи другие ошибочные идеи.Я не уверен, что лучший подход здесь.Кажется, мне повезло, что я не использую ЛЮБУЮ кодировку, потому что это по крайней мере приведет к тому, что НЕКОТОРЫЕ текстовые редакторы будут просматривать результаты правильно (emacs, textwrangler)

Я прочитал несколько постов здесь относительно этоготема и до сих пор не может сделать головы или хвосты того, что происходит.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 02 октября 2011

Я следовал твоим инструкциям. Отображаемая страница имеет код NOT в кодировке UTF-8; декодирование с использованием UTF-8 завершается неудачно. Согласно экспериментальному детектору наборов символов, с которым я иногда сталкиваюсь, он закодирован в латинской кодировке ... одной из ISO-8859-1, cp1252 и ISO-8859-15, и язык выглядит так: es '(испанский) или' fr '(французский). По моему мнению, это испанский. Firefox (View >>> view кодирование) говорит, что это ISO-8859-1.

Итак, теперь вам нужно поэкспериментировать с тем, какие инструменты будут правильно отображать ваши сохраненные файлы. Если вы не можете его найти, вам нужно будет перекодировать ваши файлы в UTF-8, то есть data.decode ('ISO-8859-1'). Encode ('UTF-8') и найти инструмент, отображающий UTF-8. правильно. Не должно быть слишком сложно. Firefox может вывести кодировку и отобразить ее корректно практически для любой кодировки, которую я выбрасывал.

Обновление после запроса на «интуицию»:

В вашем третьем блоке кода вы включаете только вход и выход, с "..." между ними. Входной код должен выдавать unicode объектов ОК. Однако в выходном коде вы используете функцию str (почему ???). Предполагая, что у вас все еще есть unicode объекты после "...", применение str() к ним вызовет исключение, если кодировка вашей системы по умолчанию 'ascii' (как и должно быть), или незаметно искажает ваши данные, если 'utf8' (как и не должно быть). Пожалуйста, опубликуйте (1) содержимое «...» (2) результат выполнения import sys; print sys.getdefaultencoding() (3) того, что вы «видите» в выходном файле вместо ожидаемого - в «Iglesia Católica» - так ли это ó? (4) фактические байты в файле (используйте print repr (данные)) вместо ожидаемых -

решено Вы говорите в комментарии, что видите Iglesia Cat√ɬ≥lica ... обратите внимание, что вместо одного ожидаемого отображается четыре символа. Это симптоматично дважды кодировать в UTF-8. Следующей загадкой было то, что отображало те символы, два из которых не отображены ни в ISO-8859-1, ни в cp1252. Я попробовал старые кодовые страницы DOS cp437 и cp850, все еще используемые в окне командной строки Windows, но они не подходили. кои8р тоже не подходил; это нуждается в основанном на латинице наборе символов. Хм как насчет макромана? Тада !! Вы отправили дважды закодированный гфф на стандартный вывод на вашем терминале Mac. См. Демонстрацию ниже.

>>> from unicodedata import name
>>> oacute = u"\xf3"
>>> print name(oacute)
LATIN SMALL LETTER O WITH ACUTE
>>> guff = oacute.encode('utf8').decode('latin1').encode('utf8')
>>> guff
'\xc3\x83\xc2\xb3'
>>> for c in guff.decode('macroman'):
...     print name(c)
...
SQUARE ROOT
LATIN CAPITAL LETTER E WITH ACUTE
NOT SIGN
GREATER-THAN OR EQUAL TO
>>>

Проверка сохраненного файла Я также сохранил веб-страницу в файл (плюс каталог, содержащий * .jpg, файл CSS и т. Д.) - используя Firefox «сохранить страницу как». Попробуйте сделать это на сохраненной странице и опубликуйте результаты.

>>> data = open('g0.htm', 'rb').read()
>>> uc = data.decode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python27\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xb7 in position 1130: invalid start byte
>>> pos = data.find("Iglesia Cat")
>>> data[pos:pos+20]
'Iglesia Cat\xf3lica</a>'
>>> # Looks like one of ISO-8859-1 and its cousins to me.

Обратите внимание: если ваш файл закодирован в UTF-8, то чтение его с кодеком UTF-8 приведет к Unicode. Если вы не обрабатываете данные каким-либо образом при синтаксическом анализе и пишете проанализированный юникод с помощью кодека UTF-8, он НЕ будет кодироваться дважды. Вам нужно внимательно посмотреть в своем коде на наличие экземпляров «str» (помните «typo»?), «Unicode», «encode», «decode», «utf», «UTF» и т. Д. Вы называете третий -партийная библиотека для разбора? Что вы видите, когда делаете print repr(key), repr(field[key]) непосредственно перед записью в выходной файл?

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

32766.html: Я только что понял, что вы тот парень, который уничтожил все свои inode, пытаясь записать слишком много файлов в папку в файловой системе vfat (или что-то в этом роде). Таким образом, вы не делаете руководство "сохранить как". Пожалуйста, опубликуйте код, который вы использовали для «сохранения» этих файлов.

1 голос
/ 03 октября 2011
>>> url = 'http://213.97.164.119/ABSYS/abwebp.cgi/X5104/ID31295/G0?ACC=DCT1'
>>> data = urllib2.urlopen(url).read()[4016:4052]; data
'Iglesia+Cat%f3lica">Iglesia Cat\xf3lica'

>>> data.decode('latin-1')
u'Iglesia+Cat%f3lica">Iglesia Cat\xf3lica'

>>> data.decode('latin-1').encode('utf-8')
'Iglesia+Cat%f3lica">Iglesia Cat\xc3\xb3lica'

Что вы получаете?

...