1

こんにちは、Python のスクレイプ ライブラリを使用してスパイダーを作成し、Web サイトからデータを抽出しています。私のパイプラインでは、Flask-SQLAlchemy を使用してスパイダーを構成し、スクレイピングしたデータを SQLite テーブルに追加します。スパイダーがテーブルに重複データを追加するのを防ぐ方法を見つけようとしているので、データベースにクエリを実行して、スパイダーがテーブルに追加しようとしている要素と同じ要素がテーブルに既に含まれているかどうかを確認します。もしそうなら、私はスパイダーにデータを追加させたくないのですが、単純に次の要素に移動します。これが私がこれまでに持っているコードです:

from flask import Flask, render_template, redirect, request, url_for
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import sessionmaker

import os
import sys

from sqlalchemy import Column, ForeignKey, Integer, String, DateTime, union
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL

app = Flask(__name__)

# Flask-SQLAlchemy
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://draft.db"
app.config["SQLALCHEMY_ECHO"] = True
db = SQLAlchemy(app)

def db_connect():
    return create_engine('sqlite:///draft.db')

Base = declarative_base()

class Events(Base):
    __tablename__ = 'events'
    id = Column(Integer, primary_key=True)
    title = Column(String(250), nullable=False)
    location = Column(String(250), nullable=False)
    date = Column(String(250), nullable=False)
    url = Column(String(250), nullable=False)

engine = create_engine('sqlite:///draft.db')

def create_events_table(engine): 
    Base.metadata.create_all(engine)

class GeneralPipeline(object):
    def __init__(self):
        engine = db_connect()
        self.Session = sessionmaker(bind=engine)    

    def process_item(self, item, spider):
        session = self.Session()
        event = Events(**item)

        duplicates = union(session.query(Events).filter_by(title=item["title"]), session.query(Events).filter_by(date=item["date"]))

        if duplicates:
            session.close()

        else:
            try:
                session.add(event)
                session.commit()
            except:
                session.rollback()
                raise
            finally:
                session.close()

        return item

これはエラー raise TypeError("Boolean value of this clause is not defined") を返しますが、これは if duplicates: ステートメントを参照していると思いますが、なぜこれが機能しないのかわかりません。重複が存在するかどうかを確認したいだけで、存在する場合、スパイダーはそのデータ要素をテーブルに追加しないでください。このシステムを機能させる方法についての指針はありますか?

要求されたスタック トレースの詳細は次のとおりです。

TypeError: Boolean value of this clause is not defined
2016-12-06 21:02:34 [scrapy] ERROR: Error processing {'location': None, 'date': datetime.datetime(2017, 1, 21, 21, 0), 'url': 'http://www.trumba.com/events-calendar/ma/boston/harvard-events/harvard-event-calendar/harvard-activities/gazette', 'title': 'Varsity Show'}
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/twisted/internet/defer.py", line 649, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "/home/ubuntu/workspace/project/draft/draft/draft/pipelines.py", line 58, in process_item
    if duplicates:
  File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/elements.py", line 481, in __bool__
    raise TypeError("Boolean value of this clause is not defined")
TypeError: Boolean value of this clause is not defined
2016-12-06 21:02:34 [scrapy] INFO: Closing spider (finished)
2016-12-06 21:02:34 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 524,
 'downloader/request_count': 2,
 'downloader/request_method_count/GET': 2,
 'downloader/response_bytes': 352524,
 'downloader/response_count': 2,
 'downloader/response_status_count/200': 2,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2016, 12, 7, 2, 2, 34, 379384),
 'log_count/DEBUG': 3,
 'log_count/ERROR': 201,
 'log_count/INFO': 7,
 'response_received_count': 2,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 1,
 'scheduler/enqueued/memory': 1,
 'start_time': datetime.datetime(2016, 12, 7, 2, 2, 32, 3552)}
2016-12-06 21:02:34 [scrapy] INFO: Spider closed (finished)
4

0 に答える 0