This commit is contained in:
HuangHai
2026-01-16 22:00:54 +08:00
parent aea318ce80
commit b79a148220
4 changed files with 32 additions and 66 deletions

View File

@@ -55,25 +55,12 @@ async def check_and_close_ad(d):
logger.info(f"检测到广告关闭按钮: ({x}, {y}) [Type: {ad_type}]")
if ad_type == "rabbit":
logger.info(">>> 检测到兔子广告。尝试使用图片识别关闭...")
logger.info(">>> 检测到兔子广告。使用模型返回的坐标关闭...")
try:
template_path_1 = os.path.join(BASE_DIR, "Template", "X1.jpg")
template_path_2 = os.path.join(BASE_DIR, "Template", "X2.jpg")
clicked = False
if d.image.click(template_path_1, timeout=3.0):
logger.info(">>> 成功通过图片识别关闭兔子广告 (X1 模板)。")
clicked = True
else:
logger.warning(">>> X1 模板未找到兔子广告关闭按钮,尝试 X2 模板。")
if d.image.click(template_path_2, timeout=3.0):
logger.info(">>> 成功通过图片识别关闭兔子广告 (X2 模板)。")
clicked = True
else:
logger.warning(">>> X2 模板也未找到兔子广告关闭按钮。")
if clicked:
await asyncio.sleep(1.5)
d.click(x, y)
await asyncio.sleep(1.5)
except Exception as ex:
logger.error(f">>> 图片识别关闭兔子广告异常: {ex}")
logger.error(f">>> 坐标点击兔子广告关闭按钮异常: {ex}")
if os.path.exists(screenshot_path): os.remove(screenshot_path)
return True

View File

@@ -107,36 +107,24 @@ class ReadImageKit:
if not os.path.exists(image_path):
return None
# 1. 优先使用图形学算法检测“新电兔AI”广告因为它的特征非常明显
cv_rabbit_point = detect_rabbit_ad_close(image_path, debug_dir=TEMP_IMAGE_DIR)
if cv_rabbit_point:
logger.info(f">>> 图形学算法精准捕捉到兔子广告关闭按钮: {cv_rabbit_point}")
# 注意Kit.py 的 detect_rabbit_ad_close 现在返回的是 0-1.0 归一化坐标
norm_point = cv_rabbit_point
ad_type = "rabbit"
# 转换坐标并返回
if not device_info:
device_info = cls._FALLBACK_DEVICE_INFO
w = device_info.get("displayWidth", FALLBACK_WIDTH)
h = device_info.get("displayHeight", FALLBACK_HEIGHT)
x = int(norm_point[0] * w)
y = int(norm_point[1] * h)
return {"x": x, "y": y, "ad_type": ad_type}
if not device_info:
device_info = cls._FALLBACK_DEVICE_INFO
primary_width = device_info.get("displayWidth") or device_info.get("width", FALLBACK_WIDTH)
primary_height = device_info.get("displayHeight") or device_info.get("height", FALLBACK_HEIGHT)
# 2. 如果图形学没找到,再请求大模型进行全量检测
with open(image_path, "rb") as image_file:
encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
img_input = {"url": f"data:image/jpeg;base64,{encoded_image}"}
# 构建提示词
prompt = (
"请仔细检查这张图片中是否存在**弹窗广告**或**悬浮广告**。\n"
"广告可能有以下几种形式:\n"
"1. **屏幕中央的大型弹窗广告**通常遮挡了页面内容内容多为优惠券、活动推广、或“免费停车”类提示例如现在可免费停车N小时了\n"
"2. **'新电兔AI'专属悬浮广告**(高频):一个卡通兔子头,带有'新电兔AI'字样关闭按钮是一个黑色圆圈内含白色X\n"
"2. **'新电兔AI'专属悬浮广告**(高频):通常出现在列表区域的左下方左侧为卡通兔子头像和“新电兔AI”文字关闭按钮是一个带 X 的圆形按钮;当右侧同一高度附近还有一个独立的浮动广告时,关闭按钮会出现在右侧浮动广告下方的圆形按钮处(一般为灰色圆圈,内部有 X可能部分覆盖在文字上\n"
"3. **底部的横幅广告**:带有明显的关闭按钮。\n\n"
"请返回关闭按钮的中心坐标。\n\n"
"如果同时存在左侧“新电兔AI”浮动区域和右侧浮动广告请优先返回右侧浮动广告下方圆形关闭按钮的坐标只有在右侧没有浮动广告时才返回左侧“新电兔AI”下方圆形关闭按钮的坐标。\n\n"
"请返回最主要的关闭按钮的中心坐标。\n\n"
"请以纯 JSON 格式输出:\n"
"{\n"
" \"has_ad\": true/false,\n"
@@ -164,37 +152,28 @@ class ReadImageKit:
raw_json = cls._extract_json(content)
result = json.loads(raw_json)
if result.get("has_ad") and result.get("close_point"):
if result.get("ad_type") == "rabbit":
logger.info("大模型找到了兔子广告,但 CV 没找到。")
# 如果大模型找到了但 CV 没找到,说明可能 CV 阈值没对上,此时采用固定坐标作为兜底
logger.info(">>> 采用兜底固定坐标策略 (94, 830)")
norm_point = [94, 830]
else:
norm_point = result["close_point"]
# 转换坐标
if len(norm_point) == 2:
if not device_info:
device_info = cls._FALLBACK_DEVICE_INFO
w = device_info.get("displayWidth", FALLBACK_WIDTH)
h = device_info.get("displayHeight", FALLBACK_HEIGHT)
x = int(norm_point[0] / 1000 * w)
y = int(norm_point[1] / 1000 * h)
return {
"x": x,
"y": y,
"ad_type": result.get("ad_type", "unknown")
}
return None
if result.get("has_ad") and result.get("close_point") and len(result.get("close_point")) == 2:
norm_point = result["close_point"]
x = int(norm_point[0] / 1000 * primary_width)
y = int(norm_point[1] / 1000 * primary_height)
return {
"x": x,
"y": y,
"ad_type": result.get("ad_type", "unknown")
}
except Exception as e:
logger.error(f"Failed to detect ad popup: {e}")
return None
logger.error(f"Failed to detect ad popup with VL model: {e}")
cv_rabbit_point = detect_rabbit_ad_close(image_path, debug_dir=TEMP_IMAGE_DIR)
if cv_rabbit_point:
logger.info(f">>> 图形学算法捕捉到兔子广告关闭按钮: {cv_rabbit_point}")
norm_point = cv_rabbit_point
x = int(norm_point[0] * primary_width)
y = int(norm_point[1] * primary_height)
return {"x": x, "y": y, "ad_type": "rabbit"}
return None
@staticmethod
def _to_minutes(t_str: str) -> int: