3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Organization

Scrapyのスケジューラscrapy-doを使ってみた

Scrapyを時刻起動させられるデーモン、scrapy-doを試してみたので、記録しておきます。
ネット上に情報が少ないこともあり、少しでも貢献できれば幸いです。

環境情報

Python 3.7.7
Scrapy 2.1.0
scrapy-do 0.4.0

macOS Catalina 10.15.4

scrapy-doについて

scrapy-doはLukasz Janyst氏が開発するScrapyの実行用デーモンです。
Scrapyのジョブを管理するコマンドライン、REST API、WebGUIが備わっています。
(公式ドキュメントはこちら)

Scrapyの実行デーモンとしては、scrapydが有名ですが、scrapy-doはscrapydにインスパイアされて開発したとのことです。

どちらも常駐プロセスとしてScrapyを実行しますが、scrapy-doは起動タイミングや実行間隔を持つ点がscrapydと大きく異なります。

scrapydでスケジュール管理をする時はcronやその他スケジューラを併用することになりますが、scrapy-doはジョブの登録時に「毎日t時に起動」のような指定が可能です。

早速使ってみる

前提事項

Scrapyチュートリアルquotes_spiderの一部を題材にします。

インストール

pipでscrapy-doをインストールします。


pip install scrapy-do

起動

任意のディレクトリで起動します。

scrapy-do -n scrapy-do

起動したディレクトリに projectsというディレクトリが作成されます。
実行ログやスケジュール情報が置かれる場所です。

projects
├── spider-data
├── schedule.db
├── metadata.pkl
└── log-dir

実行環境設定

ジョブ実行の並列数やプロジェクトの保存先など、設定全般は設定ファイルで指定します。
詳細は公式ドキュメントServer Configurationを参照。

scrapy-do scrapy-do --config /path/to/config/file.conf

プロジェクトのpush(コマンド)

Scrapyプロジェクトをpushします。
ここでいうプロジェクトとは、scrapy startproject tutorialtutorialを意味しています。

pushの方法はcliとRESTの2通り。

まずはcliでpushしてみます。
デフォルトでカレントディレクトリのプロジェクトをpushしますが、--project-pathでpush対象のパスを指定することも可能です。

push対象のディレクトリに入る
cd tutorial
pushする
scrapy-do-cl push-project
+------------+
| tutorial   |
|------------|
| quotes     |
+------------+

pushすると、プロジェクト内にあるスパイダーを見つけて表示してくれます。

さきほどのprojectsディレクトリを見てみると、pushされたtutorialプロジェクトが追加されているのがわかります。

projects
├── [  64]  log-dir
├── [ 140]  metadata.pkl
├── [ 20K]  schedule.db
├── [  64]  spider-data
└── [9.1K]  tutorial.zip

なお、scrapy-doではスパイダーを更新した時はプロジェクトの再pushが必要です。
再pushと初回pushで実行方法に違いはありません。

プロジェクトのpush(REST)

一応RESTでpushする場合も試してみます。

RESTでpushするときは、push対象のプロジェクトをzip圧縮してパラメータで指定します。


zip -r tutorial_archive.zip tutorial/

curl -s http://localhost:7654/push-project.json \
     -F archive=@tutorial_archive.zip | jq -r
{
  "status": "ok",
  "name": "tutorial",
  "spiders": [
    "quotes"
  ]
}

サーバ側のコンソールにはプロジェクトの受付ログが出力されています。

2020-05-24T10:12:14+0900 [scrapy_do.controller.Controller#info] Pushing new project
2020-05-24T10:12:15+0900 [scrapy_do.controller.Controller#info] Added project "tutorial" with spiders ['quotes']
2020-05-24T10:12:15+0900 [twisted.python.log#info] "127.0.0.1" - - [24/May/2020:01:12:14 +0000] "POST /push-project.json HTTP/1.1" 200 60 "-" "python-requests/2.23.0"

ジョブのスケジューリング

ジョブの実行をスケジューリングしてみます。

特徴的なのが--whenで指定する起動タイミング。
結構オシャレな指定方法になってます。

詳しくは公式ドキュメントのScheduling Specsを参照

  • 'every monday at 12:30'
  • 'every 2 to 3 hours'
  • 'every 6 minutes'
  • 'every hour at 00:15'
3分間隔の指定

scrapy-do-cl schedule-job --project tutorial \
    --spider quotes --when 'every 3 minutes'
+--------------------------------------+
| identifier                           |
|--------------------------------------|
| 3280bfb3-01df-49a5-aa53-805a5723df93 |
+--------------------------------------+

即時実行させたい時は --when 'now'と指定します。

ジョブのキャンセル

登録したジョブをキャンセルしたい時は、cancel-jobコマンド or APIでジョブIDを指定します。

scrapy-do-cl cancel-job --job-id 3280bfb3-01df-49a5-aa53-805a5723df93
Canceled.

ジョブの結果確認

ジョブの実行状況は、確認コマンド or APIで確認できます。

ステータスACTIVEで実行中ジョブ、COMPLETEDで終了したジョブを確認できます。

curl -s "http://localhost:7654/list-jobs.json?status=ACTIVE" | jq -r
{
  "status": "ok",
  "jobs": [
    {
      "identifier": "ddd118dd-15f0-4448-8408-967fc806a859",
      "status": "SUCCESSFUL",
      "actor": "USER",
      "schedule": "now",
      "project": "tutorial",
      "spider": "quotes",
      "description": "",
      "timestamp": "2020-05-24 14:14:34.990209",
      "duration": 3,
      "payload": "{\"testkey\": \"hogehoge\"}"
    },
...

若干(というか結構)気になったのが、--when 'every 3 minutes'で指定したジョブは、実際に実行される時に別ジョブIDが発行されて、結果を見ると"schedule": "now"で実行されたことになっている点。

時刻が来ると--when 'now'で即時ジョブを登録するようになっているみたいです。

Spiderに引数を渡す

スケジューリングの際にpayloadオプションを指定すると、Spiderに引数を渡せます。

指定できるのはvalidなJSON形式に限られており、Spider側からはpayloadという引数名で受け取ることができます。

curl -s http://localhost:7654/schedule-job.json \
       -F project=tutorial \
       -F spider=quotes \
       -F "when=now" \
       -F payload='{"hoge": "foobar"}' | jq -r

引数はJSON形式のstringで渡ってくるので、astなどで辞書型に変換して使います。

Web GUI

ここまで書いてきませんでしたが、localhost:7654でアクセスできる管理画面も提供されています。

scrapy-do1.jpg

ただ私の環境が悪いのか、ジョブを登録した後に画面を開くと、JavaScriptのシンタックスエラーが発生して見えなくなってしまいました。

さいごに

scrapy-doを軽く動かしてみました。
まだバージョンは0.4.0ですが、scrapydで悩ましかった時刻起動がカバーされているのは非常にありがたく、今後に期待したいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
3
Help us understand the problem. What are the problem?