Scrapy の結果を Firestore に出力したい。
Scrapy のドキュメントにはオリジナルのパイプラインで MongoDB にデータ投入する、というサンプルが掲載されておりました。
これにインスパイアされて直接、Firestore にデータを投入してみよう、という試みです。
いくつかハマりポイントがあったのでメモしておきます。
対象環境
- Python: Anaconda + 3.7
Jupyter notebook から動かしてみてます。
準備
1. パッケージのインストール
以下のコマンドで scrapy と google-cloud-apiをインストールします。
!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 が生成されていると思います。
これを以下のように置き換えます。
# -*- 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です。
...
ITEM_PIPELINES = {
'myProject.pipelines.CloudFireStorePipeline': 300,
}
...
上記の myProject
は Scrapy のプロジェクト名に差し替えてください。
実行
以下のコマンドでクローラーを実行します。例によって jupyter notebook から実行です。
!scrapy crawl mySpider
mySpider
は実行する Spider の名前です。