Python Scrapy-如何从另一个Spider方法调用变量? 项目 items.py 使用元参数

问题描述

因此,我试图学习scrapy和用于学习项目,我想从此站点项目名称(仅从1个类别的atm中)https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html进行爬行,然后输入这些项目的网址并获取描述文字

我已经有了写2个Spider的建议,但是我不知道如何在解析方法中从变量中获取数据,从第一个Spider到第二个Spider来填充start_urls。

在这里

import scrapy


class Names(scrapy.Spider):

    name = 'killernames'

    start_urls = ['https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html?viewall=1',]

    def parse(self,response):
        self.detail = response.xpath('//div[contains(@class,"product-item")]/div[@class="name"]/a/@href').getall()

        for item in response.xpath('//div[@class="name"]'):
            yield {
                'name': item.xpath('./a/text()').extract_first(),'url': item.xpath('./a/@href').extract_first(),}

class Detail(scrapy.Spider):

    name = 'killerdetail'

    start_urls = []

    for item in self.detail: (I dont kNow how to get it from first spider)
        url = 'https://www.killertools.com/' + item
        start_urls.append(url)



    def parse(self,response):

        for item in response.xpath('//div[@itemprop="description"]'):
            yield {
                   'detail': item.xpath('./p/strong/text()').extract_first(),}

解决方法

您可以使用一个蜘蛛将链接转到各个页面,而不是使用两个蜘蛛。首先介绍创建蜘蛛的几点,然后介绍一些需要了解的概念才能进行这种抓取。然后是下面的代码示例和说明。

代码查看

  • 使用get()代替extract_first()更为简洁,它将始终为您提供一个字符串,而且草率的文档建议使用
  • 不要混淆使用getall()extract()。有时候extract()会给您一个列表或字符串,getall()总是会给您一个列表。
  • 使用项字典而不是产生字典。尤其是在数据不干净的情况下。

要了解的概念

项目

项字典是scrapy收集数据的惯用方式。它允许您更改传入的数据并在需要时稍后输出。它比产生字典更灵活。 要开始使用项目,您需要在想要用作潜在列的items.py中包括字段名称。在这种情况下,名称,URL,描述。

items.py

进口沙皮

class KillerItem(scrapy.Item):
   
    name = scrapy.Field()
    url = scrapy.Field()
    description = scrapy.Field()

我们正在创建一个KillerItem类,该类将scrapy.Item子类化。我们正在实例化Field()对象,并将其命名为我们要作为列产生的名称。

您还需要在蜘蛛脚本中添加

from ..items import KillerItem

这是一个相对导入,..表示上级目录,item.py位于其中。 KillerItem是需要实例化以创建项目字典的类。我们通过下面的代码来做到这一点。

items = KillerItem()

哪个创建了item字典,但是它具有与我们在items.py中创建的字段名称相对应的键。因此,我们现在可以使用与所需数据相对应的值来填充这些键。在这种情况下,请输入名称,URL和说明。

items['name] = ...

完成项目字典的填充后,我们必须使用yield items。这一点很重要,因为当我们拥有每个页面的名称,URL和描述时,我们要屈服。

使用元参数

您可以通过scrapy请求的meta参数在函数之间传递变量。 meta参数接受一个字典,在这种情况下,我们要转移在解析函数中使用名称和URL创建的项字典。我们希望使用各个页面中的描述填充此项目字典。为此,我们创建一个带有选择键的字典,然后将其值设为实例化KillerItems类时定义的项字典。

meta= {'items',items}

在下一个功能中访问该项目字典,即在其中分析各个页面。我们可以通过响应访问

items = response.meta['items']

我们与我们的items变量保持一致,并通过meta ['items']访问值

现在我们将解释代码示例。

代码示例

import scrapy
from ..items import KillerItem

class Names(scrapy.Spider):

    name = 'killernames'

    start_urls = ['https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html?viewall=1']

    def parse(self,response):
        

        for item in response.xpath('//div[@class="name"]'):
            items = KillerItem()
          
            items['name'] = item.xpath('./a/text()').get()
            items['url'] = 'https://www.killertools.com/' + item.xpath('./a/@href').get()
            

            
            yield response.follow(url=items['url'],callback=self.page,meta={'items':items})
           
    def page(self,response):
       
        items = response.meta['items']
        base = response.xpath('//div[@itemprop="description"]')
        if base.xpath('./p/strong/text()') and base.xpath('./p/span/text()'):
            items['description'] = base.xpath('./p/strong/text()').get().replace('\xa0','') + base.xpath('./p/span/text()').get().replace('\xa0','')
        elif base.xpath('./p/strong/text()'):
            items['description'] = base.xpath('./p/strong/text()').get().replace('\xa0','')
        elif base.xpath('./p/span/text()'):
            items['description'] = base.xpath('./p/span/text()').get().replace('\xa0','')
        elif base.xpath('./span/text()'):
            items['description'] = base.xpath('./span/text()').get().replace('\xa0','')
        elif base.xpath('./h3/text()'):
            items['description'] = base.xpath('./h3/text()').get().replace('\xa0','')
        else:
            items['description'] = base.xpath('./text()').get()
        yield items

解释

解析功能没有太大变化,我们使用您的xpath选择器创建名称和URL的值。我们填充与在items.py中创建的字段名称相对应的items键。

。我们使用response.follow方法,在参数中,我们为for循环的每次迭代指定URL,该URL为items ['url'],我们将其称为self.page的回调函数,我们还使用了meta参数它创建了一个简单的名称项字典,并创建了我们的项字典的值,以将项字典转移到解析函数。

不幸的是,在pages函数中,我们有很多elif语句,因为每个页面的描述不一致。

最后,我们得到了item字典,现在我们有了每个页面的描述。

您实际上并没有指定说明的要点,但是如果需要,您应该有足够的时间获得额外的日期。