Python Selenium爬取需身份认证站点时如何存储登录会话
问题原因及修复方案
代码存在的核心问题
- 多余的Cookie操作覆盖原有有效会话:你使用的是同一个Firefox驱动实例,登录完成后会话Cookie会自动保存在驱动的会话存储中,不需要手动调用
get_cookies再add_cookie,该操作可能导致有效Cookie被覆盖、属性异常,反而破坏登录态。 - 未等待登录流程完全落地就获取Cookie:输入验证码按下回车后,站点需要完成后端校验、返回会话Cookie、跳转登录后页面的流程,你立即执行Cookie读取操作时,核心会话Cookie还未写入浏览器存储,拿到的Cookie不包含有效身份凭证。
- XPath表达式存在语法隐患:你编写的class匹配规则错误使用了HTML转义符
",Python字符串中单引号包裹的内容可直接使用双引号,不需要转义,该问题可能导致验证元素匹配失败,登录流程未完整执行。 - (跨驱动复用Cookie场景特有问题)添加Cookie前未访问对应域名:如果你后续要实现重启驱动复用Cookie的功能,Selenium要求添加Cookie前,驱动必须先访问过Cookie所属域名的任意页面,否则会因为域名校验不通过添加失败。
修复代码示例
同驱动直接访问登录后页面(最简修复)
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver import Firefox driver = Firefox() def logon(drvr): drvr.get('https://www.site/to/scrape/logon') wait = WebDriverWait(drvr, 10) elem = wait.until(EC.presence_of_element_located((By.NAME, 'memberId'))) elem.send_keys('xxxx', Keys.RETURN) elem = wait.until(EC.presence_of_element_located((By.NAME, 'password'))) elem.send_keys('xxxx', Keys.RETURN) # 修复XPath引号问题 elem = wait.until(EC.presence_of_element_located((By.XPATH, '//a[@class="sub-label font-narrow"]'))) ver = elem.get_attribute('aria-label') if ' '.join(ver.split()) == 'phone number ending in 1 3 6 1': elem.click() value = input('Enter security code: ') elem = wait.until(EC.presence_of_element_located((By.NAME, 'inputValue'))) elem.send_keys(value, Keys.RETURN) # 新增:等待登录完成,确认会话Cookie生效 # 替换为你登录成功后跳转的URL特征,或者等待登录后才存在的页面元素 wait.until(EC.url_contains('site.com/home')) def main(drvr): # 移除多余的Cookie操作,直接访问受保护页面 drvr.get('https://www.site/behind/logon') print(drvr.page_source[:1000]) logon(driver) main(driver)
跨驱动持久化复用登录态(可选方案)
如果需要重启浏览器仍保留登录状态,可使用如下方案序列化存储Cookie:
import json import time # 登录完成后保存Cookie到本地 def save_cookies(drvr, path='site_cookies.json'): with open(path, 'w', encoding='utf-8') as f: json.dump(drvr.get_cookies(), f, ensure_ascii=False, indent=2) # 新启动驱动后加载本地Cookie def load_cookies(drvr, path='site_cookies.json', target_domain_root='https://www.site/'): # 必须先访问目标站点任意页面,才能添加对应域名的Cookie drvr.get(target_domain_root + '404') with open(path, 'r', encoding='utf-8') as f: cookies = json.load(f) for cookie in cookies: # 过滤过期Cookie if 'expiry' in cookie and cookie['expiry'] < time.time(): continue drvr.add_cookie(cookie) # 添加完成后再访问受保护页面 drvr.get('https://www.site/behind/logon')
非Cookie存储会话的排查方案
如果确认Cookie正确仍无法登录,可按以下顺序排查其他会话存储方式:
- 排查LocalStorage/SessionStorage:打开浏览器F12控制台「应用」标签,查看对应域名下的Local Storage、Session Storage内容,多数单页应用会将JWT身份令牌、会话标识存在此处。Selenium可通过执行JS读写存储内容:
drvr.execute_script('return window.localStorage.getItem("token_key")')、drvr.execute_script('window.localStorage.setItem("key", "value")')。 - 排查自定义请求头:在F12「网络」标签对比登录前后访问受保护页面的请求头差异,部分站点会使用
X-Auth-Token、Authorization等自定义头传递身份凭证,可通过Selenium的请求拦截功能添加对应头字段。 - 排查设备指纹绑定:部分站点会将会话和浏览器User-Agent、屏幕分辨率、WebGL指纹等设备特征绑定,重启驱动时需保持启动参数、浏览器属性和登录时完全一致。
- 排查Cookie属性限制:检查Cookie的
Secure、SameSite、HttpOnly属性,确保访问协议、域名和Cookie要求的规则匹配,例如Secure标识的Cookie只能在HTTPS协议下传递。
内容的提问来源于stack exchange,提问作者malonn
相关产品推荐
相关产品推荐

