これをお読みの方の中で、ディレクトリ型検索エンジンを運営している、といった方は殆どいらっしゃらないと思いますが、ディレクトリ型サイトを運営していて困ることの一つに登録サイトのリンク切れといったものがあります。

サイトが閉鎖となったり、ドメイン変更やURLが移転されたりと、リンク切れに至る理由は様々あるようですが、中にはYahooジオシティーズのように、無料スペースを使ってサイトを頑張っていたのに、スパッと閉鎖されてしまったものも多々見られました。

せっかく申請いただいたサイトを一つ一つチェックして頑張ってディレクトリを作っていっても、カテゴリにリンク切れが出てしまうと印象も悪く、多分SEO的にも悪影響だろうとは思うので、このリンク切れチェックも必要になってくるわけです。

とはいえ、登録申請すら10,000サイト以上たまっているようなこの状況では、流石にそこまで手が回るはずもなく、、カテゴリを日に頑張って3つチェックしたとしても、900以上のカテゴリを見るには年近い時間がかかってしまう感じで、正直なところ日に1カテゴリもチェックすらできておりませんでした。

そこで、18年目に突入ということもありまして、かつてのYahooカテゴリでも登録サイト向けに頻繁に走っていたクローラーのようなLINKステータスチェッカーをPHPで作ってみようと思い立ったというお話です。前置き長くて失礼致しました。

まずはじめに、ステータスをチェックするには外部のURLからデータを取得しないと話になりませんので、PHPで外部データの取得からスタートです。

昔のイメージではfile_get_contents()でという感じでしょうが、今ではget_headers()cURLを使ってという方が一般的のようですので、まずは get_headers() でお試ししてみました。

$URL = 'https://www.dtn.jp/';
$headers = @get_headers($URL);
$headers[0] //ここにステータスが入ってます

カテゴリに登録されたサイトURLをSQLで一つ引っ張りだし、 get_headers() に投げてステータスを取ってみましたが、全く問題なくステータスを取ることができました。$headersには、 $headers[0] => HTTP/1.1 200 OK’ のような感じでしっかりステータスが入っています。ということで、早速これを100サイト程度ループで回してみましたが、途端にPHPが「504 Gateway Time-outを吐き出してしまいました。。。

php.inimax_execution_timeをいくらか増やしてみましたが、それでも全くダメという感じです。外部に順次接続しているので、仕方ないかもしれないですが。。

ということで、本命のcurl_multiによる並列処理でやってみることにしました。 http://にちなんだcURLのロゴは微妙ですが気にせずどうぞ。

まずは先程同様にPDOでSQLから取ってきた登録URL情報を配列に入れておきます。

while($rows = $prepare -> fetch()){
  $REG_URLs[] = $rows["url"];
}

その後はcurl_multi_execのお作法に沿って先程の登録サイトURLの配列を元に設定を作っていけば良さそうです。cURLのオプションを入れるcurl_setoptは設定項目が多数あるので適当に必要そうなものを追加しておきました。ヘッダを取るのでCURLOPT_HEADERをTRUEとして、本文は不要なのでCURLOPT_NOBODYもTRUEにする等々でしょうか。

//マルチハンドル初期化
$mh = curl_multi_init();
//URLのセット
foreach($REG_URLs as $URL) {
	$ch = curl_init();
	curl_setopt_array($ch, array(
    		CURLOPT_URL               => $URL,
    		CURLOPT_HEADER            => TRUE,
    		CURLOPT_NOBODY            => TRUE,
    		CURLOPT_FOLLOWLOCATION    => FALSE,
    		CURLOPT_USERAGENT         => "*******",
    		CURLOPT_CONNECTTIMEOUT    => 100,
    		CURLOPT_RETURNTRANSFER    => TRUE,
		CURLOPT_SSL_VERIFYPEER    => FALSE,
		CURLOPT_TIMEOUT           => 100
	));
	curl_multi_add_handle($mh, $ch);
}

ここまできたら、あとはcurl_multiのリクエスト処理で接続をかけ、サイトのステータスデータを配列に取り込むといった感じです。curl_multiについては、phpのマニュアルよりもこちらのサイト様の方がとても分かりやすかったです。

//HEADER情報取得
foreach($ch_array as $ch){
	↓この配列にステータスを取り込み
	$linkstatus[] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	curl_multi_remove_handle($mh, $ch);
	curl_close($ch);
}

最後に、取得した$linkstatus[] の配列データと、先に取った$REG_URLs[]の配列データを並べて表示させておけば簡易リンクチェッカーの出来上がりとなりました。

HTTPのステータスはたまに0が入っている時もありましたが、2xx、3xx、4xxと概ねキッチリ取ることができていました。できたリンクチェッカーを見ると、やはり403が山ほどあり、1,000URL分を一覧出力したら大変なことになったので、日に100URLずつのチェックという感じにしておきました。カテゴリメンテナンスも頑張りたいと思います。

スポンサーリンク