Webスクレイピング Advent Calendar 2017 21日目の記事です。

趣味でクローリング・スクレイピングをするときがあります。その作業が長時間に及ぶときは、サーバーでバッチを動かして、クローリング・スクレイピングをやっています。この記事ではそのときに行った工夫について話したいと思います。あまり深く考えてないで雑にやっているので、改善点等があればコメントをお願いします。

想定するクローリング・スクレイピングのシーン

  1. 商品一覧ページをスクレイピング
  2. 各商品の詳細ページをスクレイピング
  3. 別の商品一覧ページに移動し、最初に戻る

これを商品一覧ページ全部をたどるまで続けます。

さらに、商品一覧ページのURLは、https://hogehoge/list/page/12 のようにURL中にページ番号があるものを想定します。つまり、上記手順3では、ページ番号を1つ増やして、別の商品一覧ページにアクセスすることになります。

バッチ運用で行った工夫

バッチでクローリング・スクレイピングを運用する上で大切なのは、何らかの理由により途中で処理がこけてバッチが止まっても、すぐにバッチを再開できるようにして、処理を継続的に行えるようにすることです。

とりあえず処理を継続的に行えるようにする

途中で処理がこけてバッチが止まってもすぐにバッチを再開できるようにするため、cronで1分毎にバッチを起動するようにします1。しかし、これだけではバッチがどんどん起動、多重起動して大変なことになってしまいます。これを防ぐため、ロックファイル/ロックディレクトリを利用します。つまり、

  • バッチ起動時に所定の位置にファイル/ディレクトリにあるかどうかを確認する
    • すでにある場合はバッチを終了する
    • ない場合はその位置にファイル/ディレクトリを作る
  • バッチの処理が終わったら作ったファイル/ディレクトリを削除する

という手順でバッチの多重起動を防ぎます。

どのページまでクローリングしたのかをメモする

商品一覧ページの何ページまで辿ったのかをファイルに記録します。バッチを再開するときには、ファイルを読み取って、続きからクローリングできるようにします。

バッチが途中でこけたときは通知する

予期せぬ例外が起きる等してバッチがこけたときは通知するようにします。バッチがこけ続けたときに適切に対処するためですね。私は通知先としてSlackをよく使います。

リダイレクト対策

ページ数が十分に大きくなって存在しないページにアクセスするときを考えます。ステータス404が返ってくれば、これを補足してクローリングを終わらせることができます。しかし、中には1ページ目にリダイレクトするWebサイトがあり、これに遭遇にしてしまうと、永遠にクローリングが終わらないのでリダイレクトを補足できるようにします。

例えば、Pythonでrequestsライブラリを使う場合は、

import requests

# urlはリクエストURL
res = requests.get(url)
if url != res.url:
  # リダイレクトされたときの処理

という風に、ResponseオブジェクトのurlがリクエストURLと異なるかどうかでリダイレクトを判定できます。

最後に

最初の方でも言った通り雑にやっていることなので、改善点等があればコメントをお願いします。


  1. もちろんバッチ内では、時間間隔をある程度空けてページアクセスを行っています。 

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.