Scrapy 蜘蛛停止抓取

问题描述 投票:0回答:1

我正在开发一个 Scrapy 蜘蛛来从网站的多个页面中抓取数据。目标是爬行每个起始 URL 的所有页面,但我希望蜘蛛在爬行每个起始 URL 的最大页面后停止。然而,蜘蛛并没有按预期工作,它并没有爬过所有页面。

我尝试使用字典来实现计数管理,以跟踪每个 URL 抓取的页面数量。这是我当前的实现:

def parse(self, response):
    # Get the current count from the request's
    self.counts = {url: 1 for url in self.start_urls}  # Initialize count for each start URL

    # Check if the count has reached 100
    count = self.counts[response.url]
    if count > 100:
        return  # Stop crawling further

    # Increment the count for the next page
    self.counts[response.url] += 1

    # Parse the items on the current page
    for result in response.xpath(".//h2/a"):
        yield scrapy.Request(url=result.xpath("@href").extract_first(), callback=self.parse_item)

    # Generate the URL for the next page and request it
    next_page_url = response.url + f"?page={count}"
    yield scrapy.Request(next_page_url, callback=self.parse)

蜘蛛似乎启动并爬行了一些页面,但它在到达每个起始 URL 的所有页面之前停止了。我不确定我哪里出错了。如何修改蜘蛛程序以确保其爬行每个起始 URL 的所有页面(最多 100 页)?任何帮助或见解将不胜感激。

提前谢谢您!

python loops web-scraping scrapy
1个回答
1
投票

您的方法存在很多问题。

  1. 您正在初始化解析方法内部的计数机制。这意味着每次调用 parse 方法时,它都会重建对象并删除以前的版本。

  2. 然后在下一行查询当前 url 的计数,因此结果要么为 1,要么在 request.url 不在其中的情况下抛出 KeyError 异常start_urls。

  3. 然后检查计数是否大于 100,这将始终为 False,因为如果它在上一步中幸存下来,则意味着它位于

    start_urls
    中,因此它的计数将为 1,因为您之前刚刚初始化了 2 条指令。

  4. 最后,您将为下一页生成一个新的 url,并创建一个由相同方法解析的请求,这意味着该请求可能不会在

    start_urls
    中,几乎保证它会抛出我之前提到的 KeyError 异常。

所以你所做的实际上是创建一种方法,几乎可以保证你永远不会超过 start_urls 中任何 url 的第一页,并且你的计数器永远没有机会达到 3,更不用说 100 了。

更好的选择是在解析方法之外初始化计数器字典,并将其作为蜘蛛的类属性而不是实例属性。但即便如此,这也无法实现您期望的目标,因为每个

next_page
请求生成的每个
start_url
都将具有唯一的 url,因此不会以您正在寻求的方式对计数器做出贡献。

更好的替代方法是重写 start_requests 方法,并在初始请求的 cb_kwargs 参数中包含一个计数器,您可以手动递增该计数器并将其传递到每个下一页,直到达到 100。

例如:

class MySpider(scrapy.Spider):

    name = "spidername"
    start_urls = [...]

    def start_requests(self):
        for url in self.start_urls:
             yield scrapy.Request(url, callback=self.parse, cb_kwargs={"count": 1})

    def parse(self, response, count=None):
        if count >= 100:
            return
        for result in response.xpath(".//h2/a"):
            yield scrapy.Request(url=result.xpath("@href").extract_first(), callback=self.parse_item)
         
        next_page_url = response.url + f"?page={count}"
        yield scrapy.Request(next_page_url, callback=self.parse, cb_kwargs={"count": count + 1})
© www.soinside.com 2019 - 2024. All rights reserved.