Files
aiData/Doc/4、流程说明.md
HuangHai b66f683dfb 'commit'
2026-01-12 07:49:18 +08:00

9.4 KiB
Raw Permalink Blame History

新电途微信小程序爬虫流程说明文档

本文档详细记录了“新电途”微信小程序爬虫的工作流程、技术细节、避坑指南及维护策略,旨在帮助开发人员快速理解系统架构,应对 UI 变更及设备更换等场景。


1. 项目概述

本项目是一个基于 Python + uiautomator2 + 视觉大模型 (VL) + 计算机图形学 (CV) 的自动化爬虫系统。 其核心目标是模拟用户操作,遍历“新电途”小程序的场站列表,识别场站信息(名称、价格、空闲桩数),并进入详情页抓取地址和分时电价。

核心技术栈

  • 控制端: uiautomator2 (Android 自动化控制)
  • 视觉识别 (VL): 阿里云 Qwen-VL / DeepSeek (负责复杂的文字和语义提取)
  • 计算机图形学 (CV): OpenCV (负责快速、低成本的广告检测、按钮定位、图像切片)
  • 数据存储: Doris (MySQL 协议) + Redis (去重缓存) + Huawei OBS (图片存储)

2. 核心流程图解

graph TD
    A[启动程序 (Y5_Full)] --> B[Step 0: 初始化服务 & 数据库]
    B --> C[Step 1: 打开小程序 (Y2)]
    C --> D{检测广告 (CV)}
    D -- 有广告 --> E[点击关闭 (CV模板/几何)]
    D -- 无广告 --> F[Step 2: 列表页爬取 (Y3)]
    E --> F
    F --> G[截图 & 切片 (CV)]
    G --> H[上传图片至 OBS]
    H --> I[调用 VL 模型解析场站列表]
    I --> J{是否存在有效场站?}
    J -- 是 --> K[遍历场站]
    K --> L{是否已处理? (Redis)}
    L -- 否 --> M[点击进入详情页]
    M --> N[截图详情页 & 解析地址]
    N --> O[抓取分时电价 (可选)]
    O --> P[返回列表页]
    P --> K
    L -- 是 --> K
    J -- 否 --> Q[下拉翻页]
    Q --> F
    Q -- 结束 --> R[Step 3: 坐标回填 (Y4)]
    R --> S{Cookie 有效?}
    S -- 是 --> T[高德 API 查询 & 更新 DB]
    S -- 否 --> U[弹窗手动登录 (T2)]
    U --> T

3. 详细步骤与技术实现

步骤 0: 初始化 (Y5_Full.py)

  • 动作: 程序启动时,首先初始化 XinDianTuService 并连接数据库。
  • 目的: 确保后续爬取过程中数据库连接立即可用,避免在写入数据时才初始化导致的延迟或错误。
  • 注意: 数据库连接采用单例模式或长连接,程序结束时需显式关闭。

步骤 1: 启动小程序 (Y2_OpenXinDianTu.py)

  • 动作:
    1. 强制停止微信并重新启动,确保回到微信主页。
    2. 点击底部“微信”标签。
    3. 点击右上角“搜索”按钮(基于百分比坐标)。
    4. 输入“新电途”并点击搜索结果进入小程序。
  • 坑点:
    • 搜索入口坐标: 搜索按钮的位置在不同分辨率手机上略有差异,目前使用 w * 0.84, h * 0.08。如果更换手机,需检查此坐标。
    • 输入法干扰: uiautomator2 的输入法有时会失效,代码中做了 send_keys(clear=True) 和直接输入的双重兜底。

步骤 2: 列表页爬取 (Y3_StationList.py)

这是最核心的循环步骤(如需广告检测会自动调用 CV 模块):

  1. 截图: d.screenshot()
  2. 图像切片 (CV): 调用 Kit.crop_cards_from_image
    • 利用行扫描算法,根据像素亮度和方差,识别出场站卡片之间的灰色分割线,将大图切割成一个个小卡片 (_vl.jpg 实际上是带绿框的整图,配合 JSON 元数据)。
    • 优势: 极大降低了 VL 模型的理解难度,模型只需识别框内内容,不用自己找位置。
  3. VL 解析: 将图片上传 OBS调用 VL 模型Qwen/DeepSeek
    • Prompt: 要求模型提取“场站名称”、“价格”、“枪数”、“距离”等。
  4. 坐标映射与安全检查:
    • 模型返回的坐标会结合 device_info (设备真实宽高) 进行校验。
    • Config.py: SAFE_EXCLUDE_RATIO=0.20 (顶部20%不点)BOTTOM_SAFE_EXCLUDE_RATIO=0.1 (底部10%不点)。这解决了第一屏场站无法点击的问题。

步骤 3: 坐标回填 (Y4_Coord.py)

  • 动作: 扫描数据库中 address 不为空但 coord_x/y 为空的记录,调用高德地图 API 补全经纬度。
  • 智能修复:
    • 任务开始前会自动探测 Cookie 有效性。
    • 如果 Cookie 失效,自动调用 T2_GetAmapCookie 弹出浏览器窗口让用户手动登录。
    • 登录完成后,程序自动保存新 Cookie 并继续执行回填任务,无需重启。

4. 技术选型指南:何时用 CV何时用 VL

场景 推荐技术 理由
广告关闭按钮 CV (OpenCV) 图标固定、形状简单(圆/叉)、要求毫秒级响应、零成本。
隐私协议按钮 CV (OpenCV) 颜色特征明显(黑色块)、位置固定。
场站卡片切分 CV (行扫描) 列表页结构规律分割线特征稳定CV 切分极其精准且快。
读取场站名称 VL (大模型) 字体多样、可能有干扰、OCR 传统方案容易错乱VL 语义理解能力强。
读取价格/枪数 VL (大模型) 格式复杂("快 闲4/4"VL 能直接提取结构化 JSON。
寻找"全部时段" CV (几何特征) 按钮只有文字没有边框,但左右空白特征明显,用边缘检测更可靠。

总结:

  • 结构固定、特征简单、追求速度 -> 用 CV。
  • 语义复杂、内容多变、容错率高 -> 用 VL。

5. 关键参数配置 (Config/Config.py)

参数名 当前值 说明 调整场景
SAFE_EXCLUDE_RATIO 0.20 顶部安全排除比例。在此比例内的坐标不点击。 如果发现第一屏顶部的场站无法点击,调小此值。
BOTTOM_SAFE_EXCLUDE_RATIO 0.1 底部安全排除比例。避开“扫码充电”等按钮。 如果频繁误触底部按钮,调大此值。
SCROLL_DISTANCE_RATIO 0.3 翻页滑动幅度的比例。 如果翻页太快漏数据,调小;翻页太慢,调大
MAX_CRAWL_DISTANCE 50 最大爬取距离 (km)。 根据业务需求调整爬取范围。
VL_MODEL_NAME qwen3-vl-flash 使用的视觉模型版本。 如果识别准确率下降,可尝试升级模型。

6. 避坑指南与设备更换

Q1: 更换手机需要注意什么?

  1. 分辨率差异:
    • 代码大部分使用了相对坐标 (百分比),理论上兼容不同分辨率。
    • 重点检查: Y2_OpenXinDianTu.py 中的搜索按钮点击坐标 (0.84, 0.08)。新手机可能刘海屏高度不同,导致 Y 轴偏移。
  2. 截图尺寸 vs 屏幕尺寸:
    • 某些手机截图分辨率与 d.info 获取的屏幕分辨率不一致(如 Retina 缩放)。
    • 解决方案: Y3_StationList.py 中已包含自动检测逻辑:if img_w != w: device_info['width'] = img_w。一般无需手动修改。

Q2: 小程序 UI 大改版怎么办?

  1. 列表样式变更:
    • 如果列表不再有明显的灰色分割线,Kit.py 的切片逻辑 (get_card_segments) 会失效。
    • 应对: 修改 Kit.py,改用 VL 模型直接进行全图目标检测 (Object Detection),或者调整 CV 分割线的颜色阈值。
  2. 广告样式变更:
    • 如果出现新广告,截图保存到 Tools/Templates,命名为 ad_close_new.jpg 即可,代码会自动加载。

Q3: 为什么有场站但没点进去?

  1. 被安全区拦截: 检查日志 safe exclude 关键字。如果是误拦截,调整 SAFE_EXCLUDE_RATIO
  2. VL 识别失败: 检查 Images/ 目录下的 _vl.jpg,看绿框是否框住了场站。如果没有,说明 CV 切片参数 (Kit.py) 需要调整(如 row_mean 阈值)。

7. 调试与单元测试

虽然本项目没有使用标准的 unittest 框架,但每个核心模块都设计了独立运行入口 (if __name__ == "__main__":),方便单步调试。

单元调试清单

功能模块 对应文件 调试方法 作用
广告检测 (CV) Util/Kit.py 无法直接运行,需编写临时脚本调用 detect_ad_close_x。建议在 Tools/T3_CropCards.py 中添加测试代码。 测试新广告模板是否生效。
切片逻辑 (CV) Tools/T3_CropCards.py 运行该脚本,会自动读取 Samples 目录下的图片进行切片测试。 调试列表分割线识别参数。
进入小程序 Tools/Y2_OpenXinDianTu.py 直接运行该文件。 测试微信启动和搜索流程。
列表爬取主循环 Tools/Y3_StationList.py 直接运行该文件 (需连接手机)。 独立测试爬取流程,不依赖外部调度。
全流程 Tools/Y5_Full.py 直接运行该文件。 生产环境模拟(含坐标回填)。

建议的开发习惯

  1. 遇到新 Bug: 先看日志 (Tools/Logs/), 确定是哪一步卡住。
  2. 保留现场: KEEP_SCREENSHOTS = True (在 Y3_StationList.py),开启后会保留所有截图,方便事后分析。
  3. 单步验证: 如果是广告检测问题,把截图拿出来,写个几行的 Python 脚本单独调用 Kit.detect_ad_close_x 进行验证,不要每次都跑全流程。