2
2

robots.txtを取得しクロール拒否されていないかチェック②

Posted at

概要

前回は、robots.txtを取得する処理を作成しました。
今回は、robots.txtからクロール拒否されていないかチェックする処理を作成したいと思います。

robots.txtの構成

まずは、サンプルとしてQiitaのrobots.txtを拝借しました。
Qiitaのrobots.txtは以下のような構成になっています。

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のみに伝える内容となります。
以下のように書くと、それぞれのクローラーに対して別の内容を伝えることができます。

robots.txt
User-agent: *
...
...
...

User-agent: GoogleBot
...
...
...

Disallow

クロールを拒否するときに指定します。

Allow

クロールを許可するときに指定します。
デフォルト許可なの基本的にあまり意味はないと思われがちですが、以下のようにDisallowで禁止した一部を許可するときに有効です。

robots.txt
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-agentDisallowといった項目を抽出する関数です。

function itemExtraction($value) {
    $item = preg_replace("/^(.*?):.+/", "$1", $value);// 項目を抽出する
    $item = preg_replace("/^(\s| )/", "", $item); // スペース削除
    $item = mb_strtolower($item); // 小文字にする
    return $item;
}

User-agentDisallowの:(コロン)より右側の情報を抽出する関数です。

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に準ずることで、お行儀の良いクローラが作成できます。
少しでも参考になれば幸いです。

ここまで読んでいただきありがとうございました。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2