0

所以我试图学习scrapy和学习项目我想刮这个网站的项目名称(来自只有1个类别的atm)https://www.killertools.com/Dent-Removal-Aluminum-Steel_c_11.html然后输入这些项目的网址并抓取描述文本。

我已经得到了一些编写 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(),
                  }
4

1 回答 1

4

您可以使用一个蜘蛛跟踪各个页面的链接,而不是使用两个蜘蛛。首先是关于创建蜘蛛的几点,然后是一些你需要理解的概念才能进行这种类型的抓取。然后是下面的代码示例和解释。

代码审查

  • 使用get()而不是extract_first(),它更简洁,总是会给你一个字符串,scrapy docs会建议它
  • 不要混淆使用getall()with extract()。有时 extract() 会给你一个列表或一个字符串,getall()总是会给你一个列表。
  • 使用项目字典而不是产生字典。特别是在这种数据不干净的情况下。

要知道的概念

项目

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

项目.py

导入scrapy

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

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

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

from ..items import KillerItem

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

items = KillerItem()

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

items['name] = ...

当我们完成填充项目字典后,我们必须使用yield items. 这很重要,因为当我们拥有每个单独页面的名称、URL 和描述时,我们希望产生。

元参数的使用

您可以通过 scrapy 请求的元参数在函数之间传输变量。meta 参数接受一个字典,在这种情况下,我们希望传输我们在 parse 函数中创建的包含名称和 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

解释

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

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

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

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

您并没有真正指定描述要点,但如果您需要,您应该有足够的时间去获得额外的日期。

于 2020-09-08T10:36:06.947 回答