ボブです。
リモートファイルの取得といっても規模や用途は様々ですが、多くの場合は単純にfile_get_contents等で取得してしまえば、要件を満たせるでしょう。
しかし、バッチで大量のURLからクロールするケースや、複数のURLから取得した結果をリアルタイムで表示するようなケースでは、レスポンスの遅い接続先に全体の処理時間が引っ張られてしまうような事もあります。そんな場合には複数のURLから並列でファイルを取得したい所です。
PHPだとプロセス制御関数を使う方法やcURL 関数を使う方法があります。
下記は後者でのサンプルクラスです。
class SampleCrawler{
//並列リクエスト上限
var $_multi_request_number = 5;
//クロールしたいURLの一覧を
//array("url"=>$対象URL, "last_crawl_datetime"=>$最後にクロールした日時)
//で渡す
function crawlUrl($url_list){
foreach($url_list as $key=>$url){
//並列処理用リストに追加
$work_list[] = $url;
unset($url_list[$key]);
if(count($work_list) >= $this->_multi_request_number || !count($url_list)){
//マルチハンドラの作成
$mch = curl_multi_init();
foreach($work_list as $work){
//curlハンドラの作成
$ch = curl_init();
//正しい形式のURLであれば
if(($parsed_url = parse_url($work["url"])) && $work["url"]){
//リクエストヘッダの作成
$header[] = 'GET /'.$work["url"].' HTTP/1.1';
$header[] = 'Host: '.$parsed_url["host"];
$header[] = 'User-Agent: Sample Crawler - Version 0.1';
//クロールした事のあるURLならIf-Modified-Sinceヘッダを付ける
if($work["last_crawl_datetime"] != "0000-00-00 00:00:00"){
$time = strtotime($work["last_crawl_datetime"]);
$mod = date("r", $time - 3600 * 9);
$header[] = 'If-Modified-Since: '.$mod;
} else {
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
}
$header[] = 'Connection: close';
//d($header);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
unset($header);
curl_setopt($ch, CURLOPT_URL, $work["url"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILETIME, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);//5秒でタイムアウト
curl_setopt($ch, CURLOPT_FILETIME, 1);
//マルチハンドラに登録
curl_multi_add_handle($mch, $ch);
$ch_list[] = $ch;
}
}
//マルチハンドルで並列リクエスト
if($ch_list){
$running=null;
do {curl_multi_exec($mch, $running);} while ($running > 0);
foreach( $ch_list as $ch ) {
// ステータスとコンテンツ内容の取得
$status = curl_getinfo($ch);
//d($status);
//ステータスコードが正常系(2XX)であれば
if(substr($status["http_code"], 0, 1) == "2" && $status["size_download"]){
//取得したコンテンツを処理
$this->process($status["url"], curl_multi_getcontent($ch), $status);
}
//マルチハンドルからcurlハンドル削除
curl_multi_remove_handle($mch, $ch);
curl_close($ch);
}
}
//マルチハンドル閉じ
curl_multi_close($mch);
unset($ch_list);
unset($work_list);
}
}
}
//クロールで取得した文字列を処理
function process($url, $contents, $status){
}
}
取得したコンテンツに何らかの処理(パースなど)をする必要があれば、processメソッドをオーバーライドして実装します。




