You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ScrapyRequest结合Rule与LinkExtractor爬取仅完成第一页后停止求助

问题根源分析
  1. CrawlSpider规则失效:你重写了parse方法,而CrawlSpider的Rule逻辑依赖默认parse方法来提取链接、生成后续请求,导致规则无法触发,自然不会跟进其他页面。
  2. 普通Request无法渲染JS:即使规则生效,默认生成的是普通Scrapy Request,不会经过Selenium渲染,JS动态加载的链接无法被提取,爬虫也无法继续爬取。

解决方案

方案一:修复CrawlSpider规则,用Selenium处理所有请求

自定义process_request函数,让Rule生成SeleniumRequest,同时避免覆盖默认parse方法:

import scrapy
from scrapy_selenium import SeleniumRequest
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

def selenium_process_request(request, response):
    # 将普通Request转为SeleniumRequest,确保所有请求都经过JS渲染
    return SeleniumRequest(
        url=request.url,
        dont_filter=True,
        callback=response.request.callback
    )

class MySpider(CrawlSpider):
    name = 'example'
    start_urls = ['https://www.example.com/']
    rules = (
        Rule(
            LinkExtractor(allow_domains=['example.com']),
            follow=True,
            process_request=selenium_process_request,
            callback='parse_item'  # 自定义页面解析方法,不覆盖默认parse
        ),
    )

    def start_requests(self):
        for url in self.start_urls:
            print("+++++++++++++++++++++++++++++++++++++++++++++++++++++",url)
            yield SeleniumRequest(url=url, callback=self.parse,dont_filter=True)

    def parse_item(self, response):
        print(response.url)
        item = {'url': response.url, 'html': response.body}
        yield item

    custom_settings = {
        'DOWNLOADER_MIDDLEWARES': {
            'scrapy_selenium.SeleniumMiddleware': 800
        },
        'SELENIUM_DRIVER_NAME': 'chrome',
        'SELENIUM_DRIVER_EXECUTABLE_PATH': '/home/ubuntu/selenium_drivers/chromedriver',
        'SELENIUM_DRIVER_ARGUMENTS': ['-headless']
    }

方案二:改用普通Spider,手动提取链接

放弃CrawlSpider的规则,自己维护已访问URL集合,手动生成SeleniumRequest:

import scrapy
from scrapy_selenium import SeleniumRequest
from scrapy.linkextractors import LinkExtractor

class MySpider(scrapy.Spider):
    name = 'example'
    start_urls = ['https://www.example.com/']
    allowed_domains = ['example.com']
    visited_urls = set()  # 避免重复爬取

    def start_requests(self):
        for url in self.start_urls:
            print("+++++++++++++++++++++++++++++++++++++++++++++++++++++",url)
            self.visited_urls.add(url)
            yield SeleniumRequest(url=url, callback=self.parse,dont_filter=True)

    def parse(self, response):
        print(response.url)
        item = {'url': response.url, 'html': response.body}
        yield item

        # 提取当前页面所有符合域名的链接
        link_extractor = LinkExtractor(allow_domains=self.allowed_domains)
        for link in link_extractor.extract_links(response):
            if link.url not in self.visited_urls:
                self.visited_urls.add(link.url)
                # 生成SeleniumRequest确保JS渲染
                yield SeleniumRequest(url=link.url, callback=self.parse, dont_filter=True)

    custom_settings = {
        'DOWNLOADER_MIDDLEWARES': {
            'scrapy_selenium.SeleniumMiddleware': 800
        },
        'SELENIUM_DRIVER_NAME': 'chrome',
        'SELENIUM_DRIVER_EXECUTABLE_PATH': '/home/ubuntu/selenium_drivers/chromedriver',
        'SELENIUM_DRIVER_ARGUMENTS': ['-headless']
    }

额外检查点
  • 确认ChromeDriver与Chrome浏览器版本完全匹配,版本不兼容会导致Selenium无法正常提取页面链接。
  • 如果页面链接是滚动/点击加载的,需在SeleniumRequest中添加等待条件:
    yield SeleniumRequest(
        url=url,
        callback=self.parse,
        dont_filter=True,
        wait_until=lambda driver: driver.execute_script('return document.readyState') == 'complete'
    )
    

内容的提问来源于stack exchange,提问作者Hans M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:46:29