This commit is contained in:
HuangHai
2026-01-15 11:46:59 +08:00
parent f038929687
commit 8cbcca472b
11 changed files with 178 additions and 41 deletions

View File

@@ -7,7 +7,7 @@ import json
import cv2
from Apps.TeLaiDian.Kit import (
take_screenshot, get_image_content_md5, clean_station_name,
setup_logger, read_image, save_image
setup_logger, read_image, save_image, detect_warm_popup_xczs_cv
)
from Apps.TeLaiDian.ReadImageKit import ReadImageKit
from Apps.TeLaiDian.Service import TeLaiDianService
@@ -103,29 +103,18 @@ class TeLaiDianCrawler(BaseCrawler):
popup_screen_path = take_screenshot(d, f"tld_detail_popup_{int(time.time())}.jpg")
logger.info(f"[详情页] 截图用于检测温馨提示弹窗: {popup_screen_path}")
template_xczs = os.path.join(os.path.dirname(__file__), "Template", "xczs.jpg")
template_point = None
if os.path.exists(template_xczs):
try:
match_res = d.image.match(template_xczs)
if match_res:
if hasattr(match_res, "point") and match_res.point:
template_point = match_res.point
elif isinstance(match_res, dict):
if match_res.get("point"):
template_point = match_res["point"]
elif "x" in match_res and "y" in match_res:
template_point = (match_res["x"], match_res["y"])
elif isinstance(match_res, (list, tuple)) and len(match_res) >= 2:
template_point = (match_res[0], match_res[1])
if template_point:
logger.info(f"[详情页] 模板检测到疑似温馨提示弹窗位置: {template_point}")
else:
logger.info("[详情页] 模板未能确定温馨提示弹窗位置")
except Exception as e:
logger.error(f"[详情页] 模板检测温馨提示弹窗失败: {e}")
# 使用 OCR 探测“下次再说”按钮 (替代原来的模板匹配)
ocr_res = detect_warm_popup_xczs_cv(popup_screen_path)
ocr_point = None
if ocr_res:
w, h = d.window_size()
ocr_point = (
int((ocr_res[0] + ocr_res[2]) / 2 * w / 1000),
int((ocr_res[1] + ocr_res[3]) / 2 * h / 1000)
)
logger.info(f"[详情页] OCR 检测到“下次再说”按钮位置: {ocr_point}")
else:
logger.info(f"[详情页] 温馨提示模板文件不存在: {template_xczs}")
logger.info("[详情页] OCR 未能检测到“下次再说”按钮")
vlm_popup = {"has_popup": False}
try:
@@ -134,10 +123,9 @@ class TeLaiDianCrawler(BaseCrawler):
logger.error(f"[详情页] VLM 检测温馨提示弹窗失败: {e}")
has_vlm_popup = isinstance(vlm_popup, dict) and vlm_popup.get("has_popup")
if template_point and has_vlm_popup:
click_x = int(template_point[0])
click_y = int(template_point[1])
logger.info(f"[详情页] 模板与 VLM 均确认存在温馨提示弹窗,即将点击关闭按钮: ({click_x}, {click_y})")
if ocr_point and has_vlm_popup:
click_x, click_y = ocr_point
logger.info(f"[详情页] OCR 与 VLM 均确认存在温馨提示弹窗,即将点击“下次再说”按钮: ({click_x}, {click_y})")
debug_popup_path = popup_screen_path.replace(".jpg", f"_xczs_click_{click_x}_{click_y}.jpg")
try:
img_popup = read_image(popup_screen_path)
@@ -153,7 +141,7 @@ class TeLaiDianCrawler(BaseCrawler):
except Exception as e:
logger.error(f"[详情页] 点击温馨提示“下次再说”失败: {e}")
else:
logger.info(f"[详情页] 温馨提示弹窗未通过双重确认,模板检测: {bool(template_point)} | VLM 检测: {vlm_popup}")
logger.info(f"[详情页] 温馨提示弹窗未通过双重确认,OCR检测: {bool(ocr_point)} | VLM 检测: {vlm_popup}")
w, h = d.window_size()
logger.info(f"执行显式下拉刷新操作: (x={w//2}, y1={int(h*0.3)} -> y2={int(h*0.8)})")
@@ -162,10 +150,11 @@ class TeLaiDianCrawler(BaseCrawler):
logger.info(f"等待 {WAIT_AFTER_SCROLL} 秒确保位置校准和列表刷新完成...")
await asyncio.sleep(WAIT_AFTER_SCROLL)
max_to_crawl = 1 if FIRST_RUN_ONLY_ONE_STATION else MAX_STATIONS_COUNT
processed_count = 0
last_md5 = None
while processed_count < MAX_STATIONS_COUNT:
while processed_count < max_to_crawl:
# 1. 截图并分析
screenshot_path = take_screenshot(d, f"tld_list_{int(time.time())}.jpg")
@@ -193,7 +182,7 @@ class TeLaiDianCrawler(BaseCrawler):
continue
for station in stations:
if processed_count >= MAX_STATIONS_COUNT:
if processed_count >= max_to_crawl:
break
name = station.get("name")
@@ -209,7 +198,9 @@ class TeLaiDianCrawler(BaseCrawler):
logger.info(f"跳过已处理场站 (Redis): {name}")
continue
logger.info(f"处理场站: {name} (坐标: {point}, 距离: {station.get('distance')})")
current_idx = processed_count + 1
remaining = max_to_crawl - current_idx
logger.info(f"--- [进度: {current_idx}/{max_to_crawl}, 剩余: {remaining}] 处理场站: {name} (坐标: {point}, 距离: {station.get('distance')}) ---")
# 点击进入详情
d.click(point[0], point[1])

View File

@@ -188,6 +188,32 @@ def detect_price_info_container_cv(image_path):
return None
def detect_warm_popup_xczs_cv(image_path):
"""
使用 OCR 精准定位“温馨提示”弹窗中的“下次再说”按钮。
返回: [x1, y1, x2, y2] 归一化坐标,如果未找到则返回 None
"""
img = read_image(image_path)
if img is None:
return None
h, w = img.shape[:2]
keyword = '下次再说'
try:
reader = get_ocr_reader()
results = reader.read_text(img)
for (quad, text, prob) in results:
if keyword in text and prob >= 0.5:
res = reader.get_normalized_rect(quad, w, h)
print(f"[OCR识别] 找到“下次再说”: '{text}', 置信度: {prob:.4f}, 归一化坐标: {res}")
return res
except Exception as e:
print(f"OCR 识别发生异常: {e}")
return None
def setup_logger(name, log_file=None, clear_old_log=False):
"""
配置日志,支持同时输出到控制台和文件。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB