Scrapy 抓取从 csv 或数组中保存的链接

Scrapy crawl saved links out of csv or array

import scrapy

class LinkSpider(scrapy.Spider):
    name = "articlelink"
    allow_domains = ['topart-online.com']
    start_urls = ['https://www.topart-online.com/de/Blattzweige-Blatt-und-Bluetenzweige/l-KAT282?seg=1']
    
    BASE_URL = 'https://www.topart-online.com/de/'
#scraping cards of specific category
    def parse(self, response):
        card = response.xpath('//a[@class="clearfix productlink"]')
        for a in card:
            yield{
                'links': a.xpath('@href').get()
            }

        next_page_url = response.xpath('//a[@class="page-link"]/@href').extract_first()
        if next_page_url:
            next_page_url = response.urljoin(next_page_url)
            yield scrapy.Request(url=next_page_url, callback=self.parse)

这是我的蜘蛛,当我在我的服务器“scrapy crawl articlelink -o filename.csv”中 运行 时,它会抓取该类别的所有页面并将所有产品链接保存到 csv 文件中。 现在我必须爬取我的 csv 文件中的所有链接以获取特定信息,这些信息不包含在 productlink clearfix 的卡片中 我该如何饱和?

所以我很高兴你已经去看看如何抓取下一页。

现在关于 productean 编号,这就是产生字典很麻烦的地方。在几乎大多数 scrapy 脚本中,使用 items 字典会更好。它适合能够从不同的页面抓取元素,这正是我们想要做的。

Scrapy 从 HTML 中提取数据,它建议这样做的机制是通过他们所谓的项目。现在 scrapy 接受几种不同类型的方法将数据放入某种形式的对象中。您可以使用沼泽标准词典,但对于需要修改的数据,或者除了来自网站的非常结构化的数据集之外几乎没有任何内容,您至少应该使用项目。 Item's 提供了一个类似对象的字典。

要在蜘蛛脚本中使用项目机制,我们必须实例化项目 class 以创建项目的对象。然后我们用我们想要的数据填充该项目字典,然后在您的特定情况下,我们跨功能共享该项目字典以继续从不同页面添加数据。

除此之外,我们还必须声明所调用的项目字段名称。但它们是项目字典的关键。我们通过位于项目文件夹中的 items.py 执行此操作。

代码示例

items.py

import scrapy

class TopartItem(scrapy.Item):
    
    title = scrapy.Field()
    links = scrapy.Field()
    ItemSKU = scrapy.Field()
    Delivery_Status = scrapy.Field()
    ItemEAN = scrapy.Field()

蜘蛛脚本

import scrapy
from ..items import TopartItem

class LinkSpider(scrapy.Spider):
    name = "link"
    allow_domains = ['topart-online.com']
    start_urls = ['https://www.topart-online.com/de/Blattzweige-Blatt-und-Bluetenzweige/l-KAT282?seg=1']
    custom_settings = {'FEED_EXPORT_FIELDS': ['title','links','ItemSKU','ItemEAN','Delivery_Status'] } 
    def parse(self, response):
        card = response.xpath('//a[@class="clearfix productlink"]')
        
        for a in card:
            items = TopartItem()
            link = a.xpath('@href')
            items['title'] = a.xpath('.//div[@class="sn_p01_desc h4 col-12 pl-0 pl-sm-3 pull-left"]/text()').get().strip()
            items['links'] = link.get()
            items['ItemSKU'] = a.xpath('.//span[@class="sn_p01_pno"]/text()').get().strip()
            items['Delivery_Status'] = a.xpath('.//div[@class="availabilitydeliverytime"]/text()').get().strip().replace('/','')
            yield response.follow(url=link.get(),callback=self.parse_item, meta={'items':items})

        last_pagination_link = response.xpath('//a[@class="page-link"]/@href')[-1].get()
        last_page_number = int(last_pagination_link.split('=')[-1])
        for i in range(2,last_page_number+1):
            url = f'https://www.topart-online.com/de/Blattzweige-Blatt-und-Bluetenzweige/l-KAT282?seg={i}'
            yield response.follow(url=url, callback=self.parse)
    

    def parse_item(self,response):
        items = response.meta['items']
        items['ItemEAN'] = response.xpath('//div[@class="productean"]/text()').get().strip()
        yield items

解释

首先在 items.py 中,我们正在创建一个名为 TopArtItem 的 class,因为我们继承自 scrapy.Item,我们可以为我们的项目对象实例化一个字段对象创建。我们要创建的任何字段我们给它一个名称并通过 scrapy.Field()

创建字段对象

在蜘蛛脚本中,我们必须将此 class TopArtItem 导入到我们的蜘蛛脚本中。 from ..items 是相对导入,这意味着我们要从蜘蛛脚本的父目录中获取 items.py.

中的内容

现在这里的代码看起来有点眼熟。首先在我们使用 items = TopArtItem().

的 for 循环中创建名为 items 的特定项目字典

添加到 items 字典的方法与任何其他 python 字典相似,items 字典中的键是我们在 items.py.

中创建的字段

变量link是指向特定页面的link。然后我们获取您之前看到的我们想要的数据。 因此,当我们填充 items 字典时,我们需要从各个页面中获取 productean 编号。我们通过 link 执行此操作,回调是我们要将 HTML 从单个页面发送到的函数。

meta = {'items',items} 是我们将项目字典传输到该函数 parse_item 的方式。我们创建一个元字典,键名为 items,值是我们刚刚创建的 items 字典。

然后我们创建了函数 parse_item。要访问该项目字典,我们必须通过 response.meta 访问它,它包含我们在上一个函数中发出请求时创建的元字典。 response.meta['items'] 是我们访问项目字典的方式,然后我们像以前一样调用它 items

现在我们可以填充 items 字典,其中已经包含来自上一个函数的数据,并向其中添加 productean 编号。然后我们最终生成那个项目字典来告诉 scrapy 我们已经完成添加数据以从这个特定的卡片中提取。

总而言之,解析函数中的工作流程我们有一个循环,对于每个循环迭代,我们都遵循一个 link,我们首先提取四块数据,然后让 scrapy 遵循特定的 link 并在移动到原始 html 文档中的下一张卡片之前添加第 5 条数据。

附加信息

  1. 注意,如果只抓取一条数据尽量用get(),多条数据尽量用getall()。这代替了 extract_first()extract()。如果您查看 scrapy 文档,他们会推荐这个。 get() 更简洁一些,当使用 extract() 时,您并不总是确定您将获得字符串还是列表作为提取的数据。 getall 总会给你一个列表。

  2. 建议您在其他scrapy脚本中查找其他项目示例。通过搜索 github 或其他网站。我建议您在了解工作流程后仔细阅读文档 here 上的项目页面。很清楚,但示例不友好。我认为当你多次创建带有项目的脚本时它更容易理解。

更新了下一页 links

我已经用获取所有数据的更可靠的方式替换了您为 next_page 使用的代码。

last_pagination_link = response.xpath('//a[@class="page-link"]/@href')[-1].get()
last_page_number = int(last_pagination_link.split('=')[-1])
for i in range(2,last_page_number+1):
    url = f'https://www.topart-online.com/de/Blattzweige-Blatt-und-Bluetenzweige/l-KAT282?seg={i}'
    yield response.follow(url=url, callback=self.parse)
    

我们在这里为最后一页创建一个变量并从中获取数字。我做这个是因为如果你有超过 3 页的页面。

我们正在执行 for 循环并为每次迭代创建 url。这个 url 里面有所谓的 f-string。 f'' 这允许我们在字符串中植入一个变量,并使用 for 循环将数字或任何其他内容添加到 url 中。所以我们首先将数字 2 放入 url 中,这使我们在第 2 页中得到 link。然后我们使用最后一页 + 1 的变量,因为范围函数只会通过选择 lastpage+1 来处理最后一页。创建第 3 页 url。然后我们也关注第 3 页 url。