scrapyで収集したデータをMongodbに格納する

2018年12月11日

下準備

Mongodbをインストールしておこう。Ubuntu16.04ならこんな感じ。

$ sudo apt-get update
$ sudo apt-get install -y mongodb-org

もちろん、インストールしただけだと起動しないので、サービスを開始しておく。

$ sudo service mongod start

dbとcollectionはこの時点で用意しなくても良い。mysqlとは違う。

あと、scrapyのプロジェクトを作っておこう。

$ scrapy startproject honyarara

実装

Mongodbにデータを入れる際にいじるファイルは以下の通り。漏れが無いよう気をつける。

  • items.py
  • pipline.py
  • settings.py
  • XXspider.py

items.pyの設定

いわゆるスキーマを設定する。最低限データを入れる所とデータの収集日時は必要だろう。

class HonyararaItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    update_time = scrapy.Field()

pipline.py

Mongodbとの連携を行う部分。データベース接続の処理等を書く。
まず冒頭でライブラリをインポート。

# pymongoライブラリをインポート
from pymongo import MongoClient

以下、こんな感じ。

class HonyararaPipeline(object):
    def __init__(self, mongo_uri, mongo_db, mongodb_collection):
        # インスタンス生成時に渡された引数で、変数初期化。各変数に代入する値は下のfrom_crawlerメソッドにて。
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db
        self.mongodb_collection = mongodb_collection
        # ユーザー、PW認証を行うときは以下のコメントを外す。
        # self.mongolab_user = mongolab_user
        # self.mongolab_pass = mongolab_pass

    @classmethod
    def from_crawler(cls, crawler):
        # settings.pyで定義した変数にアクセスする
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'), 
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items'),
            mongodb_collection=crawler.settings.get('MONGODB_COLLECTION')
        )

        #userとpassを設定しているならばreturn内にこいつらも含める。外に出してるけど、使うときはreturn cls中に入れる。
            # mongolab_user=crawler.settings.get('MONGOLAB_USER'),
            # mongolab_pass=crawler.settings.get('MONGOLAB_PASS')
    # スパイダー開始時に実行される。データベース接続を行う。
    def open_spider(self, spider): 
        self.client = MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]
        # ユーザー、PW認証を行うときは以下のコメントを外す。
        # self.db.authenticate(self.mongolab_user, self.mongolab_pass)

    def close_spider(self, spider): # スパイダー終了時に実行される。データベース接続を閉じる。
        self.client.close()

    # XXspider.pyでitemが返されたときに実行される。
    def process_item(self, item, spider):
        self.db[self.mongodb_collection].insert_one(dict(item))
        # ちなみに既にデータがあるかどうか確認してあったら更新するってばあいはこんな感じ↓
        # self.db[self.mongodb_collection].update(
        #     {u'title': item['title']},
        #     {"$set": dict(item)},
        #     upsert = True
        # ) 
        return item

settings.pyを書く

settings.pyはあらかじめ色々書かれている。一部コメントアウトして内容を変更するのと、追記する。
まず、この部分がコメントになってるのでコメントアウト。余談ではあるが、コメントアウトと書くときに脳内で「浜田アウト!」と言ってしまう。

ITEM_PIPELINES = {
    'honyarara.pipelines.HonyararaPipeline': 300,
}

pipeline.pyで使うMongodbの設定を追記する。

#mongodb接続設定
MONGO_URI = "mongodb://127.0.0.1:27017"
MONGO_DATABASE = "honyarara"
MONGODB_COLLECTION = "honya"
# ユーザー、PW接続をするときは以下をコメントアウトして設定。
# MONGOLAB_USER = 'honyauser'
# MONGOLAB_PASS = 'honyapw'

XXspider.pyをいじる

spiderフォルダ内にspiderファイルを作って処理を書いていく。 辞書形式でデータを格納して、yield itemってやれば大丈夫。 まず、冒頭でitemをインポートすることを忘れずに。 あと、データの取得日時を入れる場合はdatatimeライブラリもね。

# itemをインポートする
from honyarara.items import HonyararaItem
# datetimeをインポートする
from datetime import datetime

んでdef parse内でitemに色々入れてyieldで返してやるとOK牧場。あえてたまには言いたくなる。

    def parse(self, response):
        # Itemのインスタンス作るす
        item = HonyararaItem()
	for block in response.xpath('//*[@class="marimokkori"]'):
		item['title'] = response.xpath('h1/text').extract
		item['update_time'] = datetime.now()
		yield item