毎日学習記録 9/4 Scrapyで使っているSQLAlchemyの実装について
概要
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を取得できると考えている。
とりあえず、いまのまま動作はするので進めてあとで改善したい。