使用自定义方法扩展Scrapy ItemLoader

时间:2019-02-02 13:44:51

标签: python scrapy

Scrapy文档列出了所有the built-in methods of ItemLoader instances并解释了how to declare your own Item Loaders。但是,您声明的任何ItemLoader都将应用于所有已处理的项目。您可以使用Item Loader Contexts稍微修改他们的行为,但这通常不够精细。<​​/ p>

假设我有一个Scrapy项目,其中所有Spider和所有项都继承相同的基本Spider和项目加载器,但这些Spider都包含具有一些通用功能的特定于站点的逻辑。在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, ..., ...)

尽管这似乎是扩展ItemLoader的一种显而易见的方法,就像您对其他任何类的扩展一样,但未记录该文档,并且在我检查过的任何地方(Google,StackOverflow),我都没有看到如何在Scrapy中执行此操作的示例。有可能/是否受支持,您将如何声明它们?

2 个答案:

答案 0 :(得分:0)

  

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

有可能。哪种方法取决于您共享的逻辑类型。

您可以以与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))

或者,根据您在 some 蜘蛛共享的函数中所具有的实际逻辑,可以将简单的processor传递给add_*方法去。

答案 1 :(得分:0)

您可以在 CustomItemLoader 文件中定义 items.py 类,您在其中定义了 Product 项目,如下所示:

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, ..., ...)