Scrapy-Playwright爬虫爬取一定页面后停滞,日志显示0页/分钟排查
Scrapy-Playwright爬虫爬取停滞的原因及修复方案
核心问题成因
1. Playwright页面实例未及时释放,耗尽浏览器资源
请求中设置了playwright_include_page=True,但仅在errback中关闭了失败请求对应的页面,成功请求的页面未在parse方法中关闭。Playwright的浏览器上下文默认有页面数量限制(通常为16个),当爬取URL数量超过该限制后,新请求无法创建新页面,导致爬虫停滞。
2. 错误使用Scrapy Rule机制
爬虫继承自scrapy.Spider,却手动设置了self._rules。Rule是CrawlSpider专属的规则配置,普通Spider类不会处理这些规则,会干扰Scrapy的请求调度逻辑,引发后续请求无法正常调度。
3. 重写__init__未调用父类构造函数
重写Spider的__init__方法时未执行super().__init__(),导致Scrapy内置的初始化逻辑(如请求队列、信号注册等)无法正常运行,可能引发调度异常。
修复后的代码示例
my_spider.py
import scrapy from faker import Faker fake = Faker() class MySpider(scrapy.Spider): name = 'my_spider' # 直接定义start_urls,无需重写__init__ start_urls = ['https://dummy0.example.com', 'https://dummy100.example.com'] # 替换为实际URL列表 def start_requests(self): for url in self.start_urls: yield scrapy.Request( url, headers={'User-Agent': fake.user_agent()}, meta=dict( playwright=True, playwright_include_page=True, errback=self.errback, ) ) async def parse(self, response): page_title = response.xpath('//title/text()').get() yield { 'url': response.url, 'title': page_title } # 关闭成功请求的页面,释放资源 page = response.meta["playwright_page"] await page.close() async def errback(self, failure): page = failure.request.meta.get("playwright_page") if page: await page.close()
settings.py(修正超时注释)
REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7" TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor" FEED_EXPORT_ENCODING = "utf-8" DOWNLOAD_HANDLERS = { "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler", } PLAYWRIGHT_DEFAULT_NAVIGATION_TIMEOUT = 10 * 1000 # 10秒超时,按需调整
额外优化建议
- 若仅需获取页面HTML,无需操作DOM,可移除
playwright_include_page=True,Scrapy-Playwright会自动处理页面关闭,减少资源占用。 - 可通过
PLAYWRIGHT_MAX_PAGES_PER_CONTEXT配置更大的页面上限,但优先推荐及时关闭页面的方案,避免不必要的资源消耗。
内容的提问来源于stack exchange,提问作者hafiz031
相关产品推荐
相关产品推荐

