Python製のクローラーフレームワークであるScrapyを使うと、簡単にクローラーを作成することができます。
実際のクローラーの開発・運用ではクローラーを定期的に動かす必要が多いです。
Scrapy単体は定期実行の機能を提供していないため、何かしらの外部の仕組みを活用して定期実行をする必要が出てきます。
例えば、Scrapyの開発元であるScrapingHub社が提供しているPaaSであるScrapy Cloudを使うと定期実行を行うことができます。
このクラウドはScrapyに特化したものであり、ヘッドレスブラウザやIPアドレス偽装などの便利機能とのインテグレーションも容易です。
しかし、この記事ではaws Lambda(以下Lambda)の上でScrapyを動作させてみます。
Lambdaで動かすことで、他のawsサービスとのインテグレーションがやりやすくなります。
PythonコードからScrapyを呼ぶ方法
通常はScrapyを呼び出すために、shellから scrapy run <spiderの名前>
実行します。
しかし、LambdaのエントリーポイントはPython関数であるため、何らかの方法でPythonからScrapyを呼び出す必要があります。
標準ライブラリのsubprocessを使いshellを呼びだすこともできますが、ここではより直接的な方法でScrapyを呼び出してみます。
以下の公式ドキュメントを参考にして、PythonからScrapyを呼び出します。
import os
import csv
from multiprocessing import Process, Queue
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from .spiders.hoge import HogeSpider
def crawl(file_name):
# settings.pyに書いていた設定をここに書く
settings = get_project_settings()
settings.set('FEEDS', { file_name: {"format": "csv"}})
process = CrawlerProcess(settings)
process.crawl(HogeSpider)
process.start()
# csvをslackに通知したり、S3に保存したりする
def run():
file_name = '/tmp/hoge.csv'
process = Process(target=do_crawl, args=(file_name,))
process.start()
process.join()
if __name__ == '__main__':
run()
crawl関数がScrapyを呼び出す処理の本体です。
ただPythonから呼び出すだけならばこれで十分ですが、LambdaがPythonプロセスを再利用した場合はこのままだとエラーになります。
これはScrapyが内部的に使っている非同期処理ライブラリのtwistによるものです。
そのため、run関数内部でプロセスを生成しそれを使い捨てることで、毎実行ごとに独立したプロセス空間でScrapyを動作させています。
Lambdaから呼び出す
ここまで出来ればあとは簡単です。
Lambdaから呼び出されるハンドラーを作成します。
from crawl import run
def start(event, context):
run()
response = {
"statusCode": 200,
"body": "Success"
}
return response
デプロイ
最後に、この設定をLambdaにデプロイします。
デプロイにはServerless Frameworkを利用します。
以下のYAMLファイルを用意し、 serverless deply
コマンドを実行すれば定期的にLambdaの上でScrapyが動きます。
service: hoge-crawler
provider:
name: aws
runtime: python3.8
region: ap-northeast-1
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true
functions:
start:
handler: handler.start
timeout: 600 # 10 min
events:
- schedule: cron(0 15 * * ? *) # every day at 00:00 JST
注意点
awsの利用規約
awsのAcceptable Use Policyには以下のように書かれています。
Monitoring or Crawling. Monitoring or crawling of a System that impairs or disrupts the System being monitored or crawled.
そのため、クローリング対象のシステムを妨害するレベルでの大量アクセスをした場合はawsのアカウントが停止される恐れがあります。
Lambda上でクローラーを運用する時は特に適切なダウンロード間隔が設定されているかどうかをしっかりと確認しましょう。
Lambdaの実行時間制限
Lambda関数の実行時間には最大15分の制限があるため、この方法は大規模なサイトをクローリングするのには向いていません。
その場合はEC2にScrapyをインストールしてcronで定期実行したり、ECS Scheduled Taskの機能で定期実行をしたりを考える必要があります。