This commit is contained in:
HuangHai
2026-01-12 16:53:43 +08:00
parent 4cef36dc96
commit f263c133b8
7 changed files with 441 additions and 758 deletions

View File

@@ -30,29 +30,15 @@ logger = logging.getLogger("AiTeJiYiChongCrawler")
async def is_already_crawled(redis_kit, station_name):
"""
检查场站是否已经爬取过,支持前缀模糊匹配处理截断名称
检查场站是否已经爬取过,仅按名称去重
"""
cleaned_name = Kit.clean_station_name(station_name)
if not cleaned_name:
return False
# 1. 检查精确匹配
redis_key = f"crawled:aite:{cleaned_name}"
if await redis_kit.get_data(redis_key):
return True
# 2. 如果名称被截断(原名包含 . ),尝试前缀匹配
# 逻辑:在 Redis 中查找是否有以当前清理后的名称开头的已完成场站
# 为了效率,我们配合 Redis 的 keys 模式(小规模数据下可用)
if ".." in station_name or station_name.endswith("."):
# 获取所有已爬取的 key 进行内存前缀比对,或者利用 Redis 模糊查询
# 这里采用一种更高效的方式:在详情页保存时,额外保存一个前缀索引
prefix_key = f"crawled:aite:prefix:{cleaned_name[:6]}" # 取前6位作为索引前缀
stored_names = await redis_kit.get_data(prefix_key)
if stored_names and isinstance(stored_names, list):
for full_name in stored_names:
if full_name.startswith(cleaned_name):
return True
return False
async def get_station_list(d, service, max_scrolls=MAX_SCROLLS):
@@ -190,16 +176,9 @@ async def get_station_list(d, service, max_scrolls=MAX_SCROLLS):
d.press("back")
await asyncio.sleep(0.8)
# 记录 Redis (保存全名并建立前缀索引)
# 记录 Redis (仅按名称去重,不再使用前缀索引)
full_name_key = f"crawled:aite:{Kit.clean_station_name(station_name)}"
await redis_kit.set_data(full_name_key, "1", expire=REDIS_STATION_EXPIRE)
# 建立前缀索引 (取前6位,方便模糊查找)
prefix_idx_key = f"crawled:aite:prefix:{Kit.clean_station_name(station_name)[:6]}"
existing_names = await redis_kit.get_data(prefix_idx_key) or []
if station_name not in existing_names:
existing_names.append(station_name)
await redis_kit.set_data(prefix_idx_key, existing_names, expire=REDIS_STATION_EXPIRE)
# 在每一页结束时,清理已完成的任务,防止内存堆积
done_tasks = [t for t in background_tasks if t.done()]

View File

@@ -44,9 +44,14 @@
2. **用户体验**: UI 操作(点击、滑动、返回)是连续的,不会因为网络请求波动而卡顿。
- **任务追踪**: 在 `Crawler.py` 中维护 `background_tasks` 列表,在每页结束时清理已完成任务,并在整个爬取结束时使用 `asyncio.gather` 等待残余任务。
### 3.2 智能去重机制
- **Redis 模糊匹配**: 针对小程序中场站名称可能被省略号截断(如“万达茂...”)的情况,不仅存储全名,还存储场站名称的前 6 位作为前缀索引。
- **逻辑**: 先查全名,再查前缀索引。如果前缀匹配成功,则视为已爬取,跳过重复工作。
### 3.2 场站去重策略
- **按名称去重**: 仅依据列表显示的场站名称进行去重,不再使用前缀或模糊匹配。
- **处理规则**:
- 名称先经 `clean_station_name` 去掉尾部省略号与空格,例如 `AAABBB...` → `AAABBB`;
- 首次遇到该名称时处理并写入 Redis 键 `crawled:aite:{name}`;
- 后续再遇到同名(包括省略号截断的同名)直接跳过,不再点击进入详情页。
- **设计原因**: 逻辑直白、符合业务预期,降低模糊匹配带来的误判风险。
- **一致性说明**: 新电途项目采用同样的按名称去重策略以保持跨项目行为一致。
### 3.3 坐标系转换
- **VL 坐标**: 0-1000 的归一化坐标。