最近在搞爬虫,然后顺便写了写基于 selenium
框架的模拟登陆脚本供以后需要时用,然而在这时我发现了一个问题:
代码一开始是这样的:
from selenium import webdriver
driver = webdriver.Chrome()
driver.maximize_window()
driver.get('http://mail.163.com')
driver.find_element_by_id('switchAccountLogin').click()
iframe = driver.find_element_by_xpath('//*[@id="loginDiv"]/iframe') # 使用Xpath选定位到iframe
driver.switch_to.frame(iframe) # 切换iframe
# iframe = driver.find_element_by_xpath("//iframe[contains(@id, 'x-URS-iframe')]") # 使用Xpath提供的contains定位
# driver.switch_to.frame(iframe)
driver.find_element_by_name('email').send_keys('name')
driver.find_element_by_name('password').send_keys('password')
driver.find_element_by_id('dologin').click()
然后进行了简单的改造:
from selenium import webdriver
class Mail163:
def __init__(self, name, password):
self.name = name
self.password = password
self.driver = webdriver.Chrome()
def run(self):
# driver.maximize_window()
self.driver.get('http://mail.163.com')
self.driver.find_element_by_id('switchAccountLogin').click()
iframe = self.driver.find_element_by_xpath('//*[@id="loginDiv"]/iframe') # 使用Xpath选定位到iframe
self.driver.switch_to.frame(iframe) # 切换iframe
# iframe = driver.find_element_by_xpath("//iframe[contains(@id, 'x-URS-iframe')]") # 使用Xpath提供的contains定位
# driver.switch_to.frame(iframe)
self.driver.find_element_by_name('email').send_keys(self.name)
self.driver.find_element_by_name('password').send_keys(self.password)
self.driver.find_element_by_id('dologin').click()
if __name__ == "__main__":
Mail163('111', 'aaa').run()
这个时候我发现,原来运行代码之后,Chrome 依然存在;而在将其函数化之后,运行完了代码 Chrome 便会直接闪退。
这时我便想到,这可能跟 Python 的函数运行机制有关,所以我连忙查了一下资料,终于发现了其原理。
在代码中,Mail163
调用时,触发了 selenium/webdriver/common/service.py
中 Service#__del__
方法;
Service#__del__
调用了同类中的 Service#stop
方法;
Service#stop
调用了同类中的 Service#send_remote_shutdown_command
方法;
Service#send_remote_shutdown_command
中的 url_request.urlopen("%s/shutdown" % self.service_url)
导致浏览器关闭。
因此结论就很明显了,当 webdriver
在局部域内被定义时,其代码运行结束后会进行 del
的操作去做资源清理(垃圾回收)。
所以如果需要在登录操作运行完后保持 Chrome 的运行,可以将 webdrive 定义部分代码 drive = webdriver.Chrome()
放到函数体外,从而避免被清理。