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

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

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

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

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

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

  3. В других случаях "ß" сохраняется как "ß", то есть без каких-либо изменений. Тогда это также отображается неправильно.

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

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

Как мне сделать все одинаковое кодирование? Возможно с функцией mb_detect_encoding()? Могу ли я написать функцию для этого? Итак, мои проблемы:

  1. Как мне узнать, какую кодировку использует текст?
  2. Как мне преобразовать его в UTF-8 - какой бы ни была старая кодировка?

Будет ли функция, как эта работа?

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

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

Ответ 1

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

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

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

Я сделал это, потому что сервис давал мне все данные, смешивая UTF-8 и Latin1 в одной строке.

Использование:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It 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(), которая будет исправлять каждую строку UTF-8, которая выглядит искаженной.

Использование:

require_once('Encoding.php');
use \ForceUTF8\Encoding;  // It 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().

Ответ 2

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


Изменить Вот что я, вероятно, сделаю:

Id использовать 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();
    }
}

Ответ 3

Обнаружение кодировки затруднено.

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.

Ответ 4

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

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

Ответ 5

В этом чит-лист перечислены некоторые общие оговорки, связанные с обработкой 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);
}

Ответ 6

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

Вероятно, это связано с тем, что вы используете базу данных с кодировкой символов Latin-1 или, возможно, ваше соединение PHP-MySQL установлено неправильно, то есть P считает, что ваш MySQL настроен на использование UTF-8, поэтому он отправляет данные как UTF-8, но ваш MySQL полагает, что PHP отправляет данные, закодированные как ISO 8859-1, поэтому он может еще раз попытаться закодировать отправленные данные как UTF-8, вызывая такие проблемы.

Посмотрите на mysql_set_charset. Это может помочь вам.

Ответ 7

Ваша кодировка выглядит так, как будто вы дважды кодировали в 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 (Latin-2).

Ответ 8

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

Я принудительно отправляю весь контент в 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.

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

Вы можете настроить его под свои нужды.

Просто вызовите его перед использованием переменных.

Ответ 9

Интересная вещь о 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)

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

Ответ 10

Все просто: когда вы получаете что-то не UTF-8, вы должны закодировать это в UTF-8.

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

Однако, если вы выбираете канал UTF-8, вам не нужно ничего делать.

Ответ 11

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

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

Ответ 12

Я знаю, что это старый вопрос, но я считаю, что полезный ответ никогда не болит. У меня возникли проблемы с моей кодировкой между настольными приложениями, 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 @ 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){}

Ответ 13

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

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

это строка "с записью", но мне нужны специальные персонажи, чтобы увидеть их, конвертированные по !! & это!

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

Набор символов моей страницы - UTF-8.

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

Поэтому мне нужно конвертировать их в какой-то "вменяемый" UTF-8. Я попытался utf8_encode(), но все еще инопланетные символы вторгались в мою базу данных...

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

это "записанная" строка, которую я хочу написать специальным чарам, чтобы увидеть их, преобразовать в фонтан !! & это!

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

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

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

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

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

Ответ 14

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 с iconv.

<?php
function convertToUTF8($str) {
    $enc = mb_detect_encoding($str);

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

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

Ответ 15

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

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

Ответ 16

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

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

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

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

Ответ 17

Эта версия предназначена для немецкого языка, но вы можете модифицировать $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 );
}
}

Ответ 18

Получить кодировку из заголовков и преобразовать ее в 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); }

Ответ 19

Ÿ является 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; я не вижу того, что я хранил

Ответ 20

Я нахожу решение здесь 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;

Ответ 21

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

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

Ответ 22

Когда вы пытаетесь обрабатывать несколько языков, таких как японский и корейский, вы можете столкнуться с проблемами. 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);
}

Ответ 23

У меня была такая же проблема с 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 и другие манипуляции не вступили в силу.

Ответ 24

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

То есть:

mb_detect_encoding($text)

вместо:

mb_detect_encoding($text, 'auto')

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