使用自定义方法扩展 Scrapy ItemLoader



Scrapy 文档列出了 ItemLoader 实例的所有内置方法,并解释了如何声明自己的 Item Loader。但是,您声明的任何条目加载器都将应用于所有已处理的项目。您可以使用条目加载器上下文稍微修改它们的行为,但这通常不够精细。

假设我有一个 Scrapy 项目,其中蜘蛛和物品都继承了相同的基础蜘蛛和物品加载器,但蜘蛛都包含特定于站点的逻辑和一些通用函数。在 Scrapy 文档中,我没有发现提到将类方法添加到 ItemLoaders

中,以便代替:
import mymodule
class MySpider(BaseSpiderName):
  def parse_item(self, response):
    product = ItemLoader(item=Product(), response=response)
    new_value = mymodule.myfunction(argument, ..., ...)
    product.add_value('my_field', new_value)

你可以这样写:

# (no extra import)
class MySpider(BaseSpiderName):
  def parse_item(self, response):
    product = CustomItemLoader(item=Product(), response=response)
    product.custom_function(argument, ..., ...)

尽管这似乎是扩展 ItemLoaders 的明显方法,就像您为任何其他类所做的那样,但它没有记录在案,而且我在我检查过的任何地方都没有看到如何在 Scrapy 中执行此操作的示例(Google、StackOverflow)。是否可能/支持,您将如何声明它们?

是否可能/支持,您将如何声明它们?

这是可能的。哪种方式取决于您共享的逻辑类型。

你可以以与 Scrapy 无关的方式声明你的方法,即就像你对任何其他 Python 类所做的那样:子类化你的CustomItemLoader类并在该子类中定义方法:

from scrapy.loaders import ItemLoader
class CustomItemLoader(ItemLoader):
    def custom_function(self, *args, **kwargs):
        self.add_value('my_field', mymodule.myfunction(*args, **kwargs))

或者,根据某些蜘蛛共享的函数中的实际逻辑,传递给add_*方法的简单处理器可能是要走的路。

您可以在定义

Productitems.py文件中定义CustomItemLoader类,如下所示:

from scrapy import Item, Field
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose, TakeFirst
class CustomItemLoader(ItemLoader):
    default_output_processor = TakeFirst()
    
    def custom_function(argument1, argument2, argument3):
        # your custom function logic goes here..
        pass

class Product(Item):
    # define the fields for your item here like:
    pass

然后你可以在你的蜘蛛代码中使用CustomItemLoader,像这样:

from <PROJECT-NAME>.items import CustomItemLoader, Product
class MySpider(BaseSpiderName):
   def parse_item(self, response):
      product = CustomItemLoader(item=Product(), response=response)
      product.custom_function(argument, ..., ...)

最新更新