Selenium webdriver的无头模式(headless)可能导致cookies内容缺失,以及解决措施

无头模式(headless)是selenium的webdriver浏览器驱动的一项功能,允许浏览器不出现而仍可访问网页,并与之交互,这对于运行自动化测试或网络抓包大有用处,因为运行速度更快、占用资源更少。

但是笔者发现在无头模式下运行时,浏览器访问某些网站产生的cookies内容可能与在正常模式(非无头模式)下略有不同。因为某些网站使用技术来检测是否被无头浏览器访问,并可能通过设定不同的 cookie 或以其他方式表现不同来做出响应。

为了说明这种差异,我们可以使用 Python 中的 Selenium WebDriver 库运行一个简单的实验。 首先,我们将创建两个 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)
# 设置window.navigator.webdriver为false
driver_headless.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => False}) "})
# 打开一个网站,输出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)
# 设置window.navigator.webdriver为false
driver_normal.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, 'webdriver', {get: () => False}) "})
# 打开同一个网站,输出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都一样。')

运行结果截图:

我测试了分别采用无头模式和正常模式访问同一个网站的链接,得出的cookies不一样。无头模式情况下的cookies比正常模式缺失两项内容:AlteonP、JSessionID。

我后续的操作是需要把selenium的cookies内容导出至requests库的session使用,若使用无头模式下的cookie,再用requests库的get、post访问该网站时都报错(status_code会出现400、403、412等非正常代码)。

众所周知requests库的get、post访问一个网站链接获取得到的cookies内容本来就稀缺,只有selenium的webdriver打开网站才能得到丰富的cookies,因此要从selenium的cookies导出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已经自动附带user-agent而不需要重复添加。但意想不到的是,无头模式访问某些网站,网站仍会检测到selenium是在做爬虫动作,故给出的cookies内容少之又少,跟requests的get获取的cookies相差无几。所以在尝试手动添加user-agent后,无头模式获取的cookies内容变得丰富起来,这个办法看似老土,但非常管用。

2、设置浏览器窗口大小

如果第一个解决方法行不通,可试试设置浏览器窗口大小,尽管无头模式下浏览器是无形的,但也许通过设置窗口大小可以瞒过某些网站的检测。

options.add_argument("--window-size=1920,1050") 

接下来就可以导出Selenium的cookies给requests使用了。

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)

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然可以。下面是一个使用SeleniumChrome浏览器实现的简便的百度网盘免Cookies的函数: ```python from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.options import Options import time def baidu_pan_login(username, password): # 创建Chrome浏览器 options = Options() options.add_argument('--headless') # 设置为无头模式,不显示浏览器界面 driver = webdriver.Chrome(options=options) # 访问百度网盘登录页面 login_url = 'https://pan.baidu.com/' driver.get(login_url) # 输入用户名和密码,点击登录按钮 username_input = driver.find_element_by_id('TANGRAM__PSP_4__userName') password_input = driver.find_element_by_id('TANGRAM__PSP_4__password') submit_button = driver.find_element_by_id('TANGRAM__PSP_4__submit') username_input.send_keys(username) password_input.send_keys(password) submit_button.click() # 等待登录成功并获取BDUSS time.sleep(5) # 等待5秒,等待登录成功 bduss = driver.execute_script('return document.cookie.match(/BDUSS=([^;]+)/) && RegExp.$1') # 获取BDUSS driver.quit() # 关闭浏览器 return bduss ``` 该函数的思路是使用SeleniumChrome浏览器自动化地模拟用户在网页上的操作,包括输入用户名和密码,点击登录按钮等。然后等待登录成功,使用JavaScript代码获取BDUSS,并关闭浏览器。需要注意的是,该函数需要安装SeleniumChrome浏览器,并设置Chrome浏览器的驱动程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值