2018年12月11日

【PHP】curlを使ったfile_get_contents。

file_get_contentsが若干遅いからcurlを使って高速化してfunction化。
	function file_cget_contents($address){
$ch = curl_init(); //初期化
curl_setopt($ch, CURLOPT_URL, $address); //URLの設定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //出力内容を受け取る設定
$result = curl_exec($ch); //データの取得
curl_close($ch); //cURLのクローズ

return $result; //データを返す
}
//使い方
$data = file_cget_contents('http://lcsious.com/');

どこかで拾ってきたはずcurlのfunctionなんだけど、元のページが見つからなかった。
このcgetはまんまfile_get_contentsの代わりとして使えて、半分の時間くらいで取得できる。
なおかつオプションをいろいろ設定できてfile_get_contentsよりも軽量化できる。
よく使う軽量化オプションはこちら。
		curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_REFERER, $ref_select);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);

CURLOPT_HEADERを使うとステータスコードが取得できるので、エラーが出た場合404なのか503なのか他の要因なのかを調べることができる。
CURLOPT_NOBODYはCURLOPT_HEADERを使った場合にソースコード自体は要らないことが多いので、そういう場合に使える。ただし〜 の間を取得しないんじゃなく、ステータスコード以外の全てを取得しない。CURLOPT_NOBODYを指定しただけでヘッダーのみ出力するらしい。
CURLOPT_USERAGENT、まんまuseragentを指定できる。今では少ないが、携帯(ガラケー)のみで見れるコンテンツとかの取得に使えた。今ではスマホのみしか見れないとかがあまりに少ないので、使い所はあんまり無いかも。
CURLOPT_REFERER、リファラーを偽装できる。取得するサイトのトップページからしか応答を受け付けないようなサイトで使える。
CURLOPT_TIMEOUT、応答時間が長すぎたらその時点でアクセスを切り上げる時間設定(秒)。多くのURLを取得するならタイムアウトを短めに取らないと長くなって時間が結構かかる。

大量のURLをリスト化して動かすようにした状態が以下。
基本はここの記述→PHPで複数のURLを404チェックする関数の速度比較 | ウダ2Blog
	$urls = null;
//省略するけど$urlsにurlを詰め込むforeachとか組む
if($urls != null){ //$urlsがnullじゃなかったら開始
$num_hoji = $saisyo_num;
//ここからcurl_multi
$mh = curl_multi_init();
$ch_list = array();
foreach($urls as $mykey => $url) {
$ch_list[$mykey] = curl_init($url);
curl_setopt($ch_list[$mykey], CURLOPT_HEADER, TRUE);
curl_setopt($ch_list[$mykey], CURLOPT_NOBODY, TRUE);
curl_setopt($ch_list[$mykey], CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch_list[$mykey], CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch_list[$mykey], CURLOPT_REFERER, $ref_select);
curl_setopt($ch_list[$mykey], CURLOPT_TIMEOUT, 5);
curl_multi_add_handle($mh, $ch_list[$mykey]);
}
$running = null;
do { curl_multi_exec($mh, $running); } while ( $running );
foreach($urls as $mykey => $url) {
$httpCode = curl_getinfo($ch_list[$mykey], CURLINFO_HTTP_CODE);
if (preg_match('/5[\d]{2}/',$httpCode)){
$url_echo[$mykey][] = $httpCode;
$url_echo[$mykey][] = 'サーバー負荷により停止しました。';
if (preg_match('/503/',$httpCode)){
break;
}
}
else if (preg_match('/200/',$httpCode)){
$url_echo[$mykey][] = $num_hoji;
$url_echo[$mykey][] = $urls[$mykey];
}
else if (preg_match('/404/',$httpCode)){
$url_notfound[$mykey][] = $num_hoji;
$url_notfound[$mykey][] = $urls[$mykey];
}
else {
$url_notfound[$mykey][] = $num_hoji;
$url_notfound[$mykey][] = $httpCode;
}
$num_hoji++;
curl_multi_remove_handle($mh, $ch_list[$mykey]);
curl_close($ch_list[$mykey]);
}
curl_multi_close($mh);
//ここまでcurl_multi
}

これはソシャゲの画像をひたすら確認するために作ったもので、連番.pngを2000枚くらい存在するかの調査のためのものでした。そのソシャゲが終わったので現状は使ってません。
これの良いところは毎回画像を取得するのではなく、ステータスコードだけを取得するのでサーバー側に不必要に負荷をかけないという点です。一時期モバマスが連番取得出来たので、サーバーに負荷がかかりすぎて連番画像をやめてちょっと複雑化した経緯があるので、そういう負荷対策をされにくいのと、そもそも負荷をほとんどかけないようにする点で非常に有用です。
最近はunity製ゲーム増えすぎて高画質pngをサーバーに直置きなんてことがほとんど無くなったので使える場面はなかなか少なくなりました。
タグ:Curl
posted by Lc at 21:17 | Comment(0) | PHP | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: