LoginSignup
6
7

More than 3 years have passed since last update.

【2019年5月】Scrapy の自作パイプラインで Firestore に結果を叩き込む

Last updated at Posted at 2019-05-07

Scrapy の結果を Firestore に出力したい。

Scrapy のドキュメントにはオリジナルのパイプラインで MongoDB にデータ投入する、というサンプルが掲載されておりました。

これにインスパイアされて直接、Firestore にデータを投入してみよう、という試みです。

いくつかハマりポイントがあったのでメモしておきます。

対象環境

  • Python: Anaconda + 3.7

Jupyter notebook から動かしてみてます。

準備

1. パッケージのインストール

以下のコマンドで scrapy と google-cloud-apiをインストールします。

jupyter_notebook
!conda install scrapy -y
!pip install google-cloud-firestore

2. サービスアカウントの作成

Google Cloud Platform の管理画面から Cloud Firestore 編集者Firebase 管理者 のロールを持ったサービスアカウントを作成し、json形式で秘密鍵をダウンロードしてください。

ダウンロードしたファイルは "cred/service_account.json" など適当な名前でnotebookから参照できる場所に置いておきます。

サービスアカウントからAPIで firestore を叩く場合、セキュリティルールは無視されます
というか、サービスアカウントのパーミッションが効きます。書き込む場合は Firestore 編集者Firebase 管理者 のロールが必要です。

※ ただし今回使用した Firestore は Firebaseから有効にした Firestoreでした。Firebase 管理者が本当に必要なのかどうか、環境に応じて検証が必要ですね。。。

3. クローラー、Spider の作成

ここでは Scrapy の Spider 実装には触れません。よろしく実装して下さい。
Cloud Firestore も Mongo 同様にドキュメント型のデータベースでありますので scrapy.Item を base とする item なら dict(item) でデータ投入できます。
安心して Spider 作って下さい。

自前パイプラインの実装

scrapy コマンドで generate した場合、プロジェクトの直下に pipelines.py が生成されていると思います。

これを以下のように置き換えます。

pipelines.py
# -*- coding: utf-8 -*-

from google.cloud import firestore

class CloudFireStorePipeline(object):

    def __init__(self, collection_name):
        self.collection_name = collection_name

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            collection_name = crawler.spider.name
        )

    def open_spider(self, spider):
        self.client = firestore.Client.from_service_account_json('./cred/credential.json')
        self.db = self.client.collection(self.collection_name)

    def process_item(self, item, spider):
        self.db.add(dict(item))
        return item

ここではspiderの名前がそのままコレクション名としてデータを保存しています。
コレクション名が決め打ちであればコンストラクタやfrom_crawlerの実装は不要です。

./cred/credential.json の箇所は上記のサービスアカウント作成の際にダウンロードしたjsonファイルの保存場所に差し替えてください。

パイプラインの有効化

settings.pyにて上記のパイプラインを有効にする必要があります。
ただし、settings.pyでコメントアウトされている箇所をコメント外してクラス名を修正するだけでOKです。

settings.py
...
ITEM_PIPELINES = {
    'myProject.pipelines.CloudFireStorePipeline': 300,
}
...

上記の myProject は Scrapy のプロジェクト名に差し替えてください。

実行

以下のコマンドでクローラーを実行します。例によって jupyter notebook から実行です。

jupyter_notebook
!scrapy crawl mySpider

mySpider は実行する Spider の名前です。

参考サイト

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7