Определить кодировку строки

Димон

Новичок
Всем хай.

Нужна помощь в опеределении кодировки строки. Строка выдирается из PDF и сохраняется в UTF-8. Исходная кодировка ISO8859-5 (это я опеределил на http://2cyr.com/decode/?lang=ru).

Выдранная строка: áÞåàÐÝØÒ ÜÝÞÓÞ ßàØÛÞÖÕÝØÙ Java, ÜÞÖÝÞ ×ÐÝïâì Òáî ÔÞáâãßÝãî ßÐÜïâì
"Перевод": сохранив много приложений Java, можно занять всю доступную память

Т.е. нажна какая-то тулза, которая эвристически или с помощью маппинга оперелить кодировку.

Юзал следующие либы. Они все естественно отдают UTF-8. Т.е. читают либо код символа, либо мета-данные из файла.

1) enca (aptitude install enca)

2) chardet (aptitude install chardet)

3) uchardet (aptitude search uchardet)

4) tika.apache.org/

5) npmjs.com/package/detect-encoding

6) libencode-detect-perl

7) www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html

8) jchardet.sourceforge.net/

9) grepcode.com/snapshot/repo1.maven.org/maven2/com.googlecode.juniversalchardet/juniversalchardet/1.0.3/

10) lxr.mozilla.org/seamonkey/source/extensions/universalchardet/src/

11) userguide.icu-project.org/

Заранее благодарю.
 

Димон

Новичок
Тогда более развернуто.
- pdftotext парсит текст из пдфки. Пдфка в ISO8859-5. Как я уже писал (это я опеределил на http://2cyr.com/decode/?lang=ru).
- pdftotext сохраняет выхлоп в utf. Для данной пфки сохраняется нечитабельным, ибо исходник не utf.
- Назначение других кодировок для pdftotext через -enc бессмысленно, т.к. подразумевается, что исходную кодировку пдф я не знаю.
- 2cyr.com как-то определяет "реальную" кодировку для сохранненого текста. Х.з. может посимвольная мапа там стоит или что еще ..
- iconv() - это все потом. Мне нужно определить кодировку.

Да и перекодировка данной строки iconv('SO8859-5', 'UTF-8', $str) дает мусор, т.к. исходник типа в UTF. Но это уже другая сказака.
 

Димон

Новичок
Вообще для русского набросать такую мапу дело нехитрое. Но есть еще другие языки .. Вот и надобно некостыльное решение.
 

stalxed

Новичок
Вообще для русского набросать такую мапу дело нехитрое. Но есть еще другие языки .. Вот и надобно некостыльное решение.
Судя по этому посту http://stackoverflow.com/questions/10656184/is-there-a-field-in-which-pdf-files-specify-their-encoding
В PDF может быть несколько кодировок, там ещё ссылка указана на спецификацию PDF - изучайте, может найдете там указание кодировки...

Вообще, лучше ищите софт какой-нибудь готовый для этого дела, зачем сюда PHP привлекать?
 

Димон

Новичок
Спасибо за ссылки.
А php тут ибо логика основная на нем. Мне все равно на чем написать определитель, perl, java, c++, питон главное чтобы либы были готовые, чтобы не возиться на низкоуровневом парсинге.
 

fixxxer

К.О.
Партнер клуба
Полагаю, перебором всех возможных вариантов (возможно, с эвристикой для отбрасывания заведомо неподходящих), пока не получится что-то похожее на кириллический текст.
 

Димон

Новичок
Получается что, "моя" кодировка является под-кодировкой UTF8. Поэтому все вышеперечисленные либы бесполезны. Плотно расковырял и поюзал вчера С++ ICU4 - результат тот же. Значит подход неверный.
В общем решил пока сделать костыль. Нашел еще сайт по определение кодировки он-лайн: http://www.online-decoder.com/ru. Потестил его - понравился больше, чем первый.

Вот костыль. Кому надобно - просто обернуть в exec() или полностью написать на пыхе.

Код:
Запрос
$ curl -L --connect-timeout 5 --max-time 20 'http://www.online-decoder.com/ru' -d 'abracadabra=ÀÐÑÞâÐ âÕÛÕäÞÝÐ ÒÞ×ÜÞÖÝÐ âÞÛìÚÞ ßàØ ÝÐÛØçØØ ÞÑáÛãÖØÒÐÝØï, ßàÕÔÞáâÐÒÛïÕÜÞÓÞ ßÞáâÐÒéØÚÞÜ ãáÛãÓ áÞâÞÒÞÙ&authenticity_token=qz0HNQv3OAyJS8a/NhUgYGaW2+6oTlouf7HpDzLvJbI=&decoder[from]=&decoder[to]=&guess=Подбор' -H 'User-Agent:Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0' --fail 2>/dev/null | tr "\n" " " | php -E '$s=$argn; if(preg_match("!<div\s+class\s*=\s*\"suggestion\s+shadowtop\"\s+id\s*=\s*\"(.+?)\"[^>]*>\s*<div\s+class\s*=\s*\"full\"[^>]*>([^<]+)!usi", $s, $m)) { echo json_encode(array($m[1],trim($m[2])), JSON_UNESCAPED_UNICODE); };'

Выхлоп:
["WINDOWS-1252+ISO-8859-5","Работа телефона возможна только при наличии обслуживания, предоставляемого поставщиком услуг сотовой"]
Если на http://stackoverflow.com или http://askubuntu.com что-нибудь путное ответят, закину ответ сюда. А пока можно морозить тему :)
Всем спасибо!
 

AmdY

Пью пиво
Команда форума
- pdftotext парсит текст из пдфки. Пдфка в ISO8859-5. Как я уже писал (это я опеределил на http://2cyr.com/decode/?lang=ru).
- pdftotext сохраняет выхлоп в utf. Для данной пфки сохраняется нечитабельным, ибо исходник не utf.
ну и в чём проблема? почитай про параметры pdftotext и выставь себе нужную кодировку, а не городи костылей.
 

Димон

Новичок
ну и в чём проблема? почитай про параметры pdftotext и выставь себе нужную кодировку, а не городи костылей.
Прежде чем писать - проверь свои доводы. -enc не работает. И об этом я писал выше. pdftotext - это бинарь вокруг API poppler. С API я "поигрался" досконально. Подход нужен другой. Какой - читай выше.
 

AmdY

Пью пиво
Команда форума
AnrDaemon, кодировка файла вшита в сам файл, а выходной указывается через параметр -enc,проблем быть не должно, если не особый шрифт с номерами глифов, тогда о кодировке вообще говорить бессмысленно, т.к. это набор картинок.

Во всей этой истории меня смущает, что у ТС всё же без проблем получается сконвертировать полученный текст, видимо у него таки проблемы с параметром enc, может глюк в версии либы или криво собранная.

Хотелось бы увидеть эту pdf-ку и посмотреть что получится на моей машине.
 

Димон

Новичок
Нашел как опеределить кодировку без 3-ей стороны:

Код:
iconv -l | tr "//" " " | perl -ne 'chomp $_; `echo "áÞåàÐÝØÒ ÜÝÞÓÞ ßàØÛÞÖÕÝØÙ Java, ÜÞÖÝÞ ×ÐÝïâì Òáî ÔÞáâãßÝãî ßÐÜïâì" | iconv -t $_ | chardet` =~ /<stdin>:\s*([^\s]+)\s*\(confidence:\s*([\d\.]+)\)/; if($1 && $2) { print "$2\t$1\n"; }' 2>/dev/null | sort | uniq | sort -k 1,1 -n -r | head -n 10

1.00    UTF-32LE
1.00    UTF-16LE
1.00    ascii
0.99    utf-8
0.99    ISO-8859-5
0.99    ISO-2022-KR
0.99    ISO-2022-JP
0.99    IBM866
0.99    EUC-TW
0.68    ISO-8859-7
При попытке перекодировать с неправильной кодировки (кроме utf*) выдается ошибка. Она пропадает только на ISO-8859-5. Но получается треш типа "УУУУУЂУ".
Код:
echo 'ÀÐÑÞâÐ' | iconv -f ascii -t utf-8 2>/dev/null && printf %s $_
-> Пусто
echo 'ÀÐÑÞâÐ' | iconv -f ISO-8859-5 -t utf-8 2>/dev/null && printf %s $_
-> УУУУУЂУ  // Работа
 

Димон

Новичок
Сделать виртуальную машину, вбить в гугл software pdf to text - заинсталить все программы и найти ту, которая выдаёт наиболее приемлемые результаты.
Начать наверное стоит с ABBYY FineReader.
Именно так и сделал. И среди них, адобовский про-конвертор - самый убогий, файн-ридер вообще через раз работает.
 

Димон

Новичок
Ну вот сделал решение. Есть либа из пакета JDK, которая перекодирует utf в заэскейпленную utf кодировку ascii.

Делается это только после того как неудалось сделать первичное определение языка документа. Например на сервисе https://detectlanguage.com/ пришел ответ с confidence < 0.95

Логика следующая:
Код:
Файл "utf-8--iso8859-5.txt" с содержимым:
áÞåàÐÝØÒ ÜÝÞÓÞ ßàØÛÞÖÕÝØÙ Java, ÜÞÖÝÞ ×ÐÝïâì Òáî ÔÞáâãßÝãî ßÐÜïâì

Удаляем все небуквенные символы:
<?php
$textSlice = preg_replace('!\P{L}!usi', ' ', mb_substr(file_get_contents('utf-8--iso8859-5.txt'), 0, 128));
$textSlice = preg_replace('!\s{2,}!usi', ' ', $textSlice);
?>

Ищем подходящую кодировку:
iconv -l | tr "//" " " | perl -ne 'chomp $_; `echo "$textSlice" | iconv -t $_ | chardet` =~ /<stdin>:\s*([^\s]+)\s*\(confidence:\s*([\d\.]+)\)/; if($1 && $2) { print "$2\t$1\n"; }' 2>/dev/null | sort | uniq | sort -k 1,1 -n -r | head -n 5
1.00    UTF-32LE
1.00    UTF-16LE
1.00    ascii
0.99    utf-8
0.99    ISO-8859-5

Используем верхние сразу после UTF*
echo $textSlice | iconv -f ascii -t utf-8 2>/dev/null && printf %s $_
-> Пусто, значит кодировка не подходит
echo $textSlice | iconv -f ISO-8859-5 -t utf-8 2>/dev/null && printf %s $_
-> "Абракадабра", значит кодировка подходит

Перекодируем в читабельный текст
echo -e `native2ascii utf-8--iso8859-5.txt | perl -ne 'chomp $_; $_ =~ s/\\\u00/\\\x/g; print $_;' 2>/dev/null` | iconv -f ISO8859-5 -t utf-8 1> result.txt
cat result.txt
сохранив много приложений Java, можно занять всю доступную память
 
Последнее редактирование:
Сверху