由於Webdriver每次實例化都會新開一個全新的瀏覽器會話,在有些狀況下須要複用以前打開未關閉的會話。好比爬蟲,但願結束腳本時,讓瀏覽器處於空閒狀態。當腳本從新運行時,它將繼續使用這個會話工做。還就是在作自動化測試時,前面作了一大推操做,可是因爲程序出錯,重啓時不用再繼續前面複雜的操做。java
我的以爲這種功能很是有用,可是官方竟然沒有提供這種功能的API,苦苦搜搜,在網上找了兩個java版的http://blog.csdn.net/wwwqjpcom/article/details/51232302 和 http://woxiangbo.iteye.com/blog/2372683
看了下源碼其實java和python的驅動原理過程都很是類似。python
打開一個Chrome會話:web
from selenium import webdriver driver = webdriver.Chrome()
運行上面的腳本,它將啓動瀏覽器並退出。由於沒有調用quit()
方法,因此瀏覽器會話仍會存在。可是代碼裏建立的driver
對象已經不在了,理論上不能用腳本控制這個瀏覽器。它將變成一個殭屍瀏覽器,只能手動殺死它。chrome
經過webdriver啓動一個瀏覽器會話大概會有這樣三個階段:shell
sessionId
來標識會話。所以只要拿到階段2中的執行器和階段3中的sessionID
就能恢復上次的會話。這兩個有api能夠直接獲取:api
from selenium import webdriver driver = webdriver.Chrome() executor_url = driver.command_executor._url session_id = driver.session_id print(session_id) print(executor_url) driver.get("http://www.spiderpy.cn/")
獲得相似這樣的輸出(第一個是會話的sessionId,第二個就是命令執行器鏈接):瀏覽器
397d725f042a076f7d4a82f7d3fead13 http://127.0.0.1:52869
一切就緒,下面就開始實現複用以前會話的功能,在Stack Overflow上面講的實現是這樣的:session
from selenium import webdriver driver = webdriver.Chrome() executor_url = driver.command_executor._url session_id = driver.session_id driver.get("http://www.spiderpy.cn/") print(session_id) print(executor_url) driver2 = webdriver.Remote(command_executor=executor_url, desired_capabilities={}) driver2.session_id = session_id print(driver2.current_url)
多是由於版本緣由吧,反正在我環境中運行時,效果是實現了,可以從新鏈接到上一個會話,可是卻打開了一個新的空白會話。看了下Remote
類的源碼,發現是由於每次實例化都會調用start_session
這個方法新建一個會話。因此解決方法就是繼承並重寫這個類。自定義一個ReuseChrome
這個類重寫start_session
方法使它再也不新建session,使用傳入的session_id:ide
from selenium.webdriver import Remote from selenium.webdriver.chrome import options from selenium.common.exceptions import InvalidArgumentException class ReuseChrome(Remote): def __init__(self, command_executor, session_id): self.r_session_id = session_id Remote.__init__(self, command_executor=command_executor, desired_capabilities={}) def start_session(self, capabilities, browser_profile=None): """ 重寫start_session方法 """ if not isinstance(capabilities, dict): raise InvalidArgumentException("Capabilities must be a dictionary") if browser_profile: if "moz:firefoxOptions" in capabilities: capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded else: capabilities.update({'firefox_profile': browser_profile.encoded}) self.capabilities = options.Options().to_capabilities() self.session_id = self.r_session_id self.w3c = False
而後在第二次鏈接是使用重寫的ReuseChrome
類:測試
from selenium import webdriver # 第一次使用Chrome() 新建瀏覽器會話 driver = webdriver.Chrome() # 記錄 executor_url 和 session_id 以便複用session executor_url = driver.command_executor._url session_id = driver.session_id # 訪問百度 driver.get("http://www.spiderpy.cn/") print(session_id) print(executor_url) # 假如driver對象不存在,但瀏覽器未關閉 del driver # 使用ReuseChrome()複用上次的session driver2 = ReuseChrome(command_executor=executor_url, session_id=session_id) # 打印current_url爲百度的地址,說明覆用成功 print(driver2.current_url) driver2.get("https://www.baidu.com")
這樣就能順利鏈接到上次沒關閉的瀏覽器會話。