Обнаруживать кодировку и делать все UTF-8

Я читаю много текстов из разных RSS-каналов и вставляю их в свою базу данных.

Конечно, в кормах есть несколько различных кодировок символов, например UTF-8 и ISO-8859-1.

К сожалению, иногда возникают проблемы с кодировками текстов. Пример:

1) «ß» в «Fußball» должен выглядеть так в моей базе данных: «ÂŸ». Если это «ÂŸ», он отображается правильно.

2) Иногда «ß» в «Fußball» выглядит так в моей базе данных: «ÃƒÂŸ». Тогда это отображается неправильно, конечно.

3) В других случаях «ß» сохраняется как «ß» – поэтому без каких-либо изменений. Затем он также отображается неправильно.

Что я могу сделать, чтобы избежать случаев 2 и 3?

Как я могу сделать все одинаковое кодирование, желательно UTF-8? Когда я должен использовать utf8_encode (), когда я должен использовать utf8_decode () (ясно, что такое эффект, но когда я должен использовать функции?), И когда я должен ничего делать со входом?

Можете ли вы мне помочь и рассказать мне, как сделать все одинаковое кодирование? Возможно, с функцией mb-detect-encoding ()? Могу ли я написать функцию для этого? Итак, мои проблемы: 1) Как узнать, какая кодировка используется в тексте 2) Как преобразовать ее в UTF-8 – независимо от старой кодировки

EDIT: Будет ли такая функция работать?

function correct_encoding($text) { $current_encoding = mb_detect_encoding($text, 'auto'); $text = iconv($current_encoding, 'UTF-8', $text); return $text; } 

Я тестировал его, но он не работает. Что с этим не так?

Если вы примените utf8_encode () к уже существующей строке UTF8, она вернет искаженный вывод UTF8.

Я сделал функцию, которая затрагивает все эти проблемы. Он называется Encoding :: toUTF8 ().

Вам не нужно знать, что такое кодировка ваших строк. Это может быть Latin1 (iso 8859-1), Windows-1252 или UTF8, или строка может содержать их. Кодирование :: toUTF8 () преобразует все в UTF8.

Я сделал это, потому что служба давала мне поток данных, все испорченные, смешивая UTF8 и Latin1 в одной строке.

Применение:

 require_once('Encoding.php'); use \ForceUTF8\Encoding; // It's namespaced now. $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string); $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string); 

Скачать:

https://github.com/neitanod/forceutf8

Обновить:

Я включил еще одну функцию, Encoding :: fixUFT8 (), которая исправит каждую строку UTF8, которая выглядит искаженной.

Применение:

 require_once('Encoding.php'); use \ForceUTF8\Encoding; // It's namespaced now. $utf8_string = Encoding::fixUTF8($garbled_utf8_string); 

Примеры:

 echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football"); 

выведет:

 Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football 

Обновление: я преобразовал функцию (forceUTF8) в семейство статических функций в классе Encoding. Новая функция – Encoding :: toUTF8 ().

Сначала вам нужно определить, какая кодировка была использована. Когда вы разбираете RSS-каналы (возможно, через HTTP), вы должны прочитать кодировку из параметра charset поля заголовка Content-Type HTTP . Если его нет, прочитайте кодировку из атрибута encoding инструкции обработки XML . Если этого не хватает, используйте UTF-8, как определено в спецификации .


Редактировать Вот что я, вероятно, сделаю:

Я бы использовал cURL для отправки и получения ответа. Это позволяет вам устанавливать определенные поля заголовка и извлекать заголовок ответа. После получения ответа вы должны проанализировать ответ HTTP и разделить его на заголовок и тело. Затем заголовок должен содержать поле заголовка Content-Type которое содержит тип MIME и (надеюсь) параметр charset с кодировкой / кодировкой. Если нет, мы проанализируем XML PI для наличия атрибута encoding и получим от него кодировку. Если это также отсутствует, спецификации XML определяют использование UTF-8 в качестве кодировки.

 $url = 'http://www.lr-online.de/storage/rss/rss/sport.xml'; $accept = array( 'type' => array('application/rss+xml', 'application/xml', 'application/rdf+xml', 'text/xml'), 'charset' => array_diff(mb_list_encodings(), array('pass', 'auto', 'wchar', 'byte2be', 'byte2le', 'byte4be', 'byte4le', 'BASE64', 'UUENCODE', 'HTML-ENTITIES', 'Quoted-Printable', '7bit', '8bit')) ); $header = array( 'Accept: '.implode(', ', $accept['type']), 'Accept-Charset: '.implode(', ', $accept['charset']), ); $encoding = null; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); $response = curl_exec($curl); if (!$response) { // error fetching the response } else { $offset = strpos($response, "\r\n\r\n"); $header = substr($response, 0, $offset); if (!$header || !preg_match('/^Content-Type:\s+([^;]+)(?:;\s*charset=(.*))?/im', $header, $match)) { // error parsing the response } else { if (!in_array(strtolower($match[1]), array_map('strtolower', $accept['type']))) { // type not accepted } $encoding = trim($match[2], '"\''); } if (!$encoding) { $body = substr($response, $offset + 4); if (preg_match('/^<\?xml\s+version=(?:"[^"]*"|\'[^\']*\')\s+encoding=("[^"]*"|\'[^\']*\')/s', $body, $match)) { $encoding = trim($match[1], '"\''); } } if (!$encoding) { $encoding = 'utf-8'; } else { if (!in_array($encoding, array_map('strtolower', $accept['charset']))) { // encoding not accepted } if ($encoding != 'utf-8') { $body = mb_convert_encoding($body, 'utf-8', $encoding); } } $simpleXML = simplexml_load_string($body, null, LIBXML_NOERROR); if (!$simpleXML) { // parse error } else { echo $simpleXML->asXML(); } } 

Обнаружение кодировки сложно.

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

До тех пор, пока вы имеете дело только с западноевропейскими языками, три основных кодировки, которые следует учитывать, – utf-8 , iso-8859-1 и cp-1252 . Поскольку они являются значениями по умолчанию для многих платформ, они также, скорее всего, ошибочно сообщаются. Например. если люди используют разные кодировки, они, вероятно, будут откровенны в этом, потому что иначе их программное обеспечение будет ломаться очень часто. Поэтому хорошей стратегией является доверие к провайдеру, если только кодировка не объявлена ​​как одна из этих трех. Вы все равно должны удвоить, что это действительно действительно, используя mb_check_encoding (обратите внимание, что действительный не то же самое, что и есть – тот же ввод может быть действителен для многих кодировок). Если это один из них, вы можете использовать mb_detect_encoding чтобы различать их. К счастью, это довольно детерминировано; Вам просто нужно использовать правильную последовательность обнаружения, которая является UTF-8,ISO-8859-1,WINDOWS-1252 .

После того, как вы обнаружили кодировку, вам необходимо преобразовать ее во внутреннее представление ( UTF-8 – единственный разумный выбор). Функция utf8_encode преобразует ISO-8859-1 в UTF-8 , поэтому она может использоваться только для этого конкретного типа ввода. Для других кодировок используйте mb_convert_encoding .

В этом чит-лист перечислены некоторые общие оговорки, связанные с обработкой UTF-8 в PHP: http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

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

 function detectUTF8($string) { return preg_match('%(?: [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte |\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte |\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates |\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 |[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 |\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )+%xs', $string); } 

Очень хороший способ реализации функции isUTF8 можно найти на php.net :

 function isUTF8($string) { return (utf8_encode(utf8_decode($string)) == $string); } 

Немного хедз-ап, вы сказали, что «ß» должно отображаться как «ÂŸ» в вашей базе данных.

Вероятно, это связано с тем, что вы используете базу данных с кодировкой символов latin1 или, возможно, неправильно настроено соединение php-mysql, это означает, что php полагает, что ваш mysql настроен на использование utf-8, поэтому он отправляет данные как utf8, но ваш mysql belives php отправляет данные, закодированные как iso-8859-1, поэтому он может снова попытаться кодировать ваши отправленные данные как utf-8, вызывая такие проблемы.

Взгляните на это, может помочь вам: http://php.net/manual/en/function.mysql-set-charset.php

Ваша кодировка выглядит так, как будто вы закодированы в UTF-8 дважды ; то есть с некоторой другой кодировки, в UTF-8 и снова в UTF-8. Как будто у вас есть iso-8859-1, преобразованный из iso-8859-1 в utf-8 и обработанный новой строкой как iso-8859-1 для другого преобразования в UTF-8.

Вот несколько псевдокодов того, что вы сделали:

 $inputstring = getFromUser(); $utf8string = iconv($current_encoding, 'utf-8', $inputstring); $flawedstring = iconv($current_encoding, 'utf-8', $utf8string); 

Ты должен попытаться:

  1. обнаруживать кодировку с использованием mb_detect_encoding() или того, что вы хотите использовать
  2. если это UTF-8, конвертировать в iso-8859-1 и повторить шаг 1
  3. наконец, конвертировать обратно в UTF-8

Это предполагает, что в «среднем» преобразовании вы использовали iso-8859-1. Если вы использовали windows-1252, то конвертируйте в windows-1252 (latin1). Исходная кодировка источника не важна; тот, который вы использовали в ошибочном, второе преобразование.

Это мое предположение о том, что произошло; есть еще немного, что вы могли бы сделать, чтобы получить четыре байта вместо одного расширенного байта ASCII.

Немецкий язык также использует iso-8859-2 и windows-1250 (latin2).

Вам нужно проверить кодировку на входе, поскольку ответы могут быть закодированы с различными кодировками.
Я заставляю все содержимое отправляться в UTF-8, выполняя обнаружение и перевод, используя следующую функцию:

 function fixRequestCharset() { $ref = array( &$_GET, &$_POST, &$_REQUEST ); foreach ( $ref as &$var ) { foreach ( $var as $key => $val ) { $encoding = mb_detect_encoding( $var[ $key ], mb_detect_order(), true ); if ( !$encoding ) continue; if ( strcasecmp( $encoding, 'UTF-8' ) != 0 ) { $encoding = iconv( $encoding, 'UTF-8', $var[ $key ] ); if ( $encoding === false ) continue; $var[ $key ] = $encoding; } } } } 

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

Это просто: когда вы получаете что-то не UTF8, вы должны ENCODE, что INTO utf8.

Итак, когда вы загружаете определенный канал, который ISO-8859-1 анализирует его через utf8_encode.

Однако, если вы загружаете канал UTF8, вам ничего не нужно делать.

Разработка кодировки символов RSS-каналов кажется сложной . Даже обычные веб-страницы часто опускают или лгут о своей кодировке.

Таким образом, вы можете попытаться использовать правильный способ обнаружения кодировки, а затем вернуться к некоторой форме автоматического обнаружения (угадывания).

Я знаю, что это более старый вопрос, но я считаю, что полезный ответ никогда не болит. У меня возникли проблемы с моей кодировкой между настольными приложениями, SQLite и GET / POST-переменными. Некоторые из них будут в UTF-8, некоторые из них будут в ASCII, и в основном все будет запутано, когда будут задействованы иностранные персонажи.

Вот мое решение. Он сглаживает ваш GET / POST / REQUEST (я пропустил файлы cookie, но вы можете добавить их, если это необходимо) при каждой загрузке страницы перед обработкой. Он хорошо работает в заголовке. PHP будет выдавать предупреждения, если он не может автоматически определить исходную кодировку, поэтому эти предупреждения подавляются с помощью @.

 //Convert everything in our vars to UTF-8 for playing nice with the database... //Use some auto detection here to help us not double-encode... //Suppress possible warnings with @'s for when encoding cannot be detected try { $process = array(&$_GET, &$_POST, &$_REQUEST); while (list($key, $val) = each($process)) { foreach ($val as $k => $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = $v; $process[] = &$process[$key][@mb_convert_encoding($k,'UTF-8','auto')]; } else { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = @mb_convert_encoding($v,'UTF-8','auto'); } } } unset($process); } catch(Exception $ex){} с //Convert everything in our vars to UTF-8 for playing nice with the database... //Use some auto detection here to help us not double-encode... //Suppress possible warnings with @'s for when encoding cannot be detected try { $process = array(&$_GET, &$_POST, &$_REQUEST); while (list($key, $val) = each($process)) { foreach ($val as $k => $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = $v; $process[] = &$process[$key][@mb_convert_encoding($k,'UTF-8','auto')]; } else { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = @mb_convert_encoding($v,'UTF-8','auto'); } } } unset($process); } catch(Exception $ex){} с //Convert everything in our vars to UTF-8 for playing nice with the database... //Use some auto detection here to help us not double-encode... //Suppress possible warnings with @'s for when encoding cannot be detected try { $process = array(&$_GET, &$_POST, &$_REQUEST); while (list($key, $val) = each($process)) { foreach ($val as $k => $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = $v; $process[] = &$process[$key][@mb_convert_encoding($k,'UTF-8','auto')]; } else { $process[$key][@mb_convert_encoding($k,'UTF-8','auto')] = @mb_convert_encoding($v,'UTF-8','auto'); } } } unset($process); } catch(Exception $ex){} 

Интересная вещь о mb_detect_encoding и mb_convert_encoding заключается в том, что порядок кодировок, которые вы предлагаете, имеет значение:

 // $input is actually UTF-8 mb_detect_encoding($input, "UTF-8", "ISO-8859-9, UTF-8"); // ISO-8859-9 (WRONG!) mb_detect_encoding($input, "UTF-8", "UTF-8, ISO-8859-9"); // UTF-8 (OK) 

Таким образом, вы можете использовать определенный порядок при указании ожидаемых кодировок. Тем не менее, имейте в виду, что это не является надежным.

Я проверял решения для кодирования с AGES, и эта страница, вероятно, является завершением лет поиска! Я протестировал некоторые из упомянутых вами предложений, и вот мои заметки:

Это моя тестовая строка:

это «wròng wrìtten» string bùt I nèed to pù 'sòme' special chàrs, чтобы увидеть thèm, convertèd by fùnctìon !! & это оно!

Я делаю INSERT, чтобы сохранить эту строку в БД в поле, которое установлено как utf8_general_ci

Шифр моей страницы – UTF-8

Если я сделаю INSERT именно так, в моей БД у меня есть некоторые символы, вероятно, идущие с Марса … поэтому мне нужно преобразовать их в какой-то «нормальный» UTF-8. Я пробовал utf8_encode() но все еще utf8_encode() символы вторгались в мою базу данных …

Поэтому я попытался использовать функцию forceUTF8 размещенную по номеру 8, но в DB сохраненная строка выглядит следующим образом:

это «wrà ² wrìtten» string bùt I nèed to pù 'sà ²me' специальные чары, чтобы увидеть thèm, convertèd by fùnctìon !! & это оно!

Поэтому, собрав еще одну информацию на этой странице и объединив ее с другой информацией на других страницах, я решил проблему с этим решением:

 $finallyIDidIt = mb_convert_encoding( $string, mysql_client_encoding($resourceID), mb_detect_encoding($string) ); 

Теперь в моей базе данных у меня есть строка с правильной кодировкой.

ПРИМЕЧАНИЕ. Только отметить, чтобы позаботиться о функции mysql_client_encoding ! Вы должны быть подключены к БД, потому что эта функция требует идентификатора ресурса в качестве параметра.

Но хорошо, я просто делаю это перекодирование перед моим INSERT, поэтому для меня это не проблема.

Надеюсь, это поможет кому-то, как эта страница, помогла мне!

Спасибо всем!

Mauro

php.net/ mb_detect_encoding

 echo mb_detect_encoding($str, "auto"); 

или

 echo mb_detect_encoding($str, "UTF-8, ASCII, ISO-8859-1"); 

я действительно не знаю, каковы результаты, но я бы посоветовал вам просто взять некоторые из ваших каналов с разными кодировками и попробовать, если mb_detect_encoding работает или нет.

Обновить
auto сокращен для «ASCII, JIS, UTF-8, EUC-JP, SJIS». он возвращает обнаруженную кодировку, которую вы можете использовать для преобразования строки в utf-8 с помощью значка .

 <?php function convertToUTF8($str) { $enc = mb_detect_encoding($str); if ($enc && $enc != 'UTF-8') { return iconv($enc, 'UTF-8', $str); } else { return $str; } } ?> 

Я не тестировал его, поэтому никаких гарантий. и, возможно, есть более простой способ.

@harpax, который работал для меня. В моем случае это достаточно хорошо:

 if (isUTF8($str)) { echo $str; } else { echo iconv("ISO-8859-1", "UTF-8//TRANSLIT", $str); } 

После сортировки ваших php-скриптов, не забудьте сказать mysql, какую кодировку вы передаете, и хотели бы получить ее.

Пример: установить набор символов utf8

Передача данных utf8 в таблицу latin1 в сеансе ввода-вывода latin1 дает эти неприятные птичьи птицы. Я вижу это каждый день в магазинах торговли. Назад и четвертое может показаться правильным. Но phpmyadmin покажет правду. Говоря mysql, какая кодировка, которую вы передаете, будет обрабатывать преобразование данных mysql для вас.

Как восстановить существующие скремблированные данные mysql – это еще один вопрос для обсуждения. 🙂

Эта версия предназначена для немецкого языка, но вы можете модифицировать $ CHARSETS и $ TESTCHARS

 class CharsetDetector { private static $CHARSETS = array( "ISO_8859-1", "ISO_8859-15", "CP850" ); private static $TESTCHARS = array( "€", "ä", "Ä", "ö", "Ö", "ü", "Ü", "ß" ); public static function convert($string) { return self::__iconv($string, self::getCharset($string)); } public static function getCharset($string) { $normalized = self::__normalize($string); if(!strlen($normalized))return "UTF-8"; $best = "UTF-8"; $charcountbest = 0; foreach (self::$CHARSETS as $charset) { $str = self::__iconv($normalized, $charset); $charcount = 0; $stop = mb_strlen( $str, "UTF-8"); for( $idx = 0; $idx < $stop; $idx++) { $char = mb_substr( $str, $idx, 1, "UTF-8"); foreach (self::$TESTCHARS as $testchar) { if($char == $testchar) { $charcount++; break; } } } if($charcount>$charcountbest) { $charcountbest=$charcount; $best=$charset; } //echo $text."<br />"; } return $best; } private static function __normalize($str) { $len = strlen($str); $ret = ""; for($i = 0; $i < $len; $i++){ $c = ord($str[$i]); if ($c > 128) { if (($c > 247)) $ret .=$str[$i]; elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($c > 191) $bytes = 2; else $ret .=$str[$i]; if (($i + $bytes) > $len) $ret .=$str[$i]; $ret2=$str[$i]; while ($bytes > 1) { $i++; $b = ord($str[$i]); if ($b < 128 || $b > 191) {$ret .=$ret2; $ret2=""; $i+=$bytes-1;$bytes=1; break;} else $ret2.=$str[$i]; $bytes--; } } } return $ret; } private static function __iconv($string, $charset) { return iconv ( $charset, "UTF-8" , $string ); } } 

Получите кодировку из заголовков и преобразуйте ее в utf-8.

 $post_url='http://website.domain'; /// Get headers //////////////////////////////////////////////////////////// function get_headers_curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 15); $r = curl_exec($ch); return $r; } $the_header = get_headers_curl($post_url); /// check for redirect ///////////////////////////////////////////////// if (preg_match("/Location:/i", $the_header)) { $arr = explode('Location:', $the_header); $location = $arr[1]; $location=explode(chr(10), $location); $location = $location[0]; $the_header = get_headers_curl(trim($location)); } /// Get charset ///////////////////////////////////////////////////////////////////// if (preg_match("/charset=/i", $the_header)) { $arr = explode('charset=', $the_header); $charset = $arr[1]; $charset=explode(chr(10), $charset); $charset = $charset[0]; } /////////////////////////////////////////////////////////////////////////////// // echo $charset; if($charset && $charset!='UTF-8') { $html = iconv($charset, "UTF-8", $html); } 

Ÿ – Mojibake для ß . В вашей базе данных у вас может быть hex

 DF if the column is "latin1", C39F if the column is utf8 -- OR -- it is latin1, but "double-encoded" C383C5B8 if double-encoded into a utf8 column 

Вы не должны использовать какие-либо функции кодирования / декодирования в PHP; вместо этого вы должны правильно настроить базу данных и соединение с ней.

Если MySQL задействован, см.: Неисправность с символами utf8; я не вижу того, что я хранил

Я нахожу решение здесь http://deer.org.ua/2009/10/06/1/

 class Encoding { /** * http://deer.org.ua/2009/10/06/1/ * @param $string * @return null */ public static function detect_encoding($string) { static $list = ['utf-8', 'windows-1251']; foreach ($list as $item) { try { $sample = iconv($item, $item, $string); } catch (\Exception $e) { continue; } if (md5($sample) == md5($string)) { return $item; } } return null; } } $content = file_get_contents($file['tmp_name']); $encoding = Encoding::detect_encoding($content); if ($encoding != 'utf-8') { $result = iconv($encoding, 'utf-8', $content); } else { $result = $content; } 

Я считаю, что @ – это плохое решение, и внести некоторые изменения в решение от deer.org.ua;

Самый проголосовавший ответ не работает. Вот моя и надеюсь, что это поможет.

 function toUTF8($raw) { try{ return mb_convert_encoding($raw, "UTF-8", "auto"); }catch(\Exception $e){ return mb_convert_encoding($raw, "UTF-8", "GBK"); } } 

Когда вы пытаетесь обрабатывать несколько языков, таких как японский и корейский, вы можете столкнуться с проблемами. mb_convert_encoding с параметром «auto» не работает. Установка mb_detect_order ('ASCII, UTF-8, JIS, EUC-JP, SJIS, EUC-KR, UHC') не помогает, так как он неправильно обнаружит EUC- *.

Я пришел к выводу, что до тех пор, пока входные строки поступают из HTML, он должен использовать «charset» в метаэлементе. Я использую простой HTML DOM Parser, потому что он поддерживает недопустимый HTML.

Следующий фрагмент извлекает элемент заголовка с веб-страницы. Если вы хотите конвертировать всю страницу, вы можете удалить некоторые строки.

 <?php require_once 'simple_html_dom.php'; echo convert_title_to_utf8(file_get_contents($argv[1])), PHP_EOL; function convert_title_to_utf8($contents) { $dom = str_get_html($contents); $title = $dom->find('title', 0); if (empty($title)) { return null; } $title = $title->plaintext; $metas = $dom->find('meta'); $charset = 'auto'; foreach ($metas as $meta) { if (!empty($meta->charset)) { // html5 $charset = $meta->charset; } else if (preg_match('@charset=(.+)@', $meta->content, $match)) { $charset = $match[1]; } } if (!in_array(strtolower($charset), array_map('strtolower', mb_list_encodings()))) { $charset = 'auto'; } return mb_convert_encoding($title, 'UTF-8', $charset); } 

У меня была такая же проблема с phpQuery ( ISO-8859-1 вместо UTF-8 ), и этот хак помог мне:

 $html = '<?xml version="1.0" encoding="UTF-8" ?>' . $html; 

mb_internal_encoding('UTF-8') , phpQuery::newDocumentHTML($html, 'utf-8') , mbstring.internal_encoding и другие манипуляции не phpQuery::newDocumentHTML($html, 'utf-8') никакого эффекта.

Попробуйте без 'auto'

То есть:

 mb_detect_encoding($text) 

вместо:

 mb_detect_encoding($text, 'auto') 

Более подробную информацию можно найти здесь: mb_detect_encoding