Scrapy:使用itemloader i.c.w. a Postgres Pipeline的最佳方法是什么?



我试图使用itemLoader给Scrapy中的空项目一个默认值,就像这样在items.py:

prod_specs = Field(
    default=[],
    input_processor=MapCompose(unicode_to_str, strip_tabs_new_lines),
)

所以如果没有设置prod_specs,它应该给它一个空对象。但这行不通。如果我尝试用item['prod_specs'].

将字段存储到数据库中

我收到一个错误告诉我键不存在:

exceptions.KeyError: 'prod_specs' 

如果没有设置,其他字段也一样。我认为我使用item['prod_specs']而不是itemLoader,如items.py,正在导致错误。但我不确定。

你们怎么看?你有解决办法吗?

edit:官方文档似乎过时了,Field默认值不再工作(参见https://github.com/scrapy/scrapy/issues/560)。因此,另一种选择是使用管道为项分配默认值:

def parse_item(self, item, spider):
    if "prod_specs" not in item: item['prod_specs'] = []
    return item

或在psycopg2期间插入:

def parse_item(self, item, spider):
    cur.execute("insert into mytable(prod_specs) values(%s)",
                item.get('prod_specs',[]))
    return

你正在尝试使用ItemLoader作为Item。下面是如何设置你的项目和itemloader。

items.py

from scrapy.item import Field, Item
from scrapy.contrib.loader.processor import MapCompose
class Product(Item):
    prod_specs = Field(
        default=[],
        input_processor=MapCompose(unicode_to_str, strip_tabs_new_lines)
    )
蜘蛛/myspider.py

from scrapy.contrib.loader import ItemLoader
from myproject.items import Product
def parse(self, response):
    l = MyLoader(item=Product(), response=response)
    l.add_xpath('prod_specs', '//div[@class="prod_specs"]')
    return l.load_item()

如果你打算使用很多不同的项,你应该子类化ItemLoader并定义默认的处理器。

这足以回答你的问题了吗?您提到您想要编写一个Postgres管道。我发现最简单的方法是使用SQLAlchemy,通过这种方式,您可以使用单个管道向任意数量的数据库写入任意数量的对象。

最新更新