2017-12-22 10 views
2

私はscrapyとsqlalchemyを使用しています。私のスパイダーのでは、私はテーブルから選択することだし、とのリクエストを作成する:あなたは、私は、各scrapy要求とSQLAlchemyの行オブジェクトを渡している見ることができるようにScalarでSqlalchemyを使用してテーブル行を更新する

def start_requests(self): 

    db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db" 
    source_table= self.table 

    engine = create_engine(db_path) 
    Base = declarative_base() 
    # metadata = Base.metadata 
    # Look up the existing tables from database 
    Base.metadata.reflect(engine) 

    # Create class that maps via ORM to the database table 
    table = type(source_table, (Base,), {'__tablename__': source_table}) 

    Session = sessionmaker(bind=engine) 
    session = Session() 
    i = 0 

for row in session.query(table).filter(table.url.contains('http')).limit(3): 

    i += 1 
    print(row.url) 
    yield Request(url=row.url, headers= headers, callback=self.get_PDF,meta={'session': session,'row': row, 'cookiejar': i },dont_filter = True) 

。各行オブジェクトには、空白のフィールドが含まれています。空白のフィールドは、スクラップレスポンスから更新します

def get_PDF(self, response): 

    row = response.meta['row'] 

    row.field1 = response.field1 # simplified pseudocode 

ここで、その変更がdbに格納されるように行オブジェクトを更新したいと思います。 セッションオブジェクトを渡していたら、私はsession.commit()を実行できます。 row_objectでこれを行う最善の方法は何ですか?セッションオブジェクトを渡す必要がありますか?

編集:それはあるとして、

def get_PDF(self, response): 

    row = response.meta['row'] 
    session = response.meta['session'] 

    row =process_output(o, row) 
    session.add(row) 
    session.commit() 

答えて

3

は、私はいつもPipelineとなり、データベースと「外部」のストレージを処理するための最良の方法だと思います。私は、セッションオブジェクトを渡すために、私のクモを変更しましたコードの論理を分離する方法です。パイプラインはスパイダーが返すアイテムのみを処理するので、スパイダーコード内のリクエストや何かを心配する必要はありません。

また、Pipelineはクローラに関連付けられたオブジェクトを作成します。このオブジェクトは一度だけインスタンス化されます。これはこのsession状況で非常に役立ちます。

アイテムを異なる方法で処理する必要がある場合は、常に各アイテムに一意の識別子を送信できるため、パイプラインはそれぞれを処理する方法を知っています。

EDIT:

スパイダー:

def start_requests(self): 
    self.session = Session() 

パイプラインクモ内部Sessionオブジェクトを作成し、パイプラインでそれを再利用するための 、あなたはこのような何かを行うことができます

def process_item(self, item, spider): 
    ... 
    spider.session.commit() 

そのspiderは、クローラ全体の「ユニークな」スパイダースインスタンスなので、その属性を使用できます。

+0

セッションオブジェクトをスパイダー内に作成することができます(たとえば 'start_requests'など)。これをパイプラインで使用することもできます。 – eLRuLL

+0

@ user61629私の更新された回答を確認してください – eLRuLL

+0

上記の私の編集をご覧ください。これはうまくいきますが、私はセッションオブジェクトの複数のコピーを作成することに懸念があるので、私はパイプラインの使用についてあなたのポイントを見ています。この場合、私は2段階のプロセスを持っています。私の最初のスパイダーは情報の90%をいくつかの空白のフィールドで項目を埋めるようにします。次に、2番目のスパイダーを使用して、最後の2つのフィールドを埋めるために、より集中的な操作を行います。私は最初のスパイダーのためにItemsとパイプラインを使用しますが、パイプラインを2回目に送信する行をアイテムに変換するのではなく、sqlalchemyを直接使用するコードが少なくて済むように思えました。 – user61629

関連する問題