Blow Up by Black Swan

Python-urllib.robotparser による robots.txt の解析

スクレイピングのためのクローリングのとき、そのサイトがクロールしても良いサイトか、クロールする場合にどのような制限が課されているかは一番最初に行うべきことの 1 つです。十分な対策を行った上でクローリングしても逮捕されてしまう事件も過去、ありました。

サイト側がクローリングの際の注意点を明示する方法の 1 つが「robots.txt」ファイルの設置です。たいていはドメイン直下に置かれています。今回は、この robots.txt を解析することができる Python 標準モジュール、 urllib.robotparser の使い方について紹介します。正直使い方については公式ドキュメントだけでも十分理解できるレベルですが、具体的な活用事例や補助資料のような形でこの記事を活用して頂ければと思います。

なお、下記サイトはクローリングの際に気をつけるべき点について網羅的に記載されていますので、気になる方は見て頂ければと思います。

また、この記事ではクローリングを「対象 URL の HTML データを取得すること」という意味で使っており、スクレイピングを「クローリングした HTML から必要なデータを抜き出す」ことを意味する言葉として、区別して使っています。この記事がどなたかの参考になれば幸いです。

1. 前提環境や利用の流れ

1-1. 利用環境

今回の利用環境は以下になります。

  • OS: MAC OSX
  • Python: 3.7.3

1-2.利用の流れ

この urllib.robotparser の利用の流れは以下になります。

  1. RobotFileParser インスタンスの作成
  2. 参照する robots.txt をセット
  3. read メソッドで robots.txt を解析
  4. 対象 URL がクロールできるか確認
  5. クロール間隔の確認

1-3.利用するデータ

今回利用するデータは、クラウドワークスの robots.txt です。2019 年 6 月 27 日時点では「https://crowdworks.jp/robots.txt」に次のような記載があります。

User-agent: *
Disallow: /api/
Disallow: /attachments/
Disallow: /oauth_clients/
Disallow: /admin/
Disallow: /cases/?attachment_id=
Disallow: /senior/jobs/
Disallow: /senior/job_categories/
Disallow: /senior/employees/
Disallow: /articles/2012/
Disallow: /articles/2013/
Disallow: /internal/
Disallow: /press/?p=

User-agent: Baiduspider
Disallow: /

User-agent: baiduspider+
Disallow: /

User-agent: BaiduMobaider
Disallow: /

User-agent: BaiduImagespider
Disallow: /

User-agent: bingbot
Crawl-delay: 10

今回はこの robots.txt を使って urllib.robotparser モジュールを利用してみます。なお、今後この内容が変わることは十分考えられますので、下記のプログラムが正しく動くかは適宜、該当の robots.txt ファイルを確認下さい。

2.プログラム例

ここからプログラムを紹介していきます。

2-1. インスタンスの作成

まずはインスタンスの作成から該当の robots.txt ファイルの解析までです。基本動作のようなものです。

import urllib.robotparser

robots_url = "https://crowdworks.jp/robots.txt"

# 1) RobotFileParserインスタンスの作成
rp = urllib.robotparser.RobotFileParser()
# 2) URLのセット
rp.set_url(robots_url)
# 3)robots.txtの読み込みと解析
rp.read()

これで robots.txt の解析が完了します。

2-2.クローリング可能な URL の確認

次にこの解析データを利用します。解析データは変数rpに格納されています。まずは、対象の URL がクローリングしても良いか確認してみます。ここで利用するのはcan_fetchメソッドで、第 1 引数で user-agent を、第 2 引数でクロールするページの URL を指定します。対象となる URL は「仕事を探す」のトップページを利用していますが、様々なページで実験してみてください。

url = "https://crowdworks.jp/public/jobs?category=jobs&order=score"

# (1-1)robotsから取得できるか確認
print('*: '+str(rp.can_fetch('*', url)))

# (1-2)robotsから取得できるか確認
print('baiduspider: '+ str(rp.can_fetch('baiduspider', url)))

戻り値は以下になります。

*: True
baiduspider: False

実行結果を見ると、対象 URL に対して一般ユーザーはクローリング OK、baiduspider は NG という結果が bool 値で返されています。この結果は robots.txt に沿った結果となっています。

2-3. クロール間隔の確認

最後にクロール間隔についてです。一般的に同一サイトをクローリングする際は 1 秒以上の間隔をあけることが推奨されていますが、サイトによってはそれ以上の間隔を求めている場合があります。ここで利用するのはcrawl_delayメソッドです。引数には user-agent をとります。

# (2-1)クロール間隔の確認
print('*: '+str(rp.crawl_delay('*')))

# (2-2)クロール間隔の確認
print('bingbot: '+str(rp.crawl_delay('bingbot')))

戻り値は以下になります。

*: None
bingbot: 10

こちらも robots.txt 通りの結果が返ってきています。

3. まとめ

このように urllib.robotparser を実際のプログラムに組み込んで活用することで、Scrapy などのフレームワークに頼らず、ルールを守ったクローリングを行うことが可能となります。ビッグデータの活用やデータサイエンティストの人材不足と育成が叫ばれる中で、インターネットの中から膨大なデータを取得するクローリング、スクレイピング技術は注目を集めています。反面、冒頭で紹介したような逮捕事案や各種法律への抵触など、様々なリスクが存在し、大手サイトでは様々な対策を施していることが多々あります。リスクが顕現化し、賠償責任や刑事罰のような損失を追わないようにするためには「ルールを守る」ことが第一ですので、そのためにもここで紹介した urllib.robotparser モジュールなどはかなり有用なツールだと思いますので、どんどん利用して頂ければと思います。多くの方の参考になれば幸いです。読んで頂き、ありがとうございました。