プログラミング雑記

【PHP】file_get_contensやcURLでページによってはエラーになる場合

goke

個人開発から世界を変えるようなプロダクトづくりを目指しています

はじめに

他のページのコンテンツを取得したいときにfile_get_contentsやcURLを使うとすごく簡単に実現することができますが、取得しようとするページによってエラーとなってしまうケースがありとても悩みました。
正確にはエラーではないのですが、どんなことが起きていたのかを下にまとめます。

ページによってコンテンツが取得できない

こんなコードを書いていました。

$target_website = "xxxxx";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_website);
$res =  curl_exec($ch);
$res_text = htmlspecialchars($res);
echo $res_text;

これを実行すると、成功するページもあれば失敗するページもあり、失敗する場合はエラーが表示されるのではなく、何も表示されません。
同じ処理をfile_get_contentsでも書けて、

$target_website = "xxxxx";
$res = @file_get_contents( $target_website );
$res_text = htmlspecialchars($res);
echo $res_text;

こんな感じにできますが、結果は変わらず。
あれこれ調べたところ、取得しようとするページのencodeに依存していることがわかりました。
つまり、PHPはUTF-8なのに取得しようとするページがSHIFT-JISだったりすると、htmlspecialcharsの処理がうまくいかず、結果が空になってしまうのです。

これを回避するためには、

$target_website = "xxxxx";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_website);
$res =  curl_exec($ch);
$res = mb_convert_encoding($res,"UTF-8",'ASCII, JIS, UTF-8, SJIS');//追加
$res_text = htmlspecialchars($res);
echo $res_text;

こんなふうに、mb_convert_encodingを入れてあげれば良いです。
ちなみに

$res = mb_convert_encoding($res,"UTF-8",'auto');

このように「auto」とすればいいのでは?と思うかもしれませんが、これだとうまくいかない場合があります。
下記にも記載がありますが、php.iniの言語設定によっては思った挙動にならないことがあるからです。

終わりに

結構ハマった内容でしたので上記にまとめてみました。
gokeでは100万ユーザーを目指したサービスづくりをしています。

  • この記事を書いた人

goke

個人開発から世界を変えるようなプロダクトづくりを目指しています

-プログラミング雑記