無頭模式(headless)是selenium的webdriver瀏覽器驅(qū)動的一項功能,允許瀏覽器不出現(xiàn)而仍可訪問網(wǎng)頁,并與之交互,這對于運行自動化測試或網(wǎng)絡(luò)抓包大有用處,因為運行速度更快、占用資源更少。
但是筆者發(fā)現(xiàn)在無頭模式下運行時,瀏覽器訪問某些網(wǎng)站產(chǎn)生的cookies內(nèi)容可能與在正常模式(非無頭模式)下略有不同。因為某些網(wǎng)站使用技術(shù)來檢測是否被無頭瀏覽器訪問,并可能通過設(shè)定不同的 cookie 或以其他方式表現(xiàn)不同來做出響應(yīng)。
為了說明這種差異,我們可以使用 Python 中的 Selenium WebDriver 庫運行一個簡單的實驗。 首先,我們將創(chuàng)建兩個 Chrome 瀏覽器實例——一個在無頭模式下,另一個在正常模式下:
from time import sleep
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# 初始化無頭模式(headless)的webdriver
options = Options()
options.add_argument('--headless')
driver_headless = webdriver.Chrome(options=options)
# 設(shè)置window.navigator.webdriver為false
driver_headless.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => False}) "})
# 打開一個網(wǎng)站,輸出cookies
driver_headless.get('http://。。。。。。')
sleep(3)
cookies_headless = driver_headless.get_cookies()
keys_headless = set([cookie['name'] for cookie in cookies_headless])
driver_headless.quit()
# 初始化正常模式的webdriver
options2 = Options()
# 取消chrome受自動控制提示
options2.add_experimental_option('useAutomationExtension', False)
options2.add_experimental_option('excludeSwitches', ['enable-automation'])
driver_normal = webdriver.Chrome(options=options2)
# 設(shè)置window.navigator.webdriver為false
driver_normal.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => False}) "})
# 打開同一個網(wǎng)站,輸出cookies
driver_normal.get('http://。。。。。。')
sleep(3)
cookies_normal = driver_normal.get_cookies()
keys_normal = set([cookie['name'] for cookie in cookies_normal])
driver_normal.quit()
# 兩相比較
keys_only_in_headless = keys_headless - keys_normal
keys_only_in_normal = keys_normal - keys_headless
if keys_only_in_headless:
print(f'無頭模式(headless)多出來的Cookie名稱是: {keys_only_in_headless}')
if keys_only_in_normal:
print(f'正常模式多出來的Cookie名稱是: {keys_only_in_normal}')
if not keys_only_in_headless and not keys_only_in_normal:
print('無頭模式和正常模式的cookies都一樣。')
運行結(jié)果截圖:
我測試了分別采用無頭模式和正常模式訪問同一個網(wǎng)站的鏈接,得出的cookies不一樣。無頭模式情況下的cookies比正常模式缺失兩項內(nèi)容:AlteonP、JSessionID。
我后續(xù)的操作是需要把selenium的cookies內(nèi)容導(dǎo)出至requests庫的session使用,若使用無頭模式下的cookie,再用requests庫的get、post訪問該網(wǎng)站時都報錯(status_code會出現(xiàn)400、403、412等非正常代碼)。
眾所周知requests庫的get、post訪問一個網(wǎng)站鏈接獲取得到的cookies內(nèi)容本來就稀缺,只有selenium的webdriver打開網(wǎng)站才能得到豐富的cookies,因此要從selenium的cookies導(dǎo)出cookies給requests庫使用是非常有必要的。要讓selenium的無頭模式也能獲取正常模式的cookies,下面是我的兩個解決思路:
1、添加user-agent
在options那幾行里插入下面兩行代碼:
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'
options.add_argument(f'user-agent={user_agent}')
也許大家和我一樣都覺得Selenium的webdriver已經(jīng)自動附帶user-agent而不需要重復(fù)添加。但意想不到的是,無頭模式訪問某些網(wǎng)站,網(wǎng)站仍會檢測到selenium是在做爬蟲動作,故給出的cookies內(nèi)容少之又少,跟requests的get獲取的cookies相差無幾。所以在嘗試手動添加user-agent后,無頭模式獲取的cookies內(nèi)容變得豐富起來,這個辦法看似老土,但非常管用。
2、設(shè)置瀏覽器窗口大小
如果第一個解決方法行不通,可試試設(shè)置瀏覽器窗口大小,盡管無頭模式下瀏覽器是無形的,但也許通過設(shè)置窗口大小可以瞞過某些網(wǎng)站的檢測。文章來源:http://www.zghlxwxcb.cn/news/detail-401899.html
options.add_argument("--window-size=1920,1050")
接下來就可以導(dǎo)出Selenium的cookies給requests使用了。文章來源地址http://www.zghlxwxcb.cn/news/detail-401899.html
from requests.cookies import RequestsCookieJar
cookies = driver.get_cookies()
jar = RequestsCookieJar()
for cookie in cookies:
jar.set(cookie['name'], cookie['value'])
se = requests.Session()
se.cookies = jar
se.headers.update({'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36'})
res = se.get('http://。。。。。。', headers=headers)
assert res.status_code==200
res.encoding = 'utf-8'
print(res.text)
到了這里,關(guān)于Selenium webdriver的無頭模式(headless)可能導(dǎo)致cookies內(nèi)容缺失,以及解決措施的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!