使用Python+Selenium从localStorage获取access token失败问题排查
解决Selenium无法获取localStorage中persist:root数据的问题
下面是针对该问题的具体解决步骤:
1. 确认同源性,确保操作正确页面
localStorage遵循同源策略,只有Selenium当前控制的页面域名与存储persist:root的域名完全一致时,才能读取到数据:
- 登录成功后手动查看浏览器地址栏的最终URL,对比代码中
EC.url_contains(DOMAIN)的DOMAIN值,确保两者完全匹配(包括协议、域名、端口)。 - 如果登录后存在多次跳转,需等待最终目标页面加载完成后,再尝试读取localStorage。
2. 优化等待逻辑,确保数据有效写入
原代码的等待逻辑无法准确判断数据是否有效,建议替换为更严谨的等待脚本:
WebDriverWait(driver, 30).until( lambda d: d.execute_script(""" const item = localStorage.getItem('persist:root'); if (!item) return false; try { const parsedRoot = JSON.parse(item); const parsedAuth = JSON.parse(parsedRoot.auth); return !!parsedAuth.access_token; } catch(e) { return false; } """) )
该脚本会等待persist:root存在、可解析,且其中的auth字段包含有效的access_token,避免提前执行后续代码。
3. 修正数据解析逻辑
原代码错误地将localStorage返回的JSON字符串当作字典直接调用.get()方法,这是核心问题。正确解析步骤如下:
# 获取localStorage中的字符串 persisted_state = driver.execute_script("return localStorage.getItem('persist:root')") # 第一步:解析整个persist:root为字典 persisted_state_dict = json.loads(persisted_state) # 第二步:取出auth字段的字符串(redux-persist会把每个state字段序列化为字符串) auth_state_str = persisted_state_dict.get('auth', '{}') # 第三步:解析auth字符串为字典 auth_state_json = json.loads(auth_state_str) # 提取access_token access_token = auth_state_json.get('access_token')
建议添加异常捕获,避免解析失败导致程序崩溃:
try: persisted_state_dict = json.loads(persisted_state) except json.JSONDecodeError: raise Exception("persist:root格式不是有效的JSON") try: auth_state_json = json.loads(auth_state_str) except json.JSONDecodeError: raise Exception("auth字段格式不是有效的JSON")
4. 调试技巧:查看浏览器控制台输出
运行代码时不要自动关闭浏览器,手动打开开发者工具(F12)查看Console标签,原代码中的console.log('Item retrieved:', item)会打印浏览器端获取到的内容:
- 如果控制台能看到数据,但Selenium返回None,大概率是同源性问题;
- 如果控制台也没有数据,说明页面还未完成redux状态持久化,需调整等待逻辑。
修正后的核心代码片段
# 等待有效数据写入localStorage WebDriverWait(driver, 30).until( lambda d: d.execute_script(""" const item = localStorage.getItem('persist:root'); if (!item) return false; try { const parsedRoot = JSON.parse(item); const parsedAuth = JSON.parse(parsedRoot.auth); return !!parsedAuth.access_token; } catch(e) { return false; } """) ) # 获取并解析数据 persisted_state = driver.execute_script("return localStorage.getItem('persist:root')") if not persisted_state: raise Exception("Failed to retrieve persisted state from localStorage") try: persisted_state_dict = json.loads(persisted_state) except json.JSONDecodeError: raise Exception("Invalid JSON format for persist:root") auth_state_str = persisted_state_dict.get('auth', '{}') try: auth_state_json = json.loads(auth_state_str) except json.JSONDecodeError: raise Exception("Invalid JSON format for auth state") access_token = auth_state_json.get('access_token') if not access_token: raise Exception("Access token not found in auth state") # 保存到文件 with open('redux-persist.json', 'w') as file: json.dump({'accessToken': access_token}, file) return access_token
内容的提问来源于stack exchange,提问作者Cường Trần Văn
相关产品推荐
相关产品推荐

