首页 > 解决方案 > 有没有关于如何使用数据类和scrapy项目的例子?

问题描述

我正在检查 Scrapy 中关于它的文档: https ://docs.scrapy.org/en/latest/topics/items.html#dataclass-objects

from dataclasses import dataclass

@dataclass
class CustomItem:
    one_field: str
    another_field: int

不幸的是,他们没有提供任何关于如何在蜘蛛中使用它的示例。我正在使用这种语法定义我的scrapy项目,我在我的代码中以这种方式调用:

        product = ProductItem(
            publicName=response.xpath(
                '//title/text()').re(r"(.+?)(?=( v?(CC-V)?(\d+\.?){1,3}))")[0],
            description=None,
            productType=self.get_product_type(response),
            salesPage=response.xpath(
                'normalize-space(//div[@class="sales_page"]/center/a/@href)').get(),
            tags=[],
            developer=response.xpath(
                '//div[@class="website"]/a/div/div/div[@class="head"]/text()').get(),
            developerId=response.xpath(
                '//div[@class="fox-sidebar"]/div[4]/div/ul/li/span/a[@rel="tag"]/@href').re(r"\/vendor\/(.*)\/")[0]
        )

我收到此错误: TypeError: 'ProductItem' object is not iterable

PS:我希望收到一个错误,例如,当使用 scrapy 预期整数时将类值定义为字符串。

标签: pythonscrapypython-dataclassesscrapy-item

解决方案


经过反复试验,我在 python 库dataclass-type-validator的帮助下实现了预期的行为:

蜘蛛代码:

        product = ProductItem(
            publicName=response.xpath(
                '//title/text()').re(r"(.+?)(?=( v?(CC-V)?(\d+\.?){1,3}))")[0],
            productType=self.get_product_type(response.xpath(
                '//div[@class="pagination-wrapper"]/ul/li/a/text()').get()),
            salesPage=response.xpath(
                'normalize-space(//div[@class="sales_page"]/center/a/@href)').get(),
            developer=response.xpath(
                '//div[@class="website"]/a/div/div/div[@class="head"]/text()').get(),
            developerId=response.xpath(
                '//div[@class="fox-sidebar"]/div[4]/div/ul/li/span/a[@rel="tag"]/@href').re(r"\/vendor\/(.*)\/")[0],
        )
        yield { "product": product.__dict__ }

将 ProductItem 实例转换为 dict 非常重要,否则您将无法通过适配器在管道中使用此 Item。

items.py 代码:

from typing import List
from dataclasses import dataclass, field
from dataclass_type_validator import dataclass_validate

@dataclass_validate()
@dataclass()
class ProductItem():
    publicName: str
    productType: str
    salesPage: str
    developer: str
    developerId: str
    tags: List[str] = field(default_factory=list)
    description: str = ""

推荐阅读