一. webdriver中常用的cookie方法
webdriver中提供了操作cookie的相關方法:
-
get_cookies() 獲得cookie信息
-
add_cookie(cookie_dict) 添加cookie
-
delete_cookie(name) 刪除特定(部分)的cookie
-
delete_all_cookies() 刪除所有的cookie
二. add_cookie()的用法
1. 源碼中的解釋
源碼中簡略的向我們展示了如何添加cookie,源碼如下:
def add_cookie(self, cookie_dict): """ Adds a cookie to your current session. :Args: - cookie_dict: A dictionary object, with required keys - "name" and "value"; optional keys - "path", "domain", "secure", "expiry" Usage: driver.add_cookie({'name' : 'foo', 'value' : 'bar'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'}) driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True}) """ self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict})
從中可以看出add_cookie()這個函數有一個參數cookie_dict,它是以字典的形式傳入的,字典中必選的鍵是"name"和"value",可選的鍵是"path", "domin", "secure", "expiry",其實源碼中還漏了一個:"httponly"
2. cookie中鍵名的含義
這些鍵名都代表什么意思呢?參考博文《selenium3.7+ python3 添加cookie模擬登陸》,羅列如下
-
name:cookie的名稱
-
value:cookie對應的值,動態生成的
-
domain:服務器域名
-
expiry:Cookie有效終止日期
-
path:Path屬性定義了Web服務器上哪些路徑下的頁面可獲取服務器設置的Cookie
-
httpOnly:防腳本攻擊
-
secure:在Cookie中標記該變量,表明只有當瀏覽器和Web Server之間的通信協議為加密認證協議時
三. 實例(以課堂派的登錄為例)
第一步:我們先手工做一次登錄,打開chrome的調試工具(F12),選擇Network—Preserve log—XHR
第二步:點擊登錄,打開調試工具中的login,可以看到右邊Response Headers下面就出現了服務器返回給瀏覽器的cookie
第三步:python代碼的實現,最容易出現問題的可能是這一步
1 from selenium import webdriver 2 3 driver = webdriver.Chrome() 4 cookies = {'value': 'think%3A%7B%22username%210293%31628193MDAwMDAwMLOGpZaIudFqhc6Gl7LQetmZtmfOk2RhbQ%22%2C%22expire%sfdaaswMDAwMDAwMLOGud6Gqb-whbiCmLOmdZ4%22%2C%22token%22%3A%22MDAwMDAwMDAwMMurrpWavLehhs1-3LLfgduEt4OWepuo123456123KZq6HQxtOK0ZCme5p-q6iZu2yrn4uNhJ3KedDYk7ivboS4it6910926YW0%22%7D', 5 'name': 'ketangpai_home_remember'} 6 7 driver.add_cookie(cookie_dict=cookies) 8 driver.get("https://www.ketangpai.com/Main/index.html")
運行結果后發現報錯了:Message: unable to set cookie
Traceback (most recent call last): File "D:/python_workshop/python6/selenium_webdriver/add_cookies的使用(二).py", line 9, in <module> driver.add_cookie(cookie_dict=cookies) File "D:\Program\python34\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 872, in add_cookie self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict}) File "D:\Program\python34\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 312, in execute self.error_handler.check_response(response) File "D:\Program\python34\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.WebDriverException: Message: unable to set cookie (Session info: chrome=66.0.3359.139) (Driver info: chromedriver=2.35.528161 (5b82f2d2aae0ca24b877009200ced9065a772e73),platform=Windows NT 6.1.7600 x86_64)
第四步:修改代碼,解決問題
這篇標題很長的文章給我們提供了一個解決方案——《Selenium: Trying to log in with cookies and get the errorMessage - “Can only set cookies for current domain” or "Unable to set Cookie"》
"技術提示:必須首先加載網站,這樣Selenium 才能知道cookie 屬於哪個網站,即使加載網站的行為對我們沒任何用處"
只需要給原來的代碼加上一句(紅色部分),這個url填"https://www.ketangpai.com/User/login.html"或"https://www.ketangpai.com/Main/index.html"都行,只要是同一個domain就行,瀏覽器會自動跳轉到登錄頁面:
1 from selenium import webdriver 2 3 driver = webdriver.Chrome() 4 cookies = {'value': 'think%3A%7B%22username%210293%31628193MDAwMDAwMLOGpZaIudFqhc6Gl7LQetmZtmfOk2RhbQ%22%2C%22expire%sfdaaswMDAwMDAwMLOGud6Gqb-whbiCmLOmdZ4%22%2C%22token%22%3A%22MDAwMDAwMDAwMMurrpWavLehhs1-3LLfgduEt4OWepuo123456123KZq6HQxtOK0ZCme5p-q6iZu2yrn4uNhJ3KedDYk7ivboS4it6910926YW0%22%7D', 5 'name': 'ketangpai_home_remember'} 6 7 driver.get("https://www.ketangpai.com/User/login.html") 8 driver.add_cookie(cookie_dict=cookies) 9 driver.get("https://www.ketangpai.com/Main/index.html")
再次運行,發現已經成功了
四. 獲取cookie的方法不止一種
cookie的可以通過瀏覽器調試來獲取,當然也可以通過抓包工具獲取,那么能不能用代碼來獲取呢?答案是肯定的
參照上面那篇博文,我們完成以下代碼,第一次通過driver1發送用戶名和密碼登錄,獲取cookie並保存,第二次driver2添加driver1保存的cookie,達到繞過登錄的目錄
1 from selenium import webdriver 2 import time 3 4 #driver1登錄網站,獲得cookie並保存 5 driver1 = webdriver.Chrome() 6 driver1.get("https://www.ketangpai.com/User/login.html") 7 driver1.maximize_window() 8 time.sleep(2) 9 10 #第一次通過send_keys向輸入框發送用戶名密碼登錄 11 driver1.find_element_by_xpath("//input[@name='account']").send_keys("your username") 12 driver1.find_element_by_xpath("//input[@name='pass']").send_keys("your password") 13 time.sleep(2) 14 driver1.find_element_by_xpath("//div[@class='padding-cont pt-login']//a[@class='auto-login fl']").click() 15 time.sleep(3) 16 driver1.find_element_by_xpath("//div[@class='padding-cont pt-login']//a[@class='btn-btn']").click() 17 time.sleep(6) 18 #用get_cookies的方法得到登錄后的cookie,這個cookie是個列表,列表中兩個元素都是字典,第一個是登錄前的cookie,第二個是登錄后的cookie 19 #將cookie保存在變量savedCookies中 20 savedCookies = driver1.get_cookies() 21 print(savedCookies) 22 23 #driver2得到driver1的cookie,先刪除自己的所有cookie,再將driver1的cookie添加進來 24 driver2 = webdriver.Chrome() 25 #必須首先加載網站,這樣selenium才知道cookie是屬於哪個網站的 26 driver2.get("https://www.ketangpai.com/User/login.html") 27 #一旦加載網站,即使沒登錄,也會產生一個cookie,所以這個cookie被刪除了 28 driver2.delete_all_cookies() 29 #遍歷savedCookies中的兩個元素 30 for cookie in savedCookies: 31 #k代表着add_cookie的參數cookie_dict中的鍵名,這次我們要傳入這5個鍵 32 for k in {'name', 'value', 'domain', 'path', 'expiry'}: 33 #cookie.keys()屬於'dict_keys'類,通過list將它轉化為列表 34 if k not in list(cookie.keys()): 35 #saveCookies中的第一個元素,由於記錄的是登錄前的狀態,所以它沒有'expiry'的鍵名,我們給它增加 36 if k == 'expiry': 37 t = time.time() 38 cookie[k] = int(t) #時間戳s 39 #將每一次遍歷的cookie中的這五個鍵名和鍵值添加到cookie 40 driver2.add_cookie({k: cookie[k] for k in {'name', 'value', 'domain', 'path', 'expiry'}}) 41 42 #加載我們想要看到的頁面的url 43 driver2.get("https://www.ketangpai.com/Main/index.html") 44 #再次打印driver2的cookie 45 print(driver2.get_cookies())
注意:cookie有兩種,一種是會話級別的,一種是有有效期的,會話級別的cookie就不能用add_cookie的方法了,因為一次會話過程(從打開瀏覽器到關閉瀏覽器,斷開連接)結束后它就失效了
參考文章
https://www.cnblogs.com/CoolJayson/p/7421013.html
https://www.cnblogs.com/huangguifeng/p/7858619.html
https://stackoverflow.com/questions/48562253/webdrivererror-unable-to-set-cookie-javascript