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




