PHP: Преобразуйте вывод curl_exec в UTF8

Я хотел бы только работать с UTF8. Проблема, я не знаю набора символов каждой веб-страницы. Как я могу обнаружить его и преобразовать в UTF8?

 true,
);
curl_setopt_array($ch, $options);
$data = curl_exec($ch);

// $data = magic($data);

print $data;

Посмотрите это в: http://paulisageek.com/tmp/curl-utf8

Что magic()?

9
задан Paul Tarjan 28 March 2010 в 01:39
поделиться

4 ответа

Следуя совету Гамбо и Пекки, я написал curl_exec_utf8

/** The same as curl_exec except tries its best to convert the output to utf8 **/
function curl_exec_utf8($ch) {
    $data = curl_exec($ch);
    if (!is_string($data)) return $data;

    unset($charset);
    $content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);

    /* 1: HTTP Content-Type: header */
    preg_match( '@([\w/+]+)(;\s*charset=(\S+))?@i', $content_type, $matches );
    if ( isset( $matches[3] ) )
        $charset = $matches[3];

    /* 2: <meta> element in the page */
    if (!isset($charset)) {
        preg_match( '@<meta\s+http-equiv="Content-Type"\s+content="([\w/]+)(;\s*charset=([^\s"]+))?@i', $data, $matches );
        if ( isset( $matches[3] ) ) {
            $charset = $matches[3];
            /* In case we want do do further processing downstream: */
            $data = preg_replace('@(<meta\s+http-equiv="Content-Type"\s+content="[\w/]+\s*;\s*charset=)([^\s"]+)@i', '$1utf-8', $data, 1);
        }
    }

    /* 3: <xml> element in the page */
    if (!isset($charset)) {
        preg_match( '@<\?xml.+encoding="([^\s"]+)@si', $data, $matches );
        if ( isset( $matches[1] ) ) {
            $charset = $matches[1];
            /* In case we want do do further processing downstream: */
            $data = preg_replace('@(<\?xml.+encoding=")([^\s"]+)@si', '$1utf-8', $data, 1);
        }
    }

    /* 4: PHP's heuristic detection */
    if (!isset($charset)) {
        $encoding = mb_detect_encoding($data);
        if ($encoding)
            $charset = $encoding;
    }

    /* 5: Default for HTML */
    if (!isset($charset)) {
        if (strstr($content_type, "text/html") === 0)
            $charset = "ISO 8859-1";
    }

    /* Convert it if it is anything but UTF-8 */
    /* You can change "UTF-8"  to "UTF-8//IGNORE" to 
       ignore conversion errors and still output something reasonable */
    if (isset($charset) && strtoupper($charset) != "UTF-8")
        $data = iconv($charset, 'UTF-8', $data);

    return $data;
}

Регулярные выражения в основном взяты из http: // nadeausoftware .com / article / 2007/06 / php_tip_how_get_web_page_content_type

25
ответ дан 4 December 2019 в 07:22
поделиться

Конвертировать очень просто. Обнаружение - самая сложная часть. Вы можете попробовать mb_detect_encoding , но это очень шаткий метод, он буквально «угадывает» тип контента и, как отмечает @troelskn в комментариях, может в лучшем случае угадать «грубые» различия (это многобайтовая кодировка ?), но не может обнаружить нюансы схожих наборов символов.

Правильным способом будет IMO:

  • Интерпретация любых content-type Meta-тегов на странице
  • Интерпретация любых заголовков content-type , отправленных сервером
  • Если это ничего не дает, попробуйте «обнюхать» кодировку с помощью mb_detect_encoding ()
  • Если это ничего не даст, вернитесь к определенному по умолчанию (возможно, ISO-8859-1, возможно, UTF-8).

В отличие от рекомендаций в ответе @ Gumbo, я лично считаю, что метатеги должны иметь приоритет над заголовками сервера, потому что я почти уверен, что наличие метатега является более надежным индикатором фактического кодирования страница, чем настройка сервера, некоторые операторы сайта даже не знают, как изменить. Однако кажется, что правильным способом является обработка заголовков типа содержимого с более высоким приоритетом.

Для первого, я думаю, вы можете использовать get_meta_tags () . Последнее вы уже должны получить из curl, вам просто нужно его проанализировать. Здесь - полный пример того, как систематически обрабатывать заголовки ответа, обслуживаемые cURL.

Преобразование будет осуществляться с использованием iconv :

$new_content = iconv("incoming-charset", "utf-8", $content);
4
ответ дан 4 December 2019 в 07:22
поделиться

Существует определенный порядок как указать кодировку символов в HTML:

[...] соответствующие агенты пользователей должны соблюдать следующие приоритеты при определении кодировки символов документа (от самого высокого приоритета к самому низкому):

  1. Параметр HTTP "charset" в поле "Content-Type".
  2. Объявление META с параметром "http-equiv", установленным на "Content-Type", и значением, установленным для "charset".
  3. Атрибут charset, установленный на элементе, обозначающем внешний ресурс.

Если объявление кодировки символов отсутствует, HTTP определяет ISO 8859-1 как кодировку символов по умолчанию. Вы можете либо использовать эту кодировку по умолчанию для HTML, либо просто отказаться обрабатывать ответ.

Для XHTML в качестве источника кодировки дополнительно используется декларация XML:

В документе XML кодировка символов документа указывается в декларации XML (например, ). Для переносимого представления документов с определенными кодировками символов лучше всего убедиться, что веб-сервер предоставляет правильные заголовки. Если это невозможно, то документ, который хочет явно установить свою кодировку символов, должен включать в XML декларацию кодировки и meta http-equiv заявление (например, ). В XHTML-согласованных агентах пользователя значение объявления кодировки в объявлении XML имеет приоритет.

Если декларация кодировки символов отсутствует, XML определяет UTF-8 и UTF-16 как кодировки символов по умолчанию:

Если только кодировка не определяется протоколом более высокого уровня, то это также является фатальной ошибкой, если сущность XML не содержит декларации кодировки и ее содержимое не является законным UTF-8 или UTF-16.

Итак, подведем итог, порядок таков:

  1. HTTP параметр "charset" в поле "Content-Type".
  2. Объявление XML с атрибутом encoding.
  3. Объявление META с параметром "http-equiv", установленным на "Content-Type", и значением, установленным для "charset".

Если декларация кодировки символов отсутствует, вы можете принять ISO 8859-1 в качестве кодировки по умолчанию для HTML и должны принять UTF-8 или UTF-16 в качестве кодировки по умолчанию для XHTML.

0
ответ дан 4 December 2019 в 07:22
поделиться

Вы можете попробовать использовать что-то вроде:

http://www.php.net/manual/en/function.mb-detect-encoding.php

http://www.php.net/manual/en/function.mb-convert-encoding.php

Хотя это не является надежной защитой.

0
ответ дан 4 December 2019 в 07:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: