概要
前回は、robots.txtを取得する処理を作成しました。
今回は、robots.txt
からクロール拒否されていないかチェックする処理を作成したいと思います。
robots.txtの構成
まずは、サンプルとしてQiitaのrobots.txtを拝借しました。
Qiitaのrobots.txtは以下のような構成になっています。
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
User-agent: *
Disallow: /*/edit$
Disallow: /api/*
Disallow: /graphql$
Disallow: /policies/td-optout$
Disallow: /search
Disallow: *.md
Disallow: */items/*/revisions
Disallow: */private/*/revisions
Allow: /api/*/docs$
Sitemap: https://cdn.qiita.com/sitemap-https/sitemap.xml.gz
robots.txtの見方
User-agent
クローラーの名前を指定します。
User-agent: *
とすると、すべてのクローラーに伝える内容となります。
User-agent: GoogleBot
とすると、GoogleBotのみに伝える内容となります。
以下のように書くと、それぞれのクローラーに対して別の内容を伝えることができます。
User-agent: *
...
...
...
User-agent: GoogleBot
...
...
...
Disallow
クロールを拒否するときに指定します。
Allow
クロールを許可するときに指定します。
デフォルト許可なので基本的にあまり意味はないと思われがちですが、以下のようにDisallowで禁止した一部を許可するときに有効です。
User-agent: *
Disallow: /api/*
Allow: /api/*/docs$
Sitemap
サイトマップの場所を知らせます。
クローラにホームページの構成を伝えるために使われます。
実装
クロールしたいURLがクロール可能かどうかをチェックするプログラムを実装します。
関数の作成
まずは、robots.txt
を一行ごとに配列に変換する関数です。
function lineBreakArray($text) {
$array = explode("\n", $text); // 改行ごとに分割
$array = array_map('trim', $array); // 各行にtrim()をかける
$array = array_filter($array, 'strlen'); // 文字数が0の行を取り除く
$array = array_values($array); // キーを連番に振る
return $array;
}
User-agent
やDisallow
といった項目を抽出する関数です。
function itemExtraction($value) {
$item = preg_replace("/^(.*?):.+/", "$1", $value);// 項目を抽出する
$item = preg_replace("/^(\s| )/", "", $item); // スペース削除
$item = mb_strtolower($item); // 小文字にする
return $item;
}
User-agent
やDisallow
の:(コロン)より右側の情報を抽出する関数です。
function conditionExtraction($value) {
$condition = preg_replace("/.*?:(.+)/", "$1", $value); // 判定を抽出する
$condition = preg_replace("/#.*/", "", $condition); // コメントアウト以降を削る
$condition = preg_replace("/^(\s| )/", "", $condition); // スペース削除
return $condition;
}
URLがクロール許可されているかチェックする関数です。
/*
* robots.txtのチェックを行う
* 第三引数の$userAgentは省略可
*/
function robotsCheck($requestUrl, $robotsArray, $userAgent = "*") {
$crawl_flg = true;
if ($userAgent == "") {
$userAgent = "*";
}
if (array_key_exists($userAgent, $robotsArray)) { //指定されたuserAgentの場合
foreach ($robotsArray[$userAgent]['disallow'] as $key => $value) {
if (preg_match('~'. asteriskRegexp($value) .'~',$requestUrl)) {
$crawl_flg = false;
}
}
} elseif ($robotsArray['*'] ) { //指定されたuserAgentが無い場合は*を使う
foreach ($robotsArray['*']['disallow'] as $key => $value) {
if (preg_match('~'. asteriskRegexp($value) .'~', $requestUrl)) {
$crawl_flg = false;
}
}
}
return $crawl_flg;
}
*(ワイルドカード)を正規表現で使えるように変換する関数
function asteriskRegexp($str) {
return preg_replace("~(\*)~", ".*?", $str);
}
メイン処理
$robotsTxt
は、前回の記事で取得したrobots.txt
が格納されています。
これを実行することで、クロールが許可されているかチェックできるようになりました。
$requestUrl = 'https://qiita.com/ishi720'; // クロールしたいURLを指定
$myUserAgent = 'myUserAgent'; // ユーザーエージェントを指定
// 1行ごとに配列格納
$lineBreakRobotsArray = lineBreakArray($robotsTxt);
$robotsArray = array();
$userAgentArray = array();
$userAgentNum = 0;
foreach ($lineBreakRobotsArray as $key => $value) {
//コメント行を削除
if (preg_match('/^#/', $value)) {
continue;
}
$item = itemExtraction($value); //itemを抽出
$condition = conditionExtraction($value); //conditionを抽出
if (preg_match('/^user-agent$/', $item)) { //User-agentが含まれている場合
if ($userAgentNum + 1 != $key) {
// 1回目のuserAgentが来た場合
$userAgentArray = array();
}
$userAgentArray[] = $condition;
$userAgentNum = $key;
} elseif (preg_match('/^(disallow|allow|crawl-delay)$/', $item)) {
foreach ($userAgentArray as $userAgent) {
$robotsArray[$userAgent][$item][] = $condition;
}
} elseif (preg_match('/^sitemap$/', $item)) {
$robotsArray[$item][] = $condition;
}
}
$crawl_flg = robotsCheck($requestUrl, $robotsArray, $myUserAgent);
// 結果の出力
if ($crawl_flg) {
print("クロールは拒否されていません");
} else {
print("クロールは拒否されています");
}
終わりに
クロール拒否されていないかチェックする処理を紹介しました。
robots.txt
に準ずることで、お行儀の良いクローラが作成できます。
少しでも参考になれば幸いです。
ここまで読んでいただきありがとうございました。