scrapy - 在scrapy中嵌套项目数据的正确方法

标签 scrapy

嵌套 Item 数据的正确方法是什么?

例如,我想要一个产品的输出:

{
'price': price,
'title': title,
'meta': {
    'url': url,
    'added_on': added_on
}

我有scrapy.Item:
class ProductItem(scrapy.Item):
    url = scrapy.Field(output_processor=TakeFirst())
    price = scrapy.Field(output_processor=TakeFirst())
    title = scrapy.Field(output_processor=TakeFirst())
    url = scrapy.Field(output_processor=TakeFirst())
    added_on = scrapy.Field(output_processor=TakeFirst())

现在,我这样做的方法只是根据新项目模板重新格式化管道中的整个项目:
class FormatedItem(scrapy.Item):
    title = scrapy.Field()
    price = scrapy.Field()
    meta = scrapy.Field()

并在管道中:
def process_item(self, item, spider):
    formated_item = FormatedItem()
    formated_item['title'] = item['title']
    formated_item['price'] = item['price']
    formated_item['meta'] = {
        'url': item['url'],
        'added_on': item['added_on']
    }
    return formated_item

这是解决这个问题的正确方法还是有更直接的方法来解决这个问题而不破坏框架的哲学?

最佳答案

更新 来自评论:看起来像 nested loaders是更新的方法。另一个评论表明这种方法会在序列化过程中导致错误。

解决这个问题的最好方法是创建一个 main和一个 meta项目类/加载器。

from scrapy.item import Item, Field
from scrapy.contrib.loader import ItemLoader
from scrapy.contrib.loader.processor import TakeFirst


class MetaItem(Item):
    url = Field()
    added_on = Field()


class MainItem(Item):
    price = Field()
    title = Field()
    meta = Field(serializer=MetaItem)


class MainItemLoader(ItemLoader):
    default_item_class = MainItem
    default_output_processor = TakeFirst()


class MetaItemLoader(ItemLoader):
    default_item_class = MetaItem
    default_output_processor = TakeFirst()

示例用法:
from scrapy.spider import Spider
from qwerty.items import  MainItemLoader, MetaItemLoader
from scrapy.selector import Selector


class DmozSpider(Spider):
    name = "dmoz"
    allowed_domains = ["example.com"]
    start_urls = ["http://example.com"]

    def parse(self, response):
        mainloader = MainItemLoader(selector=Selector(response))
        mainloader.add_value('title', 'test')
        mainloader.add_value('price', 'price')
        mainloader.add_value('meta', self.get_meta(response))
        return mainloader.load_item()

    def get_meta(self, response):
        metaloader = MetaItemLoader(selector=Selector(response))
        metaloader.add_value('url', response.url)
        metaloader.add_value('added_on', 'now')
        return metaloader.load_item()

之后,您可以通过创建更多“子项目”来轻松扩展您的项目。

关于scrapy - 在scrapy中嵌套项目数据的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25095233/

相关文章:

python - Scrapy - 发送具有多个选项的表单数据

python - Scrapy 爬取 0 页(0 页/分钟)

Python + Scrapy + JSON + XPath : How to scrape JSON data with Scrapy

python - Scrapy 和代理

python - Webrawling in Python with Scrapy - 如何强制页面显示面包屑菜单?

python - 使用 scrapy css 选择器定位 id

python - 从脚本运行的 Scrapy 不起作用

python - 每个进程运行多个蜘蛛 - 不保存输出数据

python - 按计划进行 Scrapy

Scrapy Torproject