This commit is contained in:
HuangHai
2026-01-12 16:16:06 +08:00
parent 45303dfcb2
commit 4cef36dc96

View File

@@ -0,0 +1,69 @@
# 艾特吉易充数据抓取流程说明文档
本文件详细记录了艾特吉易充(微信小程序)数据抓取爬虫的设计架构、抓取流程及关键技术实现。
---
## 1. 项目概述
本爬虫旨在自动化抓取“艾特吉易充”小程序中的充电场站信息,包括场站名称、地址、充电枪状态、实时价格以及 24 小时分时价格表。
## 2. 核心抓取流程
爬虫采用“列表 -> 详情 -> 价格 -> 返回 -> 列表”的闭环循环逻辑。
### 2.1 第一级:场站列表页
- **操作**: 自动滚动列表,每屏截取一张大图。
- **识别方法**:
- **图形学切片**: 使用 OpenCV 识别图片中的白色卡片区域(几何卡片),确定点击位置。
- **VL 模型分析**: 使用 `Qwen-VL` 模型识别本页所有场站的名称、基础价格和归一化坐标。
- **坐标匹配**: 将几何卡片的像素坐标与 VL 模型的归一化坐标进行交叉比对,确定每个卡片对应的场站名称。
- **关键点**: 通过几何卡片确保点击的准确性,通过 VL 模型确保数据的语义准确性。
### 2.2 第二级:场站详情页
- **进入**: 点击列表页卡片。
- **操作**: 截取详情页全图。
- **识别方法**:
- **异步识别**: 截图后立即启动 `asyncio.create_task` 在后台调用 VL 模型提取地址和基础信息。
- **模板匹配**: 使用 OpenCV 查找“分时价格”图标(`timePrice.jpg`)的坐标。
- **关键点**: UI 流程不等待 VL 模型返回,直接寻找入口进入下一级。
### 2.3 第三级:价格详情页
- **进入**: 点击详情页中的分时价格入口。
- **操作**: 截取价格列表,若列表过长则执行滑动截图,利用 MD5 校验判断是否滑动到底部。
- **识别方法**:
- **异步识别**: 截图完成后UI 立即执行 `d.press("back")` 返回列表页,所有截图交给后台任务处理。
- **数据规整**: 后台任务调用 VL 模型识别各时段价格,并使用 `ReadImageKit.expand_schedule_to_24h` 将不规则时段规整为 24 小时整点数据。
---
## 3. 关键技术点
### 3.1 异步并发设计 (Decoupling)
- **实现方式**: 使用 `AsyncOpenAI` 客户端和 `asyncio.create_task`
- **为什么要异步?**:
1. **提高吞吐量**: VL 模型响应通常需要 3-8 秒。如果同步等待,爬取一个场站可能需要 20 秒以上。异步化后,手机 UI 可以在后台分析的同时继续操作。
2. **用户体验**: UI 操作(点击、滑动、返回)是连续的,不会因为网络请求波动而卡顿。
- **任务追踪**: 在 `Crawler.py` 中维护 `background_tasks` 列表,在每页结束时清理已完成任务,并在整个爬取结束时使用 `asyncio.gather` 等待残余任务。
### 3.2 智能去重机制
- **Redis 模糊匹配**: 针对小程序中场站名称可能被省略号截断(如“万达茂...”)的情况,不仅存储全名,还存储场站名称的前 6 位作为前缀索引。
- **逻辑**: 先查全名,再查前缀索引。如果前缀匹配成功,则视为已爬取,跳过重复工作。
### 3.3 坐标系转换
- **VL 坐标**: 0-1000 的归一化坐标。
- **UI 坐标**: 屏幕像素坐标(如 1080x2400
- **转换公式**: `px = val * screen_size / 1000`。用于将 VL 识别的场站位置映射到屏幕实际可点击位置。
### 3.4 鲁棒性设计
- **JSON 提取器**: `ReadImageKit._extract_json` 采用递归和 `raw_decode` 策略,能够从 VL 模型输出的杂乱文本中精准提取 JSON 内容,容忍模型输出的说明文字。
- **图片读写**: `Kit.py` 封装了支持中文路径的图片读写方法(`np.fromfile` / `cv2.imencode`),并增加了空文件校验,防止因并发读写导致的 `cv2` 崩溃。
---
## 4. 给研发人员的建议
1. **调试模式**: 开启 `logging.INFO` 级别可以观察到 VL 模型的完整响应。
2. **环境依赖**: 确保 `uiautomator2` 已正确连接 Android 设备。
3. **API 消耗**: 异步调用会增加 API 并发压力,请确保使用的 API Key 具有足够的 QPS 限额。
4. **内存管理**: 后台任务会持有图片路径,处理完成后务必调用 `os.remove` 清理临时图片。
---
*文档更新日期2026-01-12*