# WeChat-shop-appid-bootstrap **Repository Path**: os621/WeChat-shop-appid-bootstrap ## Basic Information - **Project Name**: WeChat-shop-appid-bootstrap - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-12 - **Last Updated**: 2026-08-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 微信小店 AppID 建档助手 这是与正式榜单采集客户端隔离的 PC 端建档工具。它复用正式仓已经验证过的 renderer 绑定与完整扫描代码,但不连接 MQTT、不写后台、不修改源 Excel,也不会放宽正式采集器的 `expectedAppId` 校验。 ## 控制店 - 主键 ID:`2069727365667258369` - 店铺名称:`中国建筑工业出版社书店` - 微信小店地址:`#微信小店://中国建筑工业出版社书店/QFztVLD1fITq6Kd` - 已知正确 AppID:`wxb083c27fcb6d650b` ## 当前闭环 1. 拒绝在正式 `WeChatShopCollector.exe` 运行时启动。 2. 要求开始前没有遗留“小店”窗口。 3. 文件传输助手已打开时直接复用;微信切换会话后即使暂时不暴露标题文本,只要存在唯一可见消息列表和唯一选中的精确同名会话,也视为已严格确认并重新获取微信 UI 根节点,不会误退化到不可用的搜索框。否则优先选择唯一可见的精确同名置顶会话,再退化到搜索“文件传输”后的唯一功能入口。 4. 第一次向输入框写入完整短链并逐字回读;第二次用第一次的消息回执精确重开同一条短链,不重复发送。 5. 发送后只接受本轮新增、名称与完整短链完全一致且带真实非空 UIA runtime ID 的一条消息,并先建立脱敏回执;即使首次点击失败,回执也会随失败 attempt 原子落盘。微信会把短链气泡和整行空白合并成一个 `ListItem`,因此拒绝使用整行 `TryGetClickablePoint`;只在右对齐消息行中按行高计算、避开左侧空白与最右头像的安全带内探测,并要求 `FromPoint` 命中的元素仍属于该精确消息。真正按下鼠标前再次按完整短链、回执和最新安全带复核。若首次点击未打开小店,只按同一 runtime 回执有界重击一次,绝不重复发送消息。 若客户端在取得回执后意外退出,下一次运行会在 campaign 运行锁内保留原始 attempt,另写中断恢复 sidecar 并把回执补入 campaign;后续 attempt 只复用该消息。找不到唯一且有效的回执时会停止并要求人工检查,不会猜测或重发。 6. 只接受由本轮动作新打开的唯一 Store HWND/PID。 7. 在该 Store 内先确认精确店名;当前区域没有“最畅销”时,每次只向下滚动 1 个刻度并立即重新检测,最多 72 步。若微信未暴露 UIA `ScrollPattern`,允许在 HWND/PID、可观察视口和真实滚轮落点均属于本轮 Store 时执行“窗口级探索滚动”,但这种模式只允许找到唯一入口这一正向结论,永远不能据此断言店铺没有榜单。只有确认从顶部开始、真实滚轮落点始终位于同一个 UIA 滚动容器内,并连续至少三次、累计稳定不少于 0.75 秒到达底部后仍未发现时,才标记 `SHOP_NO_BESTSELLER`;其余情况统一记为可重试的 `BESTSELLER_SEARCH_INCOMPLETE`。每一步保存脱敏证据;发现实名授权弹层时停止,不代替用户授权。 8. 点击唯一可见的“最畅销”前,先用命中测试确认点击点的顶层窗口仍是本轮 Store;点击后先原地确认榜单摘要。摘要仍位于当前视口下方时,使用同样受保护的 UIA 容器或 Store 窗口级探索滚动,最多再逐格下滚 12 步,直到看到“近一个月销量最高的商品”。到上限、页面不移动或落点无法证明时只记为可重试的转场失败,不会误写成没有榜单。 9. 将 Store HWND/PID 严格绑定到 renderer 代际,执行完整内存扫描。仅当严格榜单响应尚未出现时有界退避复扫 3 轮;manifest、schema、店名或 AppID 冲突仍立即拒绝。 10. 优先只从带 `GetProductRankList` 端点,或由扫描器证明与该端点标记处于同一物理 JSON 解析片段的 `listType=1` 响应中读取 `product_card.appid`。实际微信版本若把 endpoint 与响应 JSON 分开保存,只允许降到明确标注的 `EXACT_RENDERER_SCOPED_ENDPOINT_MARKER_AND_RANK_SHAPE`:同一精确 renderer 内必须同时存在 endpoint 标记和排除商品详情后的严格榜单响应;全部商品卡 AppID 仍须格式合法且全集为单例。 11. 用发现出的单例 AppID 回灌正式严格解析器,再与控制店已知 AppID 比较。 12. 只写本地脱敏 JSON 证据;成功时精确关闭本轮 Store 窗口。 如果同一 Store 进程下存在多个结构上可信的 renderer,工具不会按内存大小 猜选。它会逐个按精确代际复核并做完整扫描,只允许一个同时满足 `GetProductRankList + listType=1 + 商品卡 AppID 单例 + 商品卡店名精确一致` 的候选;纯响应缺席会按候选有界复扫。仅限结构候选恰好为两个、其中一个 严格命中且另一个连续三轮完全没有 `GetProductRankList` 响应时,先精确重绑 稳定复扫命中候选,再对空响应候选按同一代际做最终短时复核;复核仍完全无 榜单响应才把它记录为 `INERT_NO_RANK_RESPONSE`。出现第二份响应、目标列表 残缺、两个以上空候选、父子链无法证明、扫描不完整、语义冲突或严格命中 不唯一都会停批。 源码运行时通过兄弟目录 `..\wechat-shop-collector\src` 复用已经验证过的 renderer 绑定、完整扫描和严格榜单解析代码;独立 EXE 会把当前干净 commit 的这些模块固化进包,并在发布清单记录源码 commit 和 EXE SHA-256。EXE 不依赖正式客户端授权、数据库、Python 环境或源码目录。 ## 缺失 AppID 监督批 后台导出的 Excel 先经过只读合同检查:固定源文件 SHA-256,要求唯一工作表、四个精确表头、连续数据行、19 位文本主键,以及唯一店名和唯一短链。短链只允许清除首尾空白;短链内名称与任务店铺名称比较时允许 Unicode 空白差异,例如 `JINTIEBOOK` 与 `JINTIE BOOK`,其他文字、字母和标点仍必须一致。 未知 AppID 不会一次扫描后直接回填。每家店必须完成两次独立 Store 生命周期、两次完整 renderer 扫描、两次精确店名和同一个商品卡 AppID;第二次重用第一次的精确消息回执,不重复发送店铺地址。两次 Store 都确认关闭后才标记 `VERIFIED`。结果写入原子旁路台账,源 Excel 保持不变。单店语义冲突或重试耗尽会把该店标记为 `REVIEW_REQUIRED` 并继续后续店铺;全局窗口、版本或证据写入异常仍会停批。 首个监督批已验证两家: - `2079463421874167810` 学丞学丞晓艳教育:`wxf161164d6e01b7ae` - `2079463376953171970` 日知图书悦读纪:`wx170d72f4610b6508` 两家均完成两次独立闭环;证据台账位于 `runtime_data\supervised-batch\20260812T053022-b2f024da\ledger.json`。 随后扩容验证 10 家,共 20 次成功闭环;一次发送前窗口遮挡被安全拦截, 一次完整扫描部分读取在新批重试后恢复。累计注册表重新验证了 12 家的双次 证据、源文件哈希和跨店 AppID 唯一性,位于 `runtime_data\verified-registry\20260812T060552-cumulative12\registry.json`。 ## 运营一键模式(推荐) 运营人员不需要手工创建或复制 `campaign.json`,也不需要执行 PowerShell 命令。准备一个独立目录,只放以下两个业务文件: ```text AppID采集\ ├─ WeChatShopAppIdBootstrap.exe └─ 店铺管理-全部_日期时间.xlsx ``` 保持微信已经登录,退出正式榜单采集客户端,然后直接双击 `WeChatShopAppIdBootstrap.exe`。程序会以 EXE 所在目录为工作目录: 1. 自动识别同目录唯一一份仍有缺失 AppID 的后台导出 XLSX; 2. 首次运行自动创建并绑定同目录的 `campaign.json`; 3. 每次双击会连续处理全部尚可自动采集的店铺(上限 500 家),每家仍必须取得两次独立且一致的 Store/内存证据; 4. 单店进入 `REVIEW_REQUIRED` 时会跳过该店继续,批次结束后统一提示人工复核; 5. 第一家验证成功后即持续更新 `店铺AppID采集结果.xlsx`; 6. 全部完成后还会生成内容相同的 `final-import.xlsx`。 每次双击 EXE 都会将当前 `REVIEW_REQUIRED` 店铺重新跑一轮,但不删除旧 attempt。 本轮成功后依旧必须满足双次独立证据才能转为 `VERIFIED`;本轮仍失败则保留 复核状态,下次双击可再跑。如电脑重启后微信尚未登录,程序只记当前一家店并整批暂停, 不会再把后续店铺批量误标为人工复核;登录微信后再双击 EXE 即可继续。 运行后目录大致如下: ```text AppID采集\ ├─ WeChatShopAppIdBootstrap.exe ├─ 店铺管理-全部_日期时间.xlsx # 原始输入,始终不修改 ├─ campaign.json # 自动创建、自动续跑 ├─ campaign-summary.json # 当前进度 ├─ 店铺AppID采集结果.xlsx # 可导入后台的持续结果 ├─ final-import.xlsx # 全部完成后的最终副本 └─ attempts\ # 脱敏采集证据 ``` 同目录不能同时放两份仍有缺失 AppID 的后台导出表,否则程序会停止并提示 清理;Excel 自动生成的 `~$` 临时文件以及上面两个结果表会被自动忽略。 如后台重新导出的 Excel 只剩下未采集店铺,可用新文件替换已不需要的旧源 Excel, 无需删除 `campaign.json`。下次双击 EXE 时,程序只在“旧源文件已不存在且同目录恰好 只有一份合法新导出表”时自动换批:旧 campaign、进度 JSON 和结果 Excel 会移入 `campaign-history\<旧campaign-id>-时间`,`attempts` 保留原位,旧任务的已验证 AppID 会作为跨批所有权集带入新 campaign,随后直接采集新表中的待处理店铺。 采集期间不要打开结果 Excel,避免 Windows 文件锁阻止原子更新。任务一旦 产生 attempt,不要移动、重命名或手工编辑 EXE、源 Excel、`campaign.json`。 修复版 EXE 可以在完全关闭旧进程后以原文件名、原路径覆盖;程序会记录升级前后 SHA-256。 ## 正式批量采集(高级命令行) 正式批量入口是 `campaign-run`。先用 `campaign-create` 创建一次任务,后续 始终续跑同一个 `campaign.json`,不要反复新建任务。创建时会自动从 Excel 选择 AppID 缺失的店铺,并排除累计注册表中已经验证的店铺;同时固定源 Excel SHA-256、正式采集源码 commit 和 seed registry SHA-256,任一输入发生 变化都会拒绝续跑。 ```powershell $BootstrapPython = '..\wechat-shop-collector\.venv-production\Scripts\python.exe' $ShopExcel = 'E:\project\xingqiu\wechat-shop-collector-prod\店铺管理-全部_2026-08-11 21_29_36.xlsx' $VerifiedRegistry = 'E:\project\xingqiu\WeChat-shop-appid-bootstrap\runtime_data\verified-registry\20260812T060552-cumulative12\registry.json' $Campaign = 'E:\project\xingqiu\WeChat-shop-appid-bootstrap\runtime_data\campaigns\next20\campaign.json' # 只创建任务,不操作微信;自动选择下一批 20 家 & $BootstrapPython -m appid_bootstrap.cli campaign-create --input $ShopExcel --registry $VerifiedRegistry --limit 20 --campaign $Campaign # 只读查看进度 & $BootstrapPython -m appid_bootstrap.cli campaign-status --campaign $Campaign # 正式采集或续跑:本次最多新验证 4 家后安全暂停 & $BootstrapPython -m appid_bootstrap.cli campaign-run --campaign $Campaign --max-shops 4 --confirm-live-ui ``` 每家店必须连续取得两次独立且一致的成功证据,才会计入 `--max-shops`。 命令正常暂停后,重复执行同一条 `campaign-run` 即从未完成店铺继续。瞬态 失败会在本轮预算内自动重试;语义冲突、AppID 碰撞或重试预算耗尽会将单店转为 `REVIEW_REQUIRED`,然后继续其他店铺。所有可自动处理店铺完成后,campaign 若仍有复核项则状态为 `PAUSED_REVIEW`。 首页从顶部逐格检查,并在同一个 UIA 滚动容器内连续至少三次、累计不少于 0.75 秒稳定确认到底后,仍没有唯一“最畅销” 入口时,campaign 才会把该店的 `review_reason` 标记为 `SHOP_NO_BESTSELLER`。无法确认从顶部开始、页面位移或页面到底时会记录 `BESTSELLER_SEARCH_INCOMPLETE` 并按瞬态失败重试,不会再把“未检测到”写成 “店铺没有”。只使用 Store 窗口级探索滚动的结果也不能生成 `SHOP_NO_BESTSELLER`。两类失败都不会生成或写入 AppID。 任务目录会持续原子更新: - `campaign.json`:唯一任务状态和完整 attempt 索引; - `attempts\...\result.json`:每次采集的脱敏证据; - `verified-import-rows.json`:本 campaign 新验证的两列回填数据; - `cumulative-import-rows.json`:seed registry 与本 campaign 的累计回填数据; - `campaign-summary.json`:便于程序和人工读取的进度摘要。 - `店铺AppID采集结果.xlsx`:存在已验证店铺后持续更新的后台导入文件; - `final-import.xlsx`:campaign 全部完成后自动生成的后台导入文件。 采集程序不会直接修改源 Excel,也不会直接写后台。 ## 打包独立 EXE 构建脚本复用正式采集仓已经安装好的 Python 3.13/PyInstaller 6.21 环境。 打包时从 `wechat-shop-collector` 当前 `HEAD` 导出干净的只读快照,不会将正式仓工作树中尚未提交的其他开发改动混入 EXE,也不会修改或清理这些改动。 ```powershell cd E:\project\xingqiu\WeChat-shop-appid-bootstrap # 未签名的内部验证包 .\scripts\build_exe.ps1 ``` `dist\campaign.json` 存在时不要删除 campaign。只要旧 EXE 已完全退出,且 EXE 路径、旧 SHA-256、collector commit 都与 campaign 记录一致,上述默认命令都会先在 `build` 临时目录完成打包和冒烟校验。安装前脚本取得同一个 campaign 运行锁,并再次 核验客户端进程、campaign 哈希和旧 EXE 哈希;确认构建期间没有启动采集或换批后,才会 备份旧 EXE、发布清单和 campaign 到 `release\campaign-upgrade-backups`,最后只替换 `dist` 中的 EXE 和发布清单。即使 campaign 尚无 attempt,也走这条受保护路径;已验证 结果、`attempts` 和源 Excel 均保持不变。 如当前 `dist` 正在执行 campaign,可输出到独立发布目录,避免覆盖运行现场: ```powershell .\scripts\build_exe.ps1 -Clean -DistDirectory release\0.3.11 ``` 输出文件: - `dist\WeChatShopAppIdBootstrap.exe` - `dist\WeChatShopAppIdBootstrap.release.json` 正式分发时应使用组织的代码签名证书: ```powershell .\scripts\build_exe.ps1 ` -SigningCertificateThumbprint '<证书SHA1指纹>' ` -SignToolPath '' ``` 不要同时运行 `WeChatShopCollector.exe` 和建档 EXE。直接双击 EXE 会进入 上面的运营一键模式;高级命令与源码版一致,但去掉 Python 前缀,例如: ```powershell .\dist\WeChatShopAppIdBootstrap.exe diagnose .\dist\WeChatShopAppIdBootstrap.exe campaign-create --input <店铺导出.xlsx> --registry --limit 20 --campaign .\dist\WeChatShopAppIdBootstrap.exe campaign-run --campaign --max-shops 4 --confirm-live-ui ``` campaign 会绑定创建它的 EXE 目录、SHA-256 和内置采集源码 commit。任务 仍处于 `PREPARED` 且 attempt 为 0 时,`campaign-run` 可以安全地自动绑定 刚重新打包的当前 EXE,也可以先显式执行: ```powershell .\dist\WeChatShopAppIdBootstrap.exe campaign-rebind-client --campaign ``` 已产生 attempt 后仍不允许移动 EXE 或换到其他路径续跑。为修复建档客户端而原路径覆盖升级时,程序会在验证源 Excel、collector commit 和原 EXE 路径都未变后,记录 `SAME_PATH_CLIENT_UPGRADE` 并续跑;旧 attempt 和已验证结果不会删除。 ## 生成和导入 Excel campaign 全部完成后,会在 campaign 目录自动生成 `final-import.xlsx`。 该文件只有经过双次独立验证的店铺,包含四列:`主键id`、`店铺名称`、 `微信小店AppID`、`店铺地址`。19 位主键和 AppID 都按文本保存。 对于之前已经合并好的累计 registry,也可以单独生成导入文件: ```powershell .\dist\WeChatShopAppIdBootstrap.exe registry-export-xlsx ` --registry ` --input <创建该registry时的原始店铺导出.xlsx> ` --output <店铺AppID导入.xlsx> ``` 后台操作步骤: 1. 先在“店铺管理”重新导出全部店铺留作备份。 2. 确认导入文件只包含本轮准备更新的 `VERIFIED` 店铺。 3. 点击“导入”,选择生成的 `.xlsx` 文件并提交。 4. 导入成功后重新导出或刷新列表,按主键核对 AppID 数量和内容。 5. 建议每次导入 20 至 30 家;后台导入是整批事务,一行失败会导致整批回滚。 重要限制:普通 Excel 导入只能更新未绑定设备、且没有活动采集任务的店铺。 已经绑定设备的店铺会被后台拒绝,必须在后台使用受控的“校正 AppID”操作, 不能通过修改 Excel 绕过。跨店 AppID 重复、店铺不存在或状态不允许也会使 整批回滚。 ## 诊断和旧监督入口 使用正式采集仓已有的 production Python 环境: ```powershell ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli diagnose ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli inspect-source --input <店铺导出.xlsx> ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli control --confirm-live-ui ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli batch --confirm-live-ui --input <店铺导出.xlsx> --shop-id <19位ID> --shop-id <19位ID> ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli merge-ledgers --ledger <批次1\ledger.json> --ledger <批次2\ledger.json> --output ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli metrics --registry ``` 其中 `control` 只用于已知正确 AppID 的控制店验真;`batch` 是需要手工提供 店铺 ID 的旧监督入口,不再作为正式批量主命令;`diagnose`、 `inspect-source`、`metrics` 都不会操作微信。 如果发送和点击已成功、但后续页面检查或扫描发生可修复错误,可按同一 `result.json` 记录的精确 Store HWND/PID 继续,避免重复发送: ```powershell ..\wechat-shop-collector\.venv-production\Scripts\python.exe -m appid_bootstrap.cli resume --confirm-live-ui --result-path ``` 证据默认写入 `runtime_data\control-poc\\result.json`。失败不会回填 AppID,也不会删除聊天消息。