はじめに
スクレイピングを始めるにあたって、一番に気を付けるべきことは法律やルール(明示的なモノや暗黙的なモノも含む)を遵守することである。スクレイピングは、非常に便利であるがゆえにこのようなルールは割と蔑ろにされがち(特に初心者)であると思う。
今回はスクレイピングのルールに関しての記事ではないので、それらについては下記の記事を参考にされたい。
参考記事
robots.txtについて
ルールについては触れないとは言うものの、記事の題材でもあるrobots.txt
については簡単に触れておく。
robots.txt
とは、スクレイピングを行うプログラムに対しての指示が書いてある文書である。robots.txt
は慣習的にはURLの直下に置かれるが、これは別に義務ではないので、そもそも配置されていないケースもある。例えば、Qiitaであればこちらに配置されている。
User-agent: *
Disallow: /*/edit$
Disallow: /api/*
Allow: /api/*/docs$
上記のQiitaのrobots.txt
を参考にして軽く解説をするが、User-Agent
というのは対象となるクローラーの種類を表す。*
は全員に対する指示である。次にAllow / Disallow
は、指定されたパスへのクロールの許可もしくは禁止を表す。上の例であれば、https://qiita.com/api/*
はクロール禁止だが、https://qiita.com/api/*/docs$
は許可されていることがわかる。また、サイトによってはCrawl-delay
が設定されていることもあるが、設定されていない場合でも暗黙の了解として、次のリクエストまで1秒間空けることが望ましい。
もっと詳細にrobots.txt
についての仕様を知りたい方は、こちらを参照されるといい。
プログラム作成
Step 1. robots.txtの読み取り
pythonの標準ライブラリのurllib
には、robots.txt
を読み取るためのurllib.robotparser
が提供されている。今回はこれを利用して、プログラムを作成する。
urllib.robotparser
については、こちらを参照。
import urllib.robotparser
# robots.txtの読み取り
robots_txt_url = 'https://qiita.com/robots.txt'
rp = urllib.robotparser.RobotFileParser()
rp.set_url(robots_txt_url)
rp.read()
# robots.txtの情報から調査したいURL、User-Agentでクロール可能かを調べる
user_agent = '*'
url = 'https://qiita.com/api/*'
result = rp.can_fetch(user_agent, url)
print(result)
False
上記のプログラムでは、まずRobotFileParser
オブジェクトを作り、set_url
関数でrobots.txt
のURLを指定、それを元にread
で読み取りを行う。次に、調査したいUser-Agent、URLをcan_fetch
関数に与えることでアクセスが許可されているかどうかが真偽値で取得できる。上記のプログラムでは、先程確認した通りhttps://qiita.com/api/*
へのクロールは許可されていないので、Falseが出力されている。
Step 2. 正規表現を用いたrobots.txtのリンクの取得
プログラムの根幹となる部分は、ほとんどStep1で終了しているが、これではライブラリの機能を利用しただけで、プログラムとして有用なものではない。そこで正規表現を用いて、robots.txt
のリンクを自動生成したいと思う。とは言っても、あまりイメージが湧かないと思うので、具体的な例を用いて説明する。
例えば、クロールが許可されているか調べたいURLがhttps://qiita.com/api/*
であるとすると、このURLを元にhttps://qiita.com/robots.txt
というリンクを生成するという事である。これは先程も述べた通りrobots.txt
は慣習的にサイトの直下に配置されているので、https://qiita.com/api/*
からhttps://qiita.com
の部分を抽出できれば、そこに/robots.txt
の文字を足すだけでリンクを作成することができる。
pythonの正規表現reについては、こちらを参照されるといい。
import re
# 正規表現によりサイトのURLを取得
def get_root_url(url):
pattern = r'(?P<root>https?://.*?)\/.*'
result = re.match(pattern, url)
if result is not None:
return result.group('root')
# サイトのURLからrobots.txtのURLを生成
def get_robots_txt_path(root_url):
return root_url + '/robots.txt'
url = 'https://qiita.com/api/*'
root_url = get_root_url(url)
robots_txt_url = get_robots_txt_path(root_url)
print(f'ROOT URL -> {root_url}')
print(f'ROBOTS.TXT URL -> {robots_txt_url}')
ROOT URL -> https://qiita.com
ROBOTS.TXT URL -> https://qiita.com/robots.txt
Step 3. 機能を追加してまとめる
Step1, Step2を元にurllib.robotparser
の機能を用いて、Crawl-Delayを取得するなどの機能を追加し、関数などをクラス化してまとめる。ここにコードを置いてもいいのだが、微妙に長いためGitHubに置いておく。60行程度なので、内容を確認したい方はどうぞ。
※GitHubのコードでimportされているcoloramaというライブラリは、ターミナルで文字を着色するために使っているものなので、特に機能に重要なものではない。