EZR 数据源导出(通用型)
30 秒上手(TL;DR)
- 装依赖:
pip install pycryptodome requests - 拿 session:浏览器 F12 → Application → Cookies →
crm-tp.ezrpro.com复制整串,存到本地文件,设EZR_COOKIE_FILE=<该文件>(不要硬编码进脚本) - 干跑看计划(不连网):
python scripts/ezr_export.py --dry-run --date 2026-07-20 - 真实导出:
python scripts/ezr_export.py --date 2026-07-20 --out ./out - 定时免登录:用
ezr_auto_refresh.py替代ezr_export.py(需 Chrome 开--remote-debugging-port=9222且已登录 EZR),遇 900 自动刷新
想看原理 / 踩坑点 / 多 AI 并发安全,往下读「概述 / 核心难点 / 常见报错 FAQ」。
概述
提供从任意 EZR(驿氪)租户导出数据源文件的端到端能力:认证 → 触发导出 → 轮询任务 → 下载/解压。平台级逻辑(认证、轮询、下载)与具体业务无关;租户参数与数据源清单可配置。比音勒芬 8 源作为内置示例,真实客户只需提供一份 sources JSON 即可复用。
何时使用
- 用户要"导出 EZR 数据 / 拉取驿氪报表 / 做比音勒芬数据日报的数据源"。
- 需要把 EZR 后台的某类数据定期固化下来(可结合
when-to-create-skill判断是否值得做成定时 skill)。 - 跨客户复用:换
--brand-id/--user-id,或提供自定义--sources配置。
使用方法
- 安装依赖:
pip install pycryptodome requests - 获取 session(二选一,不要硬编码):
- 完整 cookie:设环境变量
EZR_COOKIE_FILE=<cookie文件路径>(浏览器 F12 → Application → Cookies → crm-tp.ezrpro.com 复制整串存入文件) - 仅 pcl_sid:设
EZR_SESSION=<pcl_sid值>
- 完整 cookie:设环境变量
🔒 凭据安全(务必遵守):cookie /
pcl_sid只存于本地文件(EZR_COOKIE_FILE)或环境变量,绝不写入代码、也绝不提交到仓库。ezr_auto_refresh.py经 CDP 读取的 cookie 也只落地到本地文件,并用原子写 + 写锁防止并发竞态与泄露。请勿把 cookie 粘进脚本或 commit。
- 干跑验证计划(不连网):
python scripts/ezr_export.py --dry-run --start 2026-07-17 --end 2026-07-19 - 真实导出:
python scripts/ezr_export.py --start 2026-07-17 --end 2026-07-19 --out <输出目录>python scripts/ezr_export.py --date 2026-07-20(按汇报日自动推算数据范围) - 换租户 / 自定义:
python scripts/ezr_export.py --user-id <uid> --brand-id <bid> --sources my_sources.json ...
⭐ session 自动刷新(定时任务免人工复制 Cookie)
scripts/ezr_auto_refresh.py 是 ezr_export.py 的包装器:当 EZR 返回 ErrorMsg=900(session 过期)时,自动通过 Chrome CDP 从已登录的 Chrome 读取最新 pcl_sid(含 HttpOnly)写入 cookie 文件并重试,无需人工干预。配套 scripts/cdp_get_ezr_cookie.mjs(Node 22+)。
前置(一次性):Chrome 已登录 EZR,且开启远程调试(chrome://inspect/#remote-debugging 勾 Allow,或快捷方式加 --remote-debugging-port=9222)。
用法(参数同 ezr_export.py,附加 --force-refresh / --no-refresh / --cookie-file / --cdp-port):
python scripts/ezr_auto_refresh.py --date 2026-07-20 --out <输出目录>
- 遇 900 → 自动 CDP 刷新 → 重试一次;重试仍失败则退出码非 0 并提示原因。
- 会话过期判定(结构化信号):
ezr_export.py在捕获EZRSessionExpired(ErrorMsg=900)时,会在输出中单独打印一行唯一标记EZR_SESSION_EXPIRED;包装器ezr_auto_refresh.py仅匹配该标记即可精准命中,不再依赖脆弱的中文串组合匹配(旧逻辑"900" in out and "session" in out.lower()易被其它上下文误触发)。文案/语言改动不会影响自动刷新。
⭐ 通用性:数据源目录与发现流程(本 skill 是"通用"的关键)
本 skill 的导出机制与业务无关(认证/触发/轮询/下载全通用),但"EZR 里有哪些数据可拿"必须靠活目录 + 发现流程支撑,否则遇到新需求(如商品订单、会员、优惠券)只能靠猜 endpoint。
- 数据源目录
references/data_source_catalog.md:地图。列出已确认源(内置 8 源)与典型待确认业务域(商品订单/会员/优惠券/退款/门店…),每域标注 UI 位置 + 模块猜测,作为"下次去哪找"的起点。 - 发现流程
references/discovery.md:标准动作。用web-access登录 EZR → 在目标报表页抓导出按钮的 XHR(得endpoint/body/模块,并从导出任务列表拿Type)→ 用scripts/ezr_discover.py真实触发一次、确认产物结构 → 入库并回填目录。 - 探针工具
scripts/ezr_discover.py:把"捕获到的 endpoint"变成"已验证的源"。真实触发小范围导出、下载并打印文件/zip 内层/xlsx sheet 名/首行表头,无需 openpyxl。
原则:宁可标"待确认"也不编造 endpoint。目录里
[待确认]的行都须经 discovery 流程钉死Type与精确路径后才能改[已知]。本机无可用 session 时无法当场枚举全部数据源,但发现流程让任何新需求都能被快速、可靠地定位。
- 配套文档:免登录自动刷新/认证原理见
references/auth.md;数据源目录见references/data_source_catalog.md;发现流程见references/discovery.md。
⭐ 多 AI / 多进程并发安全(共用同一 Chrome + 同一 EZR 后台时)
当设备上有多个 AI(或多个定时任务)共用同一个已登录的 Chrome、访问同一个 EZR 后台时,会涉及三类冲突面,本 skill 已做对应处理:
- 浏览器 / CDP(9222):本 skill 不自行启动 Chrome,只连接已开着的、带
--remote-debugging-port=9222的 Chrome。CDP 协议支持多客户端同时连同一 Chrome,故多 AI 连同一浏览器不会互相"占住"。冲突仅出现在"某 AI 自起 Chrome 抢 9222"的极端情况(本 skill 不做此动作)。 - EZR 登录会话(同账号 pcl_sid):多 AI 共用同一份
pcl_sid= 同一账号复用同一 cookie,不会因"后登录踢前登录"而互相挤下线(这比各自登录更安全)。风险仅在并发导出任务可能串台/被限流;若改用不同 EZR 账号登录同一后台,EZR 若有单会话策略反而会真互踢——故推荐共享账号。 - Cookie 文件(磁盘竞态,已根治):以前默认
ezr_cookie.txt被所有调用共享,并发刷新会互相覆盖、读者读到半截 → 900。现:- 原子写:
write_cookie_file先写.tmp再os.replace原子替换(Windows MoveFileEx / POSIX rename)→ 读者(ezr_export.py)任何时刻都读到完整旧文件或完整新文件,绝无半截。 - 写锁:
_cookie_write_lock用<cookie_file>.lock的O_EXCL原子创建串行化并发刷新(跨平台,含 120s 过期锁清理防死锁;超时 30s 报错提示手动删锁)。锁按 cookie 文件路径派生,不同账号/不同路径互不阻塞。
- 原子写:
多 AI 部署建议
- 共享同一 EZR 账号(推荐,最省事):所有 AI 用同一个
EZR_COOKIE_FILE+ 上述写锁;但不要同时跑大量导出,错峰即可。 - 需要真正隔离:给每个 AI 配 独立的 EZR 子账号;或 独立的 Chrome 用户数据目录 + 各自 9222 端口(如 9223 / 9224,用
--cdp-port/EZR_CDP_PORT区分),并各自指向独立的EZR_COOKIE_FILE。
核心难点(务必注意)
- 轮询防串台(daily 源必须用 strict_day):
GetDownList是租户(品牌)级共享的,里面混着同名但数据范围不同的历史/他人任务。例:20260719分销导购数据导出既有真单日(QuerysStartTime=EndTime=2026-07-19,导购业绩=4239)也有三天范围(QuerysStartTime=2026-07-17,=14620 三天之和)的 Status=2 任务。只按"日期字符串+CreateDate最新"会挑到跨天的错报告。poll_task对 daily 型源强制strict_day校验:解析 Querys 起止日期,只接受起止都==当天 的真单日报告,跨天/累计一律排除。month_end 型(分销月累/活码月累/1V1)不应用 strict_day。单日活码额外用exclude_keywords=["累计"]。 - GetDownList 时间窗(两个坑):① 不能按运行当天过滤(原
BegDate=EndDate=today是 bug)——任务可能是更早日期建的(如 7/21 重导 7/19 数据时,那份单日任务是 7/20 建的),会被窗口挡掉导致轮询超时、文件保留旧错值。现改为最近 120 天窗 + match_name + strict_day + 最新 定位。② EZR 限制查询时间段不得超过 180 天,窗太宽会报"查询时间段超过了180天"而整体失败。120 天是安全上限内的值。 - 认证/字段:
BigData用 RSAv头(明文 Body);CRM用 AES_jmbody+ SHA1s头。ErrorMsg=900= session 过期需重登(由EZRSessionExpired异常 +EZR_SESSION_EXPIRED标记结构化上报,供自动刷新包装器精准识别)。需数字类型的字段用{brand_id!int}渲染为整数。 - 活码按添加日口径:多人活码按
LogCreateDateBeg/End(添加时间)筛选,不是报告范围;单日分别筛选 + 累计一份。 - 依赖:
pip install pycryptodome requests(xlsx 直接下载,无需 openpyxl)。
常见报错 FAQ(用户向排查)
-
Q1:报
EZR_SESSION_EXPIRED/ErrorMsg=900(session 过期) → 含义:pcl_sid失效,需重新登录。 → 处理:① 用ezr_auto_refresh.py(推荐,自动经 CDP 从已登录 Chrome 刷新);② 或手动到 EZR 网页登录一次、重新复制 cookie 写入EZR_COOKIE_FILE。 → 仍失败:确认 Chrome 里 EZR 确实处于「已登录」状态(不是停在登录页),且已开--remote-debugging-port=9222。 -
Q2:导出的数字对不上 / 混进了其它日期的数据(串台) → 含义:daily 源(分销按日等)从租户级共享任务列表挑报告时,挑到了跨天 / 累计的错报告。 → 处理:daily 型源本 skill 默认强制
strict_day校验(只接受起止都 == 当天);用--date 2026-07-20按汇报日单日导出,不要人为放大--start/--end范围冒充单日。 -
Q3:报错「获取 cookie 写锁超时」/
<cookie_file>.lock残留 → 含义:上一次刷新被强杀,残留锁文件未清理。 → 处理:删掉<cookie_file>.lock后重试(锁含 120s 过期自动清理,等一会通常也会自愈)。 -
Q4:报「查询时间段超过了180天」 → 含义:EZR 限制单次查询窗 ≤180 天。 → 处理:缩小
--start/--end范围再跑;本 skill 内部轮询窗已设为 120 天安全上限。 -
Q5:CDP 取 cookie 失败 / 提示缺少 cdp helper → 处理:确认 Node 22+ 已装、
scripts/cdp_get_ezr_cookie.mjs存在;确认 Chrome 已开 9222 且已登录 EZR。
参考
references/auth.md— 双模块认证原理、v/s 头算法、session 安全references/data_sources.md— 数据源格式差异、按日/月累、活码口径、8 源清单、自定义 sources JSON 写法references/data_source_catalog.md— EZR 数据源目录(通用地图):已确认源 + 待确认业务域速查references/discovery.md— 发现任意新数据源的标准流程 +ezr_discover.py用法scripts/ezr_discover.py— 新数据源探针:验证 endpoint/Type 并打印产物结构(无 openpyxl 依赖)
Scan to join WeChat group