PHPのcurl_multiによるHTTP並行リクエストを使い、「ディレクトリ型検索エンジンdtn」のディレクトリ登録サイトのリンク切れチェッカーを制作してみました。

この記事では、curl_multiのリクエスト処理でURLに対して接続をかけ、取得したサイトのステータスデータを配列に取り込み保存する流れについて説明したいと思います。curl_multiによるリクエスト処理と、get_headersによるHTTPレスポンス取得も比較しています。




カテゴリ登録サイトのリンク切れチェック

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

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

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

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

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

PHPでリンクチェッカー

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

get_headers()でHTMLを取得

昔のイメージでは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でHTMLを取得

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

http://をイメージしたcURLライブラリのロゴ
URLを使用してデータ転送するcURLライブラリ

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

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

あとはcurl_multi_execのお作法に沿い、先程の登録サイトURL配列を元に設定を作っていきます。

curl_setoptの設定項目

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のリクエスト処理で接続をかけ、サイトのステータスデータを配列に取り込むといった感じです。速度は全く問題ありません。

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

curl_multiについては、phpのマニュアルよりもこちらのサイト様の方がとても分かりやすかったです。

おわりに

curl_multiで取得したHTMLステータスが入った$linkstatus[] のデータと、先に取った$REG_URLs[]のデータを並べて表示させれば、これで簡易リンクチェッカーの出来上がりとなりました。

PHPでリンク先のHTTPステータスコードを取得するリンク切れチェッカー
リンク先のステータスをcURLを使って取得

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

ABOUT dtn.jp

この運営ブログをみてdtn.jpの運営サイトに興味をお持ちになった方は下記のリンク集からサイトをご参照ください。PHP・SQL・JS・HTML・CSSや様々なAPIでゼロから立ち上げたサイトを複数運営しています。

dtn.jp関連サイト

  • ディレクトリ型検索エンジンdtn大手は全てサービスを終了してしまい、中小でも運営を継続するところがほとんど無くなったディレクトリ型検索エンジンを、2002年から細々運営しております。今も申請されたサイトは実際に管理人が訪問して確認後に登録しています。是非登録どうぞ。
  • 猫ネコサーチエンジン猫・ペットサイト専用のディレクトリ型検索エンジンです。登録サイトはサイトのスクリーンショット付きでカテゴリに掲載をいたします。
  • 画像掲示板の泉画像・YouTube・ニコニコ動画・Tiktokの貼り付けが可能な匿名画像掲示板です。27ジャンルに分かれた掲示板に、それぞれ100スレッドまで立てることが可能です。
  • ツイータンTwitter APIを使って10分おきに収集したTwitterトレンドワード・人気ハッシュタグデータを、月別に集計してランキング形式で公開しています。年間トレンドワードも公開中。
  • Keyword Tool++Yahooショッピングや楽天のトレンドワードデータを日次収集し、EC系の人気キーワードをラインキング形式でご紹介しています。各ワードの検索ボリュームや関連語、24か月の検索ボリュームをグラフで確認が可能です。
  • 消費者金融の泉カードローン商品を取り扱う金融業者を一覧で比較可能としたサイトです。カテゴリ別、人気度別、限度額別、金利別に比較可能です。
  • TrendinGファッションブランドを人気アイテムヒット率でランキング化し、一覧でご紹介しているサイトです。

各サイトの開発方法などについて

各サイトの開発方法や運用トラブルについては、当ブログで不定期にご紹介しています。Twitterで新着記事のお知らせもしています。宜しければフォロー下さい。