'commit'
This commit is contained in:
@@ -241,59 +241,16 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
d.swipe(w * 0.5, h * 0.8, w * 0.5, h * 0.3, 0.5)
|
||||
await asyncio.sleep(1.0)
|
||||
|
||||
template_jgxx = os.path.join(os.path.dirname(__file__), "Template", "jgxx.jpg")
|
||||
template_qbsd = os.path.join(os.path.dirname(__file__), "Template", "qbsd.jpg")
|
||||
entrance_point = None
|
||||
entrance_source = None
|
||||
max_search_rounds = 5
|
||||
|
||||
if os.path.exists(template_qbsd):
|
||||
try:
|
||||
match_res_qbsd = d.image.match(template_qbsd)
|
||||
except Exception as e:
|
||||
match_res_qbsd = None
|
||||
logger.error(f"[详情页] qbsd 模板匹配价格入口失败: {e}")
|
||||
if match_res_qbsd:
|
||||
logger.info(f"[详情页] qbsd 模板匹配返回结果: {match_res_qbsd}")
|
||||
if hasattr(match_res_qbsd, "point") and match_res_qbsd.point:
|
||||
entrance_point = match_res_qbsd.point
|
||||
elif isinstance(match_res_qbsd, dict):
|
||||
if "point" in match_res_qbsd and match_res_qbsd["point"]:
|
||||
entrance_point = match_res_qbsd["point"]
|
||||
elif "x" in match_res_qbsd and "y" in match_res_qbsd:
|
||||
entrance_point = (match_res_qbsd["x"], match_res_qbsd["y"])
|
||||
elif isinstance(match_res_qbsd, (list, tuple)) and len(match_res_qbsd) >= 2:
|
||||
entrance_point = (match_res_qbsd[0], match_res_qbsd[1])
|
||||
if entrance_point:
|
||||
entrance_source = "qbsd"
|
||||
logger.info(f"[详情页] 通过 qbsd.jpg 成功找到价格入口: {entrance_point}")
|
||||
|
||||
for round_idx in range(max_search_rounds):
|
||||
if entrance_point:
|
||||
break
|
||||
search_screen_path = take_screenshot(d, f"tld_detail_search_{int(time.time())}_{round_idx}.jpg")
|
||||
logger.info(f"[详情页] 搜索价格入口,第 {round_idx + 1}/{max_search_rounds} 轮: {search_screen_path}")
|
||||
|
||||
if os.path.exists(template_jgxx):
|
||||
try:
|
||||
match_res = d.image.match(template_jgxx)
|
||||
except Exception as e:
|
||||
match_res = None
|
||||
logger.error(f"[详情页] 模板匹配价格入口失败: {e}")
|
||||
if match_res:
|
||||
logger.info(f"[详情页] 模板匹配返回结果: {match_res}")
|
||||
if hasattr(match_res, "point") and match_res.point:
|
||||
entrance_point = match_res.point
|
||||
elif isinstance(match_res, dict):
|
||||
if "point" in match_res and match_res["point"]:
|
||||
entrance_point = match_res["point"]
|
||||
elif "x" in match_res and "y" in match_res:
|
||||
entrance_point = (match_res["x"], match_res["y"])
|
||||
elif isinstance(match_res, (list, tuple)) and len(match_res) >= 2:
|
||||
entrance_point = (match_res[0], match_res[1])
|
||||
if entrance_point and not entrance_source:
|
||||
entrance_source = "jgxx"
|
||||
|
||||
if not entrance_point:
|
||||
try:
|
||||
vlm_res = await self.read_image_kit.find_price_entrance_vlm(search_screen_path)
|
||||
@@ -332,10 +289,17 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
)
|
||||
|
||||
ex, ey = int(entrance_point[0]), int(entrance_point[1])
|
||||
click_x = ex
|
||||
offset_y = int(h * 0.1)
|
||||
click_y = min(h - 10, ey + offset_y)
|
||||
logger.info(f"[详情页] 使用 {entrance_source or '模板'} 价格入口坐标: ({ex}, {ey}),调整后点击坐标: ({click_x}, {click_y}),即将进入电价页")
|
||||
entered_price_page = False
|
||||
|
||||
if entrance_source == "vlm":
|
||||
click_x = ex
|
||||
click_y = ey
|
||||
logger.info(f"[详情页] 使用 VLM 当前价红色价格入口坐标直接点击: ({click_x}, {click_y})")
|
||||
else:
|
||||
click_x = ex
|
||||
offset_y = int(h * 0.1)
|
||||
click_y = min(h - 10, ey + offset_y)
|
||||
logger.info(f"[详情页] 使用 {entrance_source or '入口'} 坐标: ({ex}, {ey}),调整后点击坐标: ({click_x}, {click_y}),即将进入电价页")
|
||||
d.click(click_x, click_y)
|
||||
await asyncio.sleep(WAIT_DETAIL_PAGE_LOAD)
|
||||
|
||||
@@ -346,13 +310,11 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
bottom_ratio=BOTTOM_SAFE_EXCLUDE_RATIO,
|
||||
)
|
||||
|
||||
entered_price_page = False
|
||||
|
||||
if before_md5 and after_md5 and before_md5 != after_md5:
|
||||
entered_price_page = True
|
||||
logger.info("[电价页] 模板点击后页面内容发生变化,判定已进入电价详情页。")
|
||||
logger.info("[电价页] 首次点击后页面内容发生变化,判定已进入电价详情页。")
|
||||
else:
|
||||
logger.warning("[电价页] 模板点击后页面内容无明显变化,尝试使用 VLM 兜底寻找价格入口。")
|
||||
logger.warning("[电价页] 首次点击后页面内容无明显变化,尝试使用 VLM 兜底寻找价格入口。")
|
||||
try:
|
||||
vlm_res = await self.read_image_kit.find_price_entrance_vlm(before_price_path)
|
||||
except Exception as e:
|
||||
@@ -371,7 +333,7 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
logger.info(f"[电价页] 使用 VLM 兜底点击价格入口: ({vx}, {vy}),原因: {vlm_res.get('reason')}")
|
||||
d.click(vx, vy)
|
||||
await asyncio.sleep(WAIT_DETAIL_PAGE_LOAD)
|
||||
|
||||
|
||||
vlm_after_path = take_screenshot(d, f"tld_detail_price_after_vlm_{int(time.time())}.jpg")
|
||||
vlm_after_md5 = get_image_content_md5(
|
||||
vlm_after_path,
|
||||
|
||||
@@ -25,16 +25,20 @@ class ReadImageKit:
|
||||
使用 VLM 在详情页寻找价格入口(如:1.1556元/度 的卡片或价格信息按钮)
|
||||
"""
|
||||
prompt = """
|
||||
分析这张充电站详情页截图,找到进入“分时电价详情”的点击入口。
|
||||
入口特征:
|
||||
1. 包含价格数字的卡片,例如 "1.1556元/度"。
|
||||
2. 或者标有 "价格信息"、"电价详情" 字样的按钮。
|
||||
|
||||
请判断该入口是否存在,并给出其中心坐标。
|
||||
分析这张特来电充电站详情页截图,找到进入“分时电价详情”的点击入口。
|
||||
入口优先级和特征如下:
|
||||
1. 首选:页面中有文字“当前价”,其正下方一行通常是红色的电价数字,
|
||||
例如 “1.1317 元/度”、“1.1556 元/度”等,请优先选择这行红色价格数字所在区域。
|
||||
2. 如果页面同时存在“停车参考价”“停车费参考价”等字样,请不要选择这些区域,
|
||||
只选择与充电“当前价”直接对应的红色价格数字。
|
||||
3. 如果页面没有“当前价”字样,则可以退而求其次,选择明显用于展示
|
||||
充电价格的卡片或按钮,例如写有“价格信息”“电价详情”的区域。
|
||||
|
||||
请判断符合上述规则的价格入口是否存在,并给出其中心坐标。
|
||||
输出格式为 JSON:
|
||||
{
|
||||
"found": true/false,
|
||||
"reason": "为什么认为这是入口",
|
||||
"reason": "为什么认为这是入口(说明是否基于当前价红色价格)",
|
||||
"point": [x, y], // 归一化坐标 [0-1000],例如 [500, 600] 代表屏幕中心偏下
|
||||
"type": "price_card" / "button"
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user