Python Scrapy - 如何从另一个蜘蛛方法调用变量?

Python Scrapy - how to call variable from another spider method?

所以我正在尝试学习 scrapy,为了学习项目,我想抓取该站点的项目名称(仅来自 1 个类别的 atm)https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html,然后输入这些项目 url 并获取描述文本。

我已经得到一些编写 2 个蜘蛛的建议,但我不知道如何从第一个蜘蛛的解析方法中的变量获取数据到第二个蜘蛛以填充 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(),它更简洁,总是会给你一个字符串,scrapy文档建议它
  • 不要混淆使用 getall()extract()。有时 extract() 会给你一个列表或一个字符串,getall() 总是会给你一个列表。
  • 使用项目字典而不是生成字典。特别是在这种数据不干净的情况下。

需要了解的概念

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

items.py

导入 scrapy

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

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

您还需要在蜘蛛脚本中包含

from ..items import KillerItem

这是相对导入,.. 表示 items.py 所在的父目录。 KillerItem 是一个 class 需要实例化以创建项目字典。我们通过下面的代码来做到这一点。

items = KillerItem()

它创建了项目字典,但它具有与我们在 items.py 中创建的字段名称相对应的键。所以我们现在可以用对应于我们想要的数据的值来填充这些键。在这种情况下,名称,URL 和描述。

items['name] = ...

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

使用元参数

您可以通过 scrapy 请求的元参数将变量从一个函数传递到另一个函数。 meta 参数接受一个字典,在这种情况下,我们想要传输我们在解析函数中创建的带有名称和 URLs 的项目字典。我们想用各个页面的描述来填充这个项目字典。我们通过创建一个带有我们选择的键的字典来做到这一点,然后该值是我们在实例化 KillerItems class.

时定义的项目字典。
meta= {'items',items}

在下一个函数中访问此项目字典,即对各个页面进行解析的地方。我们可以通过response

访问
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.

中创建的字段名称相对应的项目键

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

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

最后我们生成项目字典,现在我们有了每个单独页面的描述。

你并没有真正指定描述要点,但如果你需要的话,你应该有足够的时间去做额外的约会。