所以我很高兴你去看看如何抓取下一页。
现在关于产品编号,这是产生字典很麻烦的地方。在几乎大多数scrapy脚本中使用items字典会更好。它适用于能够从不同页面抓取正是想要做的元素。
Scrapy 从 HTML 中提取数据,它建议这样做的机制是通过他们所谓的项目。现在,scrapy 接受了几种不同类型的方法来将数据放入某种形式的对象中。您可以使用 bog 标准字典,但对于需要修改的数据或除了来自网站的非常结构化的数据集之外几乎没有任何内容的数据,您至少应该使用项目。 Item 提供了一个类似对象的字典。
要在我们的蜘蛛脚本中使用项目机制,我们必须实例化项目类来创建项目的对象。然后,我们用我们想要的数据填充该项目字典,然后在您的特殊情况下,我们跨函数共享此项目字典以继续从不同页面添加数据。
除此之外,我们必须将项目字段名称声明为被调用。但它们是项目字典的键。我们通过位于项目文件夹中的 items.py 来执行此操作。
代码示例
项目.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 的类,因为我们继承自 scrapy.Item,我们可以为我们的项目对象实例化一个字段对象创建。我们要创建的任何字段都给它一个名称并通过scrapy.Field()创建字段对象
在蜘蛛脚本中,我们必须将这个类TopArtItem 导入到我们的蜘蛛脚本中。 from ..items 是一个相对导入,这意味着我们要从蜘蛛脚本的父目录中从 items.py 中获取一些东西。
现在这里的代码看起来有点熟悉。首先在我们使用 items = TopArtItem() 的 for 循环中创建名为 items 的特定项目的字典。
添加到items字典的方式和其他python字典类似,items字典中的key就是我们在items.py中创建的字段。
变量link 是指向特定页面的链接。然后我们获取您之前看到的我们想要的数据。
因此,当我们填充我们的项目字典时,我们需要从各个页面中获取产品编号。我们通过点击链接来做到这一点,回调是我们想要将 HTML 从单个页面发送到的函数。
meta = {'items',items} 是我们将项目字典传输到该函数parse_item 的方式。我们创建一个元字典,键名为 items,值是我们刚刚创建的 items 字典。
然后我们创建了函数parse_item。要访问该项目字典,我们必须通过response.meta 访问它,该字典包含我们在上一个函数中发出请求时创建的元字典。 response.meta['items'] 是我们访问项目字典的方式,然后我们像以前一样调用它items。
现在我们可以从前面的函数中填充已经包含数据的项目字典,并将产品编号添加到其中。然后,我们最终生成项目字典,告诉 scrapy 我们已经完成了从这张特定卡片中提取数据的添加。
总结一下 parse 函数中的工作流程,我们有一个循环,对于每个循环迭代,我们都跟踪一个链接,我们首先提取四个数据,然后让 scrapy 跟踪特定链接并添加第 5 个数据在移动到原始 html 文档中的下一张卡片之前。
附加信息
-
注意,如果您只想抓取一条数据,请尝试使用get(),如果您想抓取多条数据,请尝试使用getall()。这不是extract_first() 和extract()。如果你查看scrapy docs,他们推荐这个。 get() 更加简洁,当使用extract() 时,您并不总是确定是否会获得字符串或列表作为提取的数据。 getall 总会给你一个列表。
-
建议您在其他 scrapy 脚本中查找其他项目示例。通过搜索github或其他网站。我建议您在了解工作流程后仔细阅读文档here 上的项目页面。这很清楚,但不友好。我认为当您多次创建带有项目的脚本时,它会更容易理解。
更新了下一页链接
我已将您用于 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,它为我们提供了到第二页的链接。然后我们使用最后一页的变量 + 1,因为 range 函数只会通过选择 lastpage+1 来处理最后一页。创建第三页网址。然后我们也关注第 3 页的 url。