This commit is contained in:
HuangHai
2026-01-16 19:15:40 +08:00
parent a565d9c45d
commit c7cf0db77e
18 changed files with 232 additions and 12 deletions

View File

@@ -157,6 +157,20 @@ class YiLaiTeCrawler(BaseCrawler):
if before_md5 != after_md5:
logger.info(f"成功进入详情页: {name}")
# 兜底:在进入详情页后,先基于列表页信息一次性写入 Profile 与 Status
try:
await self.service.save_station_profile_and_status(
station_name=name,
address=address,
total_piles=station.get("total_piles"),
free_piles=station.get("free_piles"),
piles_detail=None,
parking_info=None,
distance=distance
)
except Exception as e:
logger.warning(f"兜底写入场站基础信息失败: {name}, {e}")
# --- 新增:点击“阶段性电价”按钮以获取完整电价列表 ---
# 使用 OCR 探测价格入口
dqdf_pos = detect_price_info_container_cv(detail_shot)

View File

@@ -154,6 +154,8 @@ class ReadImageKit:
- "name": 场站名称 (仅提取名称文字)
- "address": 场站地址 (通常在名称下方,请完整提取地址文字)
- "distance": 距离 (如 "1.2km", "800m" 等,如果存在请提取)
- "total_piles": 总桩数 (如果存在请提取)
- "free_piles": 空闲桩数 (如果存在请提取)
- "is_valid": true/false (是否为真实的场站卡片)
注意:仅提取名称、地址和距离,不要包含价格。
@@ -190,6 +192,8 @@ class ReadImageKit:
"name": res.get("name"),
"address": res.get("address"),
"distance": res.get("distance"),
"total_piles": res.get("total_piles"),
"free_piles": res.get("free_piles"),
"point": [(bbox[0] + bbox[2]) // 2, (bbox[1] + bbox[3]) // 2],
"bbox": bbox
})

View File

@@ -195,6 +195,41 @@ class YiLaiTeService:
logger.info(f"成功保存驿来特场站数据: {station_name} | 距离: {distance} | 价格条数: {cnt}")
return True
async def save_station_profile_and_status(self, station_name, address=None, total_piles=None, free_piles=None, piles_detail=None, parking_info=None, distance=None):
"""
一次性写入场站基础信息与状态,用于列表页兜底
"""
if not station_name:
return False
station_hash = self.get_hash(station_name)
now = datetime.now()
async with await self.db.get_session() as session:
profile_id = self.generate_id()
await self.station_profile_model.save(
session=session,
id=profile_id,
station_hash=station_hash,
operator=self.operator,
station_name=station_name,
address=address,
valid_start_time=now,
)
status_id = self.generate_id()
await self.station_status_model.save(
session=session,
id=status_id,
station_hash=station_hash,
total_piles=total_piles,
free_piles=free_piles,
piles_detail_json=piles_detail,
parking_info=parking_info,
distance=distance,
current_price=None,
valid_start_time=now,
)
await session.commit()
logger.info(f"兜底写入驿来特场站基础信息与状态: {station_name} | 桩数: {free_piles}/{total_piles} | 距离: {distance}")
return True
async def process_station_list_vl(self, image_path, json_metadata, device_info=None, max_count=None) -> list:
"""
基于 VL 模式处理场站列表 (整页识别)

Binary file not shown.

View File

@@ -0,0 +1,73 @@
import sys
import os
import time
import uiautomator2 as u2
def kill_all_apps():
try:
d = u2.connect()
except Exception as e:
print(f"设备连接失败: {e}")
return False
print("返回桌面...")
try:
d.press("home")
except Exception as e:
print(f"按 Home 键失败: {e}")
return False
time.sleep(0.5)
print("打开快捷设置面板...")
opened = False
try:
d.open_quick_settings()
opened = True
except Exception:
try:
d.open_notification()
opened = True
except Exception as e:
print(f"打开快捷设置/通知面板失败: {e}")
if not opened:
return False
time.sleep(0.5)
print("查找“一键清理”按钮并点击...")
btn = None
for _ in range(3):
btn = d(text="一键清理")
if btn.exists:
break
btn = d(resourceId="com.android.systemui:id/statebutton3")
if btn.exists:
break
time.sleep(0.5)
if not btn or not btn.exists:
print("未找到“一键清理”按钮,请确认系统界面支持此功能。")
return False
try:
btn.click()
time.sleep(0.5)
print("已点击“一键清理”,正在结束后台应用。")
return True
except Exception as e:
print(f"点击“一键清理”失败: {e}")
return False
def main():
success = kill_all_apps()
if not success:
sys.exit(1)
if __name__ == "__main__":
main()