Проблемы с кодировкой GuzzleHTTP

Я пытаюсь использовать GuzzleHTTP 6 для очистки веб-страниц, и до сих пор я не смог найти решение для перепутанной кодировки в теле ответа.

Допустим, я хочу проанализировать веб-страницу, которая возвращает данные на разных языках.

Инициализация клиента

public function __construct() {
    $this->dataClient = new Client(['base_uri' => 'http://somewebsite.org/{language_code}']);
}

Использование клиента данных

$request = $this->dataClient->get('/endpoint/' . $data_query . '/');
$response = $request->getBody()->__toString();
$decoded = json_decode($response, true);
foreach ($decoded as $index => $data) {
    $decoded[$index] = str_replace(['<option', '>', '</option>'], '', $data);
}
return $decoded;

Проблемы:

  1. Если текст на английском языке, ответ выглядит почти нормально, за исключением того, что некоторые символы перепутаны.

    манипуляция, есть

Вместо

manipulation, there's
  1. Если я пытаюсь получить данные на любых других языках, я получаю вот что (данные на русском языке)

    Ð;Ð;°; Ð;¿;Ð;µ;Ñ;€Ð;²;Ñ;‹Ð;¹; Ð;²;Ð

Вместо

На первый взгляд

И проблема в том, что если вы просматриваете веб-сайт, все хорошо и красиво, но если вы попытаетесь его очистить, вы столкнетесь с этими проблемами. Пока не могу найти источник проблемы, ни utf8_decode, ни iconv не помогают решить проблему.
Приветствуются любые решения!

Итак, небольшое обновление. Это функция разбора:

public function processData($data_query) {
    $request = $this->dataClient->get('/endpoint/' . $data_query . '/');
    $response = $request->getBody()->__toString();
    // echo $response; - Everything is fine, no encoding problems
    // return $response; - Encoding problems
    $decoded = json_decode($response, true);
    // return $decoded; - Encoding problems
    foreach ($decoded as $index => $data) {
        $decoded[$index] = str_replace(['<option', '>', '</option>'], '', $data);
    }
    return $decoded; - Encoding Problems
}

Необработанные заголовки ответа

{
    Date: [
        "Wed, 08 Jun 2016 01:45:30 GMT"
    ],
    Server: [
        "Apache"
    ],
    X-Frame-Options: [
        "SAMEORIGIN"
    ],
    Retry-After: [
        "600"
    ],
    Content-Language: [
        "en-GB"
    ],
    Vary: [
        "Accept-Encoding"
    ],
    Transfer-Encoding: [
        "chunked"
    ],
    Content-Type: [
        "text/html;charset=UTF-8"
    ]
}

person Ivan Zhivolupov    schedule 08.06.2016    source источник
comment
Можете ли вы показать, какое значение имеет заголовок Content-Type в ответе? Должен (надеюсь) быть параметр charset. Что это говорит? Вы могли бы попытаться добавить заголовок Accept-Charset: UTF-8. Это должно заставить сервер кодировать данные в UTF-8, если они реализованы правильно.   -  person Brad Frost    schedule 08.06.2016
comment
{ Дата: [ 08 июня 2016 г., 01:28:18 по Гринвичу ], сервер: [ Apache ], параметры X-Frame: [ SAMEORIGIN ], повторная попытка после: [ 600 ], язык содержимого: [ en-GB ] , Vary: [ Accept-Encoding ], Transfer-Encoding: [ chunked ], Content-Type: [ text/html;charset=UTF-8 ] }   -  person Ivan Zhivolupov    schedule 08.06.2016
comment
Как именно вы проверяете ответ? Какова кодировка цели, на которую вы печатаете ответ?   -  person zerkms    schedule 08.06.2016
comment
Ну, это то, что я пытаюсь сделать на самом деле. Я обновлю основной пост новой информацией   -  person Ivan Zhivolupov    schedule 08.06.2016
comment
Итак, вы упомянули ниже, что все в порядке, если вы повторите ответ. Вы имеете в виду, что нет перепутанных символов utf-8?   -  person Brad Frost    schedule 08.06.2016
comment
Если ответ повторяется, все в порядке, если он декодируется/просто возвращается испорченным   -  person Ivan Zhivolupov    schedule 08.06.2016


Ответы (2)


У меня аналогичный случай (загрузить XML с помощью Guzzle и проанализировать с помощью SimpleXML), но я знаю, что источник был в ISO-8559-1, но результат анализа SimpleXML был зашифрован. Я пробовал много способов, только этот решил_:

$attribute = mb_convert_encoding((string) $attribute, 'ISO-8859-1', 'UTF-8');

Атрибут представляет собой некоторое значение узла XML. Я просто конвертирую из известной кодировки в ту, которую хочу. Надежда может помочь кому-то...

person Holzhey    schedule 06.04.2018

Прочитайте более старый ответ SO, размещенный здесь: Can Goutte/ Жрать принудительно в режиме UTF-8?. Да, упоминается использование utf8_decode(), но также и в сочетании с форком Guzzle. Взгляните на систему отслеживания проблем Guzzle, есть ли там проблема, похожая на вашу? Если это так, прокомментируйте это, чтобы узнать, исправят ли это основные разработчики. Вышеупомянутому сообщению SO уже 3 года, я был бы удивлен, если бы хаки и форки все еще были нужны, если бы проблема была настолько распространена.

Возможно, она была исправлена, и теперь вам нужно убедиться, что просканированная страница сама отправляет правильные заголовки кодировки. Обратите внимание, что существует порядок старшинства заголовков ответов. Я считаю, что важнее всего веб-сервер, а затем сам DOM, если эти заголовки не отправляются или опускаются в ответе веб-сервера. Но, пожалуйста, проверьте это, так как я не на 100%.

person theruss    schedule 08.06.2016
comment
Спасибо за комментарий! Я уже читал эту тему, и дело в следующем: 1. Поскольку проект довольно большой, мне не разрешено вносить какие-либо изменения в HTTP-клиент PHP 2. Обходной путь в этой теме не работает с текущей версией GuzzleHTTP. 3. Удаленный сервер возвращает text/html;charset=UTF-8 4. Локальный сервер настроен на режим UTF-8 5. Все запросы выполняются с использованием UTF-8 (по какой-то причине CP1251 также работает в IE) 6. Если вы повторите этот ответ, все будет хорошо, но если вы попытаетесь с ним работать, он будет испорчен - person Ivan Zhivolupov; 08.06.2016
comment
И если я пытаюсь «угадать» кодировку с помощью PHP (или любого другого инструмента), я получаю разные кодировки, но не UTF-8. Но я знаю, что это должно быть в UTF-8. Последними были CP850, CP851, MACчто-то и другие, так что я действительно потерялся в этом «зоопарке» кодировок. - person Ivan Zhivolupov; 08.06.2016
comment
ОК, поэтому он печатает ОК, но вы не можете с ним работать. Таким образом, существует разница, связанная с кодировкой, между тем, как вы печатаете/отображаете и работаете с ним. Можете ли вы рассказать нам некоторые подробности о том, как вы эхо и как вы работаете с ним? На данном этапе это больше похоже на проблему принимающей стороны. - person theruss; 08.06.2016
comment
Я обновил основной пост, добавил полную функцию в конец. Также предоставил некоторые комментарии - person Ivan Zhivolupov; 08.06.2016