6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Goutteで文字化け

Last updated at Posted at 2015-10-02

現象

あるサイトをスクレイピングしていて、ajaxで取得されるページの内容を取得しようとしたところ
突然 $crawler->html() したときに日本語が文字化ける現象に遭遇。

文字的には è‰åŠ /東武伊勢崎・大師線 とかそんな感じ。

原因

「取得しようとしていたページにcharsetがない」

実際はUTF-8なんだけど、headerにもmetaにも明示されてない。
で処理を追っていくと Synfony\ComponetnDomCrawler\Crawler::addContent() にて

/**
* Adds HTML/XML content.
*
* If the charset is not set via the content type, it is assumed
* to be ISO-8859-1, which is the default charset defined by the
* HTTP 1.1 specification.
*
* @param string $content A string to parse as HTML/XML
* @param null|string $type The content type of the string
*/

ということでHTTP 1.1に従ってデフォルトはISO-8859-1にしますよ、と。

対策

単純にレスポンスをmb_convert_encodingしてもダメだったので
以下のような継承クラスを定義してこっちを使う。

<?php namespace MyNameSpace;
use Goutte\Client;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\BrowserKit\Response;

class GoutteClientCustom extends Client
{
    protected function createResponse(ResponseInterface $response)
    {
        $headers = $response->getHeaders();
        if (!isset($headers['Content-Type'])) {
            $headers['Content-Type'][0] = 'text/html; charset=UTF-8';
        } elseif (stripos($headers['Content-Type'][0], 'charset=') === false) {
            if (trim($headers['Content-Type'][0]) && substr(trim($headers['Content-Type'][0]), -1) !== ';') {
                $headers['Content-Type'][0] = trim($headers['Content-Type'][0]) . ';';
            }
            $headers['Content-Type'][0] .= ' charset=UTF-8';
        }
        return new Response((string) $response->getBody(), $response->getStatusCode(), $headers);
    }
}

headerに無理やり charset=UTF-8 をねじ込む。
とりえあずはこれでうまくいった。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?