【问题标题】:How to get the spider name in Scrapy pipeline outside of the process_item function?如何在 process_item 函数之外获取 Scrapy 管道中的蜘蛛名称?
【发布时间】:2018-08-22 23:19:36
【问题描述】:

我编写了一些从不同来源提取相似数据的蜘蛛。我还编写了一个管道,允许将这些数据放入数据库中。我希望能够为多个蜘蛛使用相同的代码输出到不同的表,从蜘蛛名称动态命名。

这里是pipeline.py 代码:

class DbPipeline(object):
def __init__(self):
    """
    Initialises database connection and sessionmaker.
    Creates table if it doesn't exist.
    """
    engine = db_connect()
    create_output_table(engine)
    self.Session = sessionmaker(bind=engine)


def process_item(self, item, spider):

    """
    Saves scraped products in database
    """

    exists = self.check_item_exists(item)

    if not exists:
        session = self.Session()
        product = Products(**item)
        try:
            session.add(product)
            session.commit()
        except:
            session.rollback()
            raise
        finally:
            session.close()


    return item

def check_item_exists(self,item):

    session = self.Session()
    product = Products(**item)

    result = session.query(Products).filter(Products.title == item['title']).first()

    return result is not None

这里是model.py 文件:

    DeclarativeBase = declarative_base()

def create_output_table(engine):
    DeclarativeBase.metadata.create_all(engine)

def db_connect():
    """
    Connects to database from settings defined in settings.py 
    Returns an sqlalchemy engine instance
    """

    return create_engine(URL(**settings.DATABASE))

class Products(DeclarativeBase):
    """Sqlalchemy table model"""
    __tablename__ = "name"

    id = Column(Integer, primary_key=True)
    title = Column('title', String(200))
    price = Column('price', String(10), nullable=True)
    url = Column('url', String(200), nullable=True)

我想要做的是让__tablename__ 变量与蜘蛛名称相同,我可以在process_item 函数中轻松做到这一点,因为它传递了一个spider 对象并且可以使用@ 987654330@ 并将其分配给类变量,但是该函数将在创建/定义表后运行。如何在pipelines.py 文件中的process_item 函数之外获取蜘蛛名称?

编辑:我已经尝试了How to access scrapy settings from item Pipeline 中列出的解决方案,但是访问“设置”并不能访问分配给当前正在运行的蜘蛛的属性。我需要根据运行管道的蜘蛛动态获取蜘蛛的名称。谢谢

【问题讨论】:

  • @gangabass 嘿,我已经更新了我的问题,为什么它不是重复的
  • 您想在您的check_item_exists 中获取当前蜘蛛名称吗?
  • 如果我可以在该文件中的任何位置获取该名称,那将是一些东西,但我需要它真正在产品类中。我目前正在尝试如何使用您链接的帖子中的 from_crawler() 方法,但我不完全确定它会有所帮助。我知道 crawler.spider.name 可能有效,但不确定这是否只会返回 DefaultSpider 名称而不是当前正在运行的名称。

标签: python-3.x sqlalchemy scrapy


【解决方案1】:

在您的create_output_table 中获取当前蜘蛛名称非常容易:

class DbPipeline(object):


    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.spider.name)

    def __init__(self, spider_name):
        """
        Initializes database connection and sessionmaker.
        Creates deals table.
        """
        engine = db_connect()
        create_output_table(engine, spider_name)
        ......

和(在models.py):

def create_output_table(engine, spider_name):
    # now you have your spider_name
    DeclarativeBase.metadata.create_all(engine)

这里的问题是 Scrapy 处理你的models.py 文件你的pipelines.py 之前。所以你需要找到一种方法来生成你的 SQLAlchemy 模型。您可以使用此线程作为起点:Dynamically setting __tablename__ for sharding in SQLAlchemy?

【讨论】:

  • 这很完美,我已经完成了一半。非常感谢你。
猜你喜欢
  • 2012-02-16
  • 2015-11-07
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多