资讯详情

资讯详情

Python+Playwright实现淘宝扫码登录与Cookie持久化完整指南

做过淘宝数据采集、商品比价、订单管理这类自动化项目的朋友十有八九都会卡在登录这一环。账密登录动不动就跳滑块验证异地登录还容易触发风控甚至把账号搞到限制登录。我前后折腾过好几种方案最后固定用了“扫码登录 Cookie持久化”这套组合成本低、成功率也高配合Python写下来也就几十行核心代码。这篇博文就把完整的实现思路、防止误触发异地登录风控的注意事项、以及Cookie稳定保存和恢复的细节都捋一遍适合正在为淘宝扫码登录和Cookie失效发愁的Python开发者和数据采集入门者参考。整个方案的核心其实就一句话用真实浏览器完成扫码授权再把浏览器产生的登录Cookie导出成文件之后请求直接复用这批Cookie。这样做的好处是你拿到的Cookie和真人浏览器一致带上完整的设备指纹上下文比手动抓包复制粘贴Cookie要稳定得多也不容易因为缺失关键字段导致后续请求全部掉线。1. 为什么扫码登录是当前最稳的方案1.1 账密登录的痛点在哪里淘宝早期的接口还能用账密直接换Cookie后面风控升级之后这条路基本堵得差不多了。常规的账密登录会遇到三个问题第一滑块验证码出现的频率非常高而且验证码的轨迹检测越来越严格机器模拟的拖动轨迹很容易被识别出来第二就算是账密验证通过了平台还会针对“非常用设备”追加短信验证这一步没有人工介入根本过不去第三账密登录成功后生成的Cookie往往下发的安全属性更高很多关键Cookie带着HttpOnly标记你单纯用浏览器开发者工具复制出来的Cookie字段会不完整直接拿去用很快就会失效。1.2 扫码登录的本质是“真人授权”扫码登录在安全模型上属于扫码确认授权它的核心逻辑是手机上完成登录动作的是账号本人那么扫码端的浏览器就获得了“临时信任”的身份。这个过程中不需要手动输入密码也不会触发密码相关的验证链所以整体风控拦截率要低得多。对自动化项目来说扫码登录还有一个额外好处二维码有效期通常在一到两分钟你只需要在网络环境稳定的前提下完成一次扫码后续只要Cookie不过期就不需要反复登录。1.3 方案选型对比接口逆向与浏览器自动化的取舍我在早期也想过直接调接口模拟扫码登录也就是自己请求生成二维码接口再轮询扫码状态接口。这种做法确实很“轻”不需要启动浏览器但实际做起来有几个麻烦点淘宝的登录接口里带了签名参数比如_ksTS、token之类这些参数需要逆向整个JS文件才能模拟出来而且接口命名和参数规则会随版本更新变化你辛苦调试好的代码可能一个月之后就废了。相比之下用Playwright这类浏览器自动化框架是更现实的路径。它的核心思路是启动一个真实Chromium浏览器让用户看着浏览器窗口里的二维码完成扫码然后直接从浏览器上下文导出包含所有Cookie和LocalStorage的状态文件。整个过程不涉及逆向签名也不需要关心具体接口参数页面改版了只要选择器调整一下就行维护成本低很多。我把两种方案做了一个对比对比维度接口逆向方案浏览器自动化方案开发工作量高需要逆向JS签名低聚焦业务流程即可代码稳定性差接口变更就失效较好页面变动影响有限防风控能力弱缺少浏览器指纹强携带完整浏览器上下文环境依赖仅requests等库需要安装Chromium内核适合场景高并发生产环境有专人维护个人项目、中小规模采集任务我的建议是如果你只是给自己的脚本维护一批可用Cookie别犹豫直接选浏览器自动化方案省下逆向的时间去做更有价值的事情。2. 异地登录风控到底在检测什么2.1 风控的底层逻辑不是单一条件很多新手把“异地登录风控”简单理解成“IP地址变了就会被拦截”这其实是个误解。平台的风控系统是多个维度综合评分的IP地址只是其中一个因素。它真正的判断逻辑是通过登录设备的各项特征判断“当前这个扫码操作是否来自真人本人的常用环境”。具体来说风控系统会关注这几个维度网络特征IP归属地与历史常用登录地是否一致、IP是否为机房IP或共享出口IP、访问频率是否异常。设备特征浏览器的User-Agent、屏幕分辨率、时区、语言设置、Canvas指纹、WebGL渲染信息等。只要是自动化工具伪造出来的环境这些指纹之间就容易出现逻辑矛盾。行为特征扫码前访问了哪些页面、停留了多长时间、鼠标是否有移动轨迹、页面滚动是否符合人类习惯。账号历史账号本身的注册时间、历史登录位置数量、近期是否有风控记录。2.2 为什么你的账号容易被“误伤”实际踩坑之后我发现很多误伤是因为“浏览器指纹不完整”导致的。比如你用Requests直接请求二维码接口服务端拿到你的请求头一看没有Canvas指纹没有WebGL信息没有浏览器插件列表甚至时区格式都不对这些东西单独看没啥但组合在一起在风控系统眼里就是一个典型的“非浏览器环境”。这时候就算你是用手机扫码授权的系统也会给你一个较高的风险评分。还有一种情况是账号很久没登录了第一次在新环境扫码。这种时候风控会更敏感经常会出现“扫码成功但网页端要求二次短信验证”的情况。遇到这种提示别慌那说明账号本身触发了安全机制手动收个验证码就能放行并不是你的工具被识别了。2.3 降低风控误判的几个原则我个人的实操经验是可以总结成四个原则固定一个网络出口。不要今天用宽带IP明天用手机热点后天又挂一个别的地区的节点。对风控来说“登录IP跟上次一致”是非常重要的信任信号。复用同一个浏览器环境。每次扫码都用同一个浏览器上下文让Cookie里记录的指纹信息保持稳定。这就是为什么代码里必须设置固定的User-Agent和viewport参数而不是每次随机生成。不要频繁扫码登录。一次扫码拿到的Cookie能用一个周期就不要去刷新它。反复登录退出会让账号的风控评分逐渐升高。登录之后模拟正常访问再退出。扫码成功之后顺手访问几个首页、商品页停留十几秒再关浏览器这个操作看起来不必要但对“模拟真人环境”是有帮助的。3. Python Playwright 扫码登录完整实现3.1 环境准备与依赖安装环境准备其实很简单不需要额外装浏览器驱动Playwright会自动管理Chromium内核的下载。需要的软件有两个Python 3.8以上版本以及Playwright库。Python的安装这里就不展开讲了注意Windows下勾选“Add Python to PATH”这一步不要漏掉装好之后在命令行验证一下python --version然后安装Playwright和二维码图片解析相关的辅助库pip install playwright pillow装完库以后下载Chromium内核playwright install chromium这一步如果下载比较慢可以设置国内镜像环境变量再执行具体按你本地的网络情况来这里不多展开。下载完成后可以跑一下playwright install --list确认内核安装成功。3.2 核心代码扫码登录并保存Cookie下面这段代码是整套方案的核心我尽量写成“复制就能用”的程度。整个流程分成三步打开淘宝登录页并切换到二维码登录等待用户扫码确认确认后把浏览器上下文的Cookie保存到本地文件。import time from playwright.sync_api import sync_playwright COOKIE_FILE taobao_cookie.json UA (Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36) def save_cookie(context): context.storage_state(pathCOOKIE_FILE) print(f[] Cookie 已保存至 {COOKIE_FILE}) def wait_qrcode_confirm(page, timeout120): 等待用户扫码并在手机上确认轮询判断是否登录成功 start time.time() while time.time() - start timeout: # 登录成功后页面 URL 会跳转这里通过 URL 变化判断 if login.taobao.com not in page.url: print([] 检测到登录成功URL 已跳转:, page.url) return True time.sleep(2) print([!] 等待扫码超时) return False def main(): with sync_playwright() as p: browser p.chromium.launch(headlessFalse) context browser.new_context( user_agentUA, viewport{width: 1280, height: 800}, localezh-CN, timezone_idAsia/Shanghai, device_scale_factor1.0, ) page context.new_page() page.goto(https://login.taobao.com/, wait_untildomcontentloaded) page.wait_for_timeout(3000) # 优先尝试点击“扫码登录”不同时期页面结构可能有差异 try: qr_tab page.locator(text扫码登录) if qr_tab.count() 0: qr_tab.first.click() print([*] 已切换到扫码登录) page.wait_for_timeout(2000) except Exception as e: print([*] 未找到扫码切换按钮默认显示二维码:, e) # 截图保存二维码方便手机扫码 page.screenshot(pathqrcode.png) print([*] 二维码已截图保存为 qrcode.png请打开淘宝 App 扫码) if wait_qrcode_confirm(page): # 登录成功后稍等几秒让页面完成跳转和状态更新 page.wait_for_timeout(5000) save_cookie(context) browser.close() if __name__ __main__: main()这段代码里有两个地方值得说明一下二维码截图是为了照顾“浏览器窗口不在眼前”的情况。如果你在远程服务器上跑没有显示器可以考虑把headless改成True但是注意无头模式下很多登录页会把二维码识别为异常环境所以我个人的建议是本地有显示器的时候用有头模式扫码扫完以后再把headlessTrue用于后续的静默访问。一张“本地扫码 服务器复现”的组合拳兼顾了便捷性和稳定性。3.3 恢复Cookie并验证有效性拿到Cookie文件之后后续脚本不需要再打开有头浏览器。你可以直接用storage_state加载之前的登录状态静默访问淘宝页面。这一步的关键是要验证Cookie是否有效因为Cookie有有效期过期之后必须重新扫码。from playwright.sync_api import sync_playwright COOKIE_FILE taobao_cookie.json def check_and_visit(): with sync_playwright() as p: browser p.chromium.launch(headlessTrue) context browser.new_context(storage_stateCOOKIE_FILE) page context.new_page() page.goto(https://www.taobao.com/, wait_untildomcontentloaded) page.wait_for_timeout(3000) # 判断是否登录成功的两个方向页面是否有用户名或是否跳转登录页 if login.taobao.com in page.url: print([-] Cookie 已失效请重新扫码登录) else: # 尝试找到表示登录状态的昵称节点 nick page.locator(.site-nav-login-info-nick) if nick.count() 0: print([] 登录有效当前用户:, nick.first.inner_text()) else: print([?] 未检测到明显的登录标识可能需要进一步确认) page.screenshot(pathcheck_result.png) browser.close() if __name__ __main__: check_and_visit()这段代码里的选择器.site-nav-login-info-nick是淘宝首页展示用户昵称的常见节点但页面改版后不一定百分百匹配。你可以根据实际情况调整也可以用“页面是否跳转到login.taobao.com”这个条件来判断。我自己更倾向于两个判断条件都写哪个命中都算有效避免单点判断失误。3.4 用Requests复用Cookie的姿势Cookie文件拿到之后很多人会想在纯Requests脚本里复用不发起浏览器进程。这样做是可行的Playwright导出的Cookie文件是JSON数组每条记录包含name、value、domain、path、expires、httpOnly、secure等字段。你只需要在Requests的Session里把这些字段转成标准Cookie即可。import json import requests with open(taobao_cookie.json, r, encodingutf-8) as f: data json.load(f) session requests.Session() for item in data.get(cookies, []): session.cookies.set( item[name], item[value], domainitem.get(domain, ), pathitem.get(path, /), ) # 设置必要的请求头 session.headers.update({ User-Agent: (Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36), Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9, }) # 测试访问 resp session.get(https://www.taobao.com/) print(响应状态码:, resp.status_code)需要注意Requests的Session和浏览器行为还是有差别的。如果页面要求JS渲染才能拿到数据你依然要依赖Playwright来执行页面脚本。Requests方案更适合调用那些直接返回JSON的公开接口。另外浏览器里有些Cookie是HttpOnly的你通过开发者工具手动复制是拿不到的但Playwright导出的JSON里包含这些字段所以这个方案在Cookie完整性上是有天然优势的。4. Cookie稳定性与常见问题排查4.1 为什么Cookie还是经常失效这个问题我在各种技术群里被问过太多次了。排除账号本身被限制的情况Cookie失效通常有以下几个原因失效原因具体表现解决方法Cookie过期访问页面跳转登录定期检查有效性过期前重新扫码关键字段缺失接口返回权限错误用Playwright导出完整Cookie不要手动复制IP频繁变动首次访问正常随后被踢下线固定出口IP避免跨地区切换浏览器指纹异常登录状态在服务端被标记复用同一套UA和viewport参数访问频率过高触发限流后返回验证控制请求频率模拟正常访问间隔4.2 高版本Chrome无法携带Cookie是怎么回事你说自己用浏览器开发者工具复制了Cookie到Requests里结果发现没过多久就失效了网上还有人说什么“Chrome高版本不能携带Cookie”。这个说法的背后其实有两个原因一个是Chrome从80版本开始把未设置SameSite属性的Cookie默认当成Lax处理导致第三方上下文中Cookie携带受限另一个原因是开发者工具复制出来的Cookie可能缺少HttpOnly或Secure字段或者你复制的时候不小心漏掉了某个重要的认证字段。这个问题在我们这个方案里实际上不存在因为Playwright导出的storage_state是浏览器内置状态所有Cookie字段都会完整保留。如果你坚持要手动复制Cookie注意查看“应用”面板里面每个Cookie的Domain、Path、Expires这几列不要只看Name和Value。4.3 提升Cookie复用稳定性的几个技巧我自己的项目里还会做这么几件事让Cookie的复用更加稳定保存Cookie的时候顺带保存一份“登录时间戳”和“UA指纹”。下次加载Cookie时先检查时间如果距离上次登录超过一定天数就直接提示重新扫码。不要让多个IP同时用同一份Cookie。如果同一份Cookie在很短的时间内从两个不同的IP登录风控会认为Cookie被泄露了大概率直接作废。每次扫码成功后等待页面完整加载完再关浏览器。页面里可能还有后续的埋点请求提前关掉容易让服务端认为“登录状态丢失”。4.4 真到了要排查的时候从哪几处入手如果Cookie还是失效了不要上来就怀疑是自己的代码问题。我建议的排查顺序是先用Playwright加载Cookie打开淘宝首页看是否跳转登录页如果不跳转说明Cookie在浏览器层面有效问题出在后续请求上如果跳转了说明Cookie本身已经失效需要重新扫码。如果Cookie浏览器有效但Requests无效那几乎可以确定是请求头不完整或者IP不一致导致的。关于异地登录风控我最后的建议是不要频繁换网络环境去测试尤其是同一个账号在大范围跨地区切换登录。这就像你在北京登录一次半个小时后IP出现在广州系统不拦你拦谁保持稳定是自动化项目账号安全的第一原则。我自己的经验是固定一个网络出口固定一套浏览器指纹一次登录之后用上十天半个月基本不会出问题。做好Cookie管理比反复研究逆向签名有意义得多。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →