Selenium操作Chrome136复制配置文件解密失败,无法复用登录会话
问题背景与当前困境
我用Python+Selenium 4.25.0自动化操作Chrome 136,想复用已登录的Chrome默认配置文件访问https://aistudio.google.com。之前遇到Selenium启动Chrome后加载了配置文件,但调用driver.get()无法离开chrome://newtab/页面,按照@Ajeet Verma的建议尝试了复制配置文件的方法:
- 完全关闭所有Chrome进程;
- 创建新目录
C:\SeleniumChromeProfiles\MyAutomationProfile; - 将原配置文件
%LOCALAPPDATA%\Google\Chrome\User Data\Default完整复制到新目录下的Default子文件夹; - 脚本中只添加
chrome_options.add_argument(f"--user-data-dir=C:\\SeleniumChromeProfiles\\MyAutomationProfile"),省略--profile-directory=Default参数。
现在的问题:Chrome启动后能识别复制的配置(比如自定义新标签页),但控制台输出大量解密错误:
[<PID>:<TID>:MMDD/HHMMSS.XXX:ERROR:components\os_crypt\sync\os_crypt_win.cc:105] Failed to decrypt: 鞈?銝迤蝣箝?(0xD)
关键是Google AI Studio的登录会话没保留,访问目标网站仍需重新登录,说明配置里的敏感数据(认证Cookie、令牌)无法被Selenium启动的Chrome实例解密,没法复用已有会话。
环境信息
- 操作系统:Windows 11 Pro 23H2
- Python版本:3.12.x
- Selenium版本:4.25.0
- Chrome版本:136.0.7103.93(64位官方版)
- ChromeDriver版本:136.0.7103.xx(win64)
简化启动代码
import time import os from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import WebDriverException # --- Configuration --- CHROME_DRIVER_PATH = r'C:\Users\stat\Downloads\chromedriver-win64\chromedriver-win64\chromedriver.exe' # My actual path # Path to the PARENT of the COPIED "Default" profile CHROME_COPIED_PROFILE_PARENT_DIR = r'C:\SeleniumChromeProfiles\MyAutomationProfile' # Example - I created this and xcopied ...\User Data\Default into ...\MyAutomationProfile\Default TARGET_URL = "https://aistudio.google.com/prompts/new_chat" def setup_driver(): print(f"Driver Path: {CHROME_DRIVER_PATH}") print(f"User Data Dir (for copied profile): {CHROME_COPIED_PROFILE_PARENT_DIR}") if not os.path.exists(CHROME_DRIVER_PATH): print(f"FATAL: ChromeDriver not found: '{CHROME_DRIVER_PATH}'.") return None if not os.path.isdir(CHROME_COPIED_PROFILE_PARENT_DIR): print(f"FATAL: Copied profile parent dir not found: '{CHROME_COPIED_PROFILE_PARENT_DIR}'.") return None if not os.path.isdir(os.path.join(CHROME_COPIED_PROFILE_PARENT_DIR, "Default")): print(f"FATAL: 'Default' subfolder NOT found inside '{CHROME_COPIED_PROFILE_PARENT_DIR}'. Profile copy likely incorrect.") return None chrome_options = Options() # Key part for copied profile method: point to the new parent directory chrome_options.add_argument(f"--user-data-dir={CHROME_COPIED_PROFILE_PARENT_DIR}") # DO NOT use --profile-directory, Chrome will look for "Default" inside the user-data-dir chrome_options.add_experimental_option("excludeSwitches", ["enable-automation", "load-extension"]) chrome_options.add_experimental_option('useAutomationExtension', False) prefs = { "credentials_enable_service": False, "profile.password_manager_enabled": False } chrome_options.add_experimental_option("prefs", prefs) chrome_options.add_argument("--disable-extensions") chrome_options.add_argument("--start-maximized") try: service = Service(executable_path=CHROME_DRIVER_PATH) driver = webdriver.Chrome(service=service, options=chrome_options) print("WebDriver initialized with copied profile settings.") return driver except WebDriverException as e: print(f"FATAL WebDriverException during setup: {e}") return None except Exception as e_setup: print(f"Unexpected FATAL error during setup: {e_setup}") return None def main(): print("IMPORTANT: Ensure ALL Google Chrome instances are FULLY CLOSED before running this script.") input("Press Enter to confirm and continue...") driver = setup_driver() if not driver: print("Driver setup failed. Exiting.") return try: print(f"Browser launched. Waiting a moment...") print(f"Initial URL: '{driver.current_url}', Initial Title: '{driver.title}'") time.sleep(4) print(f"Attempting to navigate to: {TARGET_URL}") driver.get(TARGET_URL) print(f"Called driver.get(). Waiting for navigation...") time.sleep(7) # Allow time for navigation / login redirect current_url_after_get = driver.current_url print(f"After 7s wait - Current URL: '{current_url_after_get}', Title: '{driver.title}'") if "accounts.google.com" in current_url_after_get: print("RESULT: Navigated to a Google login/account page. Copied session was not active/decrypted.") elif TARGET_URL in current_url_after_get: print("RESULT: Potentially successful navigation to AI Studio (but still check if login is required on page).") else: print(f"RESULT: Navigation FAILED. Browser is on '{current_url_after_get}'.") except Exception as e: print(f"An error occurred: {e}") finally: print("Script finished or errored.") input("Browser will remain open. Press Enter to close...") if driver: driver.quit() if __name__ == "__main__": if not os.path.exists(CHROME_COPIED_PROFILE_PARENT_DIR) or \ not os.path.isdir(os.path.join(CHROME_COPIED_PROFILE_PARENT_DIR, "Default")): print("ERROR: The copied profile directory setup seems incorrect.") print(f"Ensure '{CHROME_COPIED_PROFILE_PARENT_DIR}' exists AND contains a 'Default' subfolder with your copied profile data.") else: main()
核心疑问
- 能否在Windows上让该“复制配置文件”方案生效,使加密会话数据成功解密并复用,避免手动重新登录?(比如特定Chrome参数或调整Windows DPAPI交互?)
- 若出于安全原因,复制配置文件直接解密对Google账户不可行,除了编写复杂的含2FA的登录流程外,还有哪些可靠的无人值守Selenium自动化方案可实现持久Google登录?
- 持续出现的“解密失败”错误,即便后续处理了登录页面,是否会导致Selenium控制的浏览器会话存在潜在不稳定或不可靠问题?
希望在遵循Chrome自动化安全机制的前提下,避免手动编写登录流程,找到更直接的配置文件复用方式。
解答
1. 复制配置文件方案的修复可能性
在Windows上,Chrome用**DPAPI(数据保护API)**加密敏感数据(Cookie、令牌等),加密密钥和当前用户的上下文、进程权限绑定。直接复制配置文件后,Selenium启动的Chrome进程无法获取原进程的解密权限,导致解密失败。可以尝试以下操作:
- 直接使用原配置目录,不复制:关闭所有Chrome进程后,脚本中直接指定原
User Data目录作为--user-data-dir,不要复制。示例:
注意:必须确保没有其他Chrome实例在运行,否则会触发配置文件锁定,导致Selenium启动失败。chrome_options.add_argument(r"--user-data-dir=C:\Users\stat\AppData\Local\Google\Chrome\User Data") - 确保脚本以原用户身份运行:Python脚本和Selenium进程必须用登录Chrome的Windows用户身份启动,不要用管理员或其他用户身份,否则DPAPI解密会失败。
复制配置文件的方式本身会破坏DPAPI的加密上下文,这是问题根源,改用原配置目录是最直接的解决办法。
2. 替代的持久登录方案
如果复制/直接使用原配置文件不可行,可以考虑以下方案:
- 使用Chrome远程调试端口:手动打开Chrome并登录到Google AI Studio,启动时加上
--remote-debugging-port=9222参数,Selenium通过连接该端口控制已登录的浏览器实例。示例代码:
无人值守场景下,可将Chrome启动命令加入系统启动项,自动打开并保持登录(需开启浏览器密码记忆、关闭系统锁屏)。chrome_options = Options() chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222") driver = webdriver.Chrome(service=service, options=chrome_options) - 导出并导入Cookie:手动登录后,用Chrome开发者工具导出Google相关网站的Cookie(包括
.google.com、aistudio.google.com)保存为JSON文件,Selenium启动后遍历添加Cookie。示例代码:
需确保导出的Cookie包含核心认证令牌(如import json # 假设cookie.json是导出的Cookie文件 with open('cookie.json', 'r') as f: cookies = json.load(f) for cookie in cookies: driver.add_cookie(cookie) driver.refresh()__Secure-1PSID、__Secure-3PSID),且定期更新过期的Cookie。 - 使用专用子配置文件:在原
User Data目录下创建新配置文件(如Profile 1),手动登录一次Google AI Studio,脚本中指定该子配置:
这种方式既复用登录会话,又不会干扰日常使用的默认配置,同样需确保无其他Chrome实例占用该子配置。chrome_options.add_argument(r"--user-data-dir=C:\Users\stat\AppData\Local\Google\Chrome\User Data") chrome_options.add_argument("--profile-directory=Profile 1")
3. 解密失败错误的影响
持续的解密失败错误主要影响加密敏感数据的加载(Cookie、密码等),但不会直接导致浏览器会话不稳定:
- 浏览器会忽略解密失败的数据,继续正常运行,只是这些数据无法使用;
- 后续手动登录后,新的会话数据会用当前Selenium进程的DPAPI上下文加密,不会再出现解密错误;
- 大量错误日志仅会占用少量磁盘空间,不会引发崩溃或功能异常,只要脚本不依赖这些解密失败的数据,会话即可正常使用。
内容的提问来源于stack exchange,提问作者STATTHINGY TRENTON
相关产品推荐
相关产品推荐

