You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Scrapy结合Selenium爬取时,WebDriver应在何时关闭?

关于Scrapy+Selenium中WebDriver的关闭时机问题

嘿,我来帮你理清楚这个WebDriver关闭的问题~

首先明确说:完全不需要在处理完每个链接后关闭WebDriver!这么做反而会拖慢你的爬取速度——每次关闭再重新启动浏览器,不仅耗时,还会频繁创建销毁进程,反而更容易导致资源残留,htop里的实例也会反复折腾,完全没必要。

然后说你现在用的__del__方法的问题:Python的__del__魔法方法其实非常不可靠,因为它的执行时机由垃圾回收机制决定,可能爬虫已经结束了,垃圾回收还没触发,导致WebDriver进程一直留在后台,这就是你在htop里能看到残留实例的原因之一。

正确的做法:利用Scrapy的spider_closed信号关闭WebDriver

Scrapy提供了专门的信号机制来处理爬虫生命周期的收尾工作,spider_closed信号会在爬虫无论正常结束还是异常终止时触发,这是最稳妥的关闭时机。

给你调整后的代码示例:

from scrapy import signals
from scrapy.spiders import Spider
from selenium import webdriver
from your_project.items import MyTestItem

class MyTestSpider(Spider):
    name = 'my_test_spider'
    array_links = ["https://example.com/link1", "https://example.com/link2"]  # 你的链接数组

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 初始化WebDriver(这里以Chrome为例,可替换为你使用的浏览器)
        self.driver = webdriver.Chrome()
        # 绑定spider_closed信号到自定义关闭方法
        self.crawler.signals.connect(self.close_webdriver, signal=signals.spider_closed)

    def parse(self, response):
        for link in self.array_links:
            self.driver.get(link)
            # 你的解析逻辑
            item = MyTestItem()
            item['test1'] = "test"
            yield item

    def close_webdriver(self, spider):
        # 彻底关闭WebDriver,释放所有关联资源
        self.driver.quit()

额外注意点:driver.quit() vs driver.close()

  • driver.quit():会彻底关闭整个浏览器进程,清除所有相关的内存和资源,是推荐的收尾方式。
  • driver.close():仅仅关闭当前的浏览器标签页,如果这是最后一个标签页,浏览器也会关闭,但相比之下quit()更彻底,能避免残留进程。

为什么这个方法能解决htop里的实例问题?

当爬虫结束时,spider_closed信号会立即触发close_webdriver方法,调用driver.quit()彻底终止浏览器进程,这样htop里就不会再有残留的WebDriver实例了,比依赖不可靠的__del__靠谱得多。

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

火山引擎 最新活动