'commit'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user