Чтение и запись файлов XML с неизвестной кодировкой в ​​Perl?

Я собираю кусочки чужого большого проекта и пытаюсь исправить ошибки. Проблема в том, что я просто не уверен, какие есть правильные способы.

Итак, я скручиваю кучу HTML-страниц, а затем записываю их в файлы с помощью простых команд, таких как:

$src = `curl http://google.com`;
open FILE, ">output.html";
print FILE $src;
close FILE;

Теперь я хотел, чтобы они были сохранены как UTF-8. Как это сохраняется? Затем я читаю html-файл, используя ту же базовую команду «открыть», анализируя html с помощью вызовов регулярных выражений и используя конкатенацию строк для создания большой строки и записи ее в файл XML (используя тот же код, что и выше). Вместо этого я уже начал использовать XML::Writer, но теперь мне нужно просмотреть и исправить файлы с неточной кодировкой.

Итак, у меня больше нет html, но у меня все еще есть XML, который должен отображать правильные символы. Вот пример: http://filevo.com/wkkixmebxlmh.html

Основная проблема заключается в обнаружении и замене рассматриваемого символа на «\x{2019}», который правильно отображается в редакторах. Но я не могу придумать регулярное выражение, чтобы на самом деле захватить персонажа в дикой природе.

ОБНОВЛЕНИЕ:

Я до сих пор не могу обнаружить символ ALT-0146 в файле XML, который я загрузил в Filevo выше. Я пытался открыть его в UTF-8 и искать /\x{2019}/, /chr(0x2019)/ и просто /’/, ничего.


person VolatileRig    schedule 27.05.2011    source источник
comment
use utf8 предназначен исключительно для обработки исходного кода вашего скрипта как закодированного в UTF-8. Он не имеет ничего общего с кодировкой любых входов и выходов вашего скрипта, включая STDOUT.   -  person mob    schedule 28.05.2011
comment
Ах, спасибо за разъяснение.   -  person VolatileRig    schedule 28.05.2011


Ответы (3)


Чтобы убедиться, что вы производите вывод в UTF-8, примените слой utf8 к выходному потоку, используя binmode

open FILE, '>output.html';
binmode FILE, ':utf8';

или в 3-аргументном вызове open

open FILE, '>:utf8', 'output.html'

Произвольный ввод сложнее. Если вам повезет, ввод HTML заранее сообщит вам кодировку:

wget http://www.google.com/ -O foo ; head -1 foo

<!doctype html><html><head><meta http-equiv="content-type" content="text/html; 
charset=ISO-8859-1"><title>Google</title><script>window.google=
{kEI:"xgngTYnYIoPbgQevid3cCg",kEXPI:"23933,28505,29134,29229,29658,
29695,29795,29822,29892,30111,30174,30215,30275,30562",kCSI:
{e:"23933,28505,29134,29229,29658,29695,29795,29822,29892,30111,
30174,30215,30275,30562",ei:"xgngTYnYIoPbgQevid3cCg",expi:
"23933,28505,29134,29229,29658,29695,29795,29822,29892,30111,
30174,30215,30275,30562"},authuser:0,ml:function(){},kHL:"en",
time:function(){return(new Date).getTime()},

А, вот оно: <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">. Теперь вы можете продолжать читать ввод как необработанные байты и найти способ декодировать эти байты с помощью известной кодировки. В этом может помочь CPAN.

person mob    schedule 27.05.2011
comment
Если вы действительно хотите, чтобы все было просто, перестаньте использовать curl для получения HTML. use LWP::UserAgent; my $ua = LWP::UserAgent->new(); my $response = $ua->get('http://www.google.com'); $response->decoded_content; HTTP::Response будет декодировать содержимое на основе заголовков во внутреннюю строку юникода Perl; тогда вы можете просто применить режим binmode unicode к своему выводу, и он просто сработает. - person Oesor; 28.05.2011
comment
это отличный совет по улучшению системы, но я все еще не могу обнаружить символ ALT-0146 в файле XML, который я загрузил в Filevo. Я пытался открыть его в UTF-8 и искать /\x{2019}/, /chr(0x2019)/ и просто /’/, ничего. - person VolatileRig; 28.05.2011
comment
@Sho Minaminoto: Когда вы переводите этот файл в Perl и используете регулярное выражение для извлечения этого символа (поскольку вы знаете символы до и после этого сложного символа), как он говорит, что тот, который вас интересует, выглядит? Вы можете распечатать его в файл и делать подобные вещи. - person Seth Robertson; 28.05.2011
comment
Вы можете открыть файл XML как текстовый файл и просмотреть его. Он выглядит как буква «а» плюс знак валюты, но это зависит от того, в каком редакторе я его открываю. - person VolatileRig; 28.05.2011

Распознать кодировку HTML-документа сложно. См. http://blog.whatwg.org/the-road-to-html-5-character-encoding и особенно то, что для этого требуется «7-шаговый алгоритм; шаг 4 имеет 2 подэтапа, первый из которых имеет 7 ветвей, один из которых имеет 8 подэтапов, один из которых на самом деле связан с отдельным алгоритмом, который сам состоит из 7 шагов... Так продолжается какое-то время».

Это то, что я использовал для своих ограниченных потребностей в анализе файлов HTML.

my $CHARACTER_SET_CLASS = '\w:.()-';

     # X(HT)?ML: http://www.w3.org/International/O-charset
     /\<\?xml [^>]*(?<= )encoding=[\'\"]?([$CHARACTER_SET_CLASS]+)/ ||
     # X?HTML: http://blog.whatwg.org/the-road-to-html-5-character-encoding
     /\<meta [^>]*\bcharset=["']?([$CHARACTER_SET_CLASS]+)/i ||
     # CSS: http://www.w3.org/International/questions/qa-css-charset
     /\@charset "([^\"]*)"/ ||
person Seth Robertson    schedule 27.05.2011

Я имею в виду обновленную часть вашего вопроса (в следующий раз откройте новый для отдельной темы). Это шестнадцатеричный дамп вашего файла (пожалуйста, воздержитесь в будущем от того, чтобы помощники прыгали через горящие обручи, чтобы получить данные вашего примера):

0000  3c 78 6d 6c 3e 0d 0a 3c  70 65 72 73 6f 6e 4e 61  <xml>␍␤< personNa
0010  6d 65 3e 47 2e 20 50 65  74 65 72 20 44 61 80 41  me>G. Pe ter Da�A
0020  6c 6f 69 61 3c 2f 70 65  72 73 6f 6e 4e 61 6d 65  loia</pe rsonName
0030  3e 0d 0a 3c 2f 78 6d 6c  3e 0d 0a                 >␍␤</xml >␍␤

Вы сказали, что знаете, что символ должен быть , но он был полностью искажен. Это не может быть 0x80 в любой кодировке. Это похоже на аварию при вставке, когда вы переносите данные между редакторами/буферами обмена вместо того, чтобы иметь дело только с файлами. Если это не так, то ваш пастух допустил ошибку, которую вы не можете исправить алгоритмически.

person daxim    schedule 28.05.2011