毎日学習記録 9/4 Scrapyで使っているSQLAlchemyの実装について

Share on:

概要

Scrapyで使っているSQLAlchemyの実装について

内容

現在、Scrapyを使用しニュースさいとをスクレイピングしデータを取得をしているのですが、 せっかくなので、itemから登録る箇所でいままでくわず嫌いをしていたSQLAlchemyを使ってみることにしました。

ディレクトリ構成

|-- scraper
      |-- items
            |-- news.py
          
      |-- models
            |-- concerns
                  |-- 共通処理
                        |-- base.py
                        |-- article.py
      |-- spiders

※本来必要な__init___.pyは省略していますので注意してください。

基本的には、

base.py: 共通の基底オブジェクトやそれに関わるもの全般

article.py: baseクラスから作られるモデルクラス (基本的にマイグレーションは別で持つので、今回は既存テーブルを利用する)

baes.yp


from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base


engine = create_engine('mysql://xxxxx')

Base = declarative_base(bind=engine)

Base.metadata.reflect(bind=engine)
session = scoped_session(
    sessionmaker(
        autocommit=False,
        autoflush=True,
        bind=engine
    )
)

Base.query = session.query_property()

article.py

普段、Railsも使用していることもありsaveメソッドで登録と更新を適切に行いたいために、モデルにsaveメソッドを作成し、その中ですでに存在していれば更新、なければ登録といったような処理をしている。 また、__tabelnaem__の箇所は既存のテーブルに対して実行するため設定している。

from . import base

class Article(base.Base):
    __tablename__ = "articles"
    __table_args__ = {
        'schema': 'news_db',
        "autoload": True,
        'extend_existing': True
    }

    def __init__(self, params):
        self.session = base.session()

        self.id      = params["id"]
        self.title   = params["title"]

    def save(self, items):
        query = self.session.query(Article).filter(Article.code == items["id"])

        if query.count():
            # update
            article = query.first()

            for key, value in items.items():
                if key in article.__dict__:
                    if article.__dict__[key] != items[key]:
                        setattr(article, key, value)
   

        else:
            self.session.add(self)

        self.session.commit()
        return items

課題

関数の定義

def save(self, items):
    xxx

これは、最初の初期化で必要なパラメーターを入れているので、selfからitemを取得できると考えている。

とりあえず、いまのまま動作はするので進めてあとで改善したい。