'commit'
This commit is contained in:
@@ -13,7 +13,7 @@ DEBUG_BOX_THICKNESS = 3
|
||||
# 等待时间配置 (秒)
|
||||
WAIT_DETAIL_PAGE_LOAD = 3.5
|
||||
WAIT_BACK_TO_LIST = 1.5
|
||||
WAIT_AFTER_SCROLL = 2.5
|
||||
WAIT_AFTER_SCROLL = 5.0
|
||||
|
||||
# 坐标计算与安全防护
|
||||
SAFE_EXCLUDE_RATIO = 0.58 # 增加比例,确保完全跳过顶部的“充电礼”红色Banner和“PLUS会员/我的卡券”图标区
|
||||
|
||||
@@ -89,8 +89,8 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
logger.info(f"执行显式下拉刷新操作: (x={w//2}, y1={int(h*0.3)} -> y2={int(h*0.8)})")
|
||||
d.swipe(w // 2, int(h * 0.3), w // 2, int(h * 0.8), duration=0.5)
|
||||
|
||||
logger.info("等待 2.5 秒确保位置校准和列表刷新完成...")
|
||||
await asyncio.sleep(2.5)
|
||||
logger.info(f"等待 {WAIT_AFTER_SCROLL} 秒确保位置校准和列表刷新完成...")
|
||||
await asyncio.sleep(WAIT_AFTER_SCROLL)
|
||||
|
||||
processed_count = 0
|
||||
last_md5 = None
|
||||
@@ -226,30 +226,58 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
|
||||
template_jgxx = os.path.join(os.path.dirname(__file__), "Template", "jgxx.jpg")
|
||||
entrance_point = None
|
||||
max_search_rounds = 5
|
||||
|
||||
if os.path.exists(template_jgxx):
|
||||
logger.info(f"[详情页] 使用模板匹配价格入口: {template_jgxx},第 1 轮(只匹配一次)")
|
||||
try:
|
||||
match_res = d.image.match(template_jgxx)
|
||||
except Exception as e:
|
||||
match_res = None
|
||||
logger.error(f"[详情页] 模板匹配价格入口失败: {e}")
|
||||
for round_idx in range(max_search_rounds):
|
||||
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 match_res:
|
||||
logger.info(f"[详情页] 第 1 轮模板匹配返回结果: {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 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 not entrance_point:
|
||||
try:
|
||||
vlm_res = await self.read_image_kit.find_price_entrance_vlm(search_screen_path)
|
||||
except Exception as e:
|
||||
vlm_res = {}
|
||||
logger.error(f"[详情页] VLM 寻找价格入口失败: {e}")
|
||||
|
||||
point = vlm_res.get("point") if isinstance(vlm_res, dict) else None
|
||||
if vlm_res.get("found") and point and len(point) >= 2:
|
||||
vx = int(point[0] * w / 1000)
|
||||
vy = int(point[1] * h / 1000)
|
||||
if vy < int(h * SAFE_EXCLUDE_RATIO):
|
||||
vy = int(h * SAFE_EXCLUDE_RATIO)
|
||||
if vy > int(h * (1 - BOTTOM_SAFE_EXCLUDE_RATIO)):
|
||||
vy = int(h * (1 - BOTTOM_SAFE_EXCLUDE_RATIO))
|
||||
entrance_point = (vx, vy)
|
||||
logger.info(f"[详情页] VLM 成功找到价格入口: {entrance_point},原因: {vlm_res.get('reason')}")
|
||||
|
||||
if entrance_point:
|
||||
break
|
||||
|
||||
logger.info("[详情页] 本轮未找到价格入口,向上滑动继续搜索...")
|
||||
d.swipe_ext("up", scale=DETAIL_SCROLL_DISTANCE_RATIO)
|
||||
await asyncio.sleep(WAIT_AFTER_SCROLL)
|
||||
|
||||
if not entrance_point:
|
||||
logger.error("[详情页] 未能通过 jgxx.jpg 找到价格入口,本次流程直接中止,需人工检查详情页布局或滚动距离。")
|
||||
raise RuntimeError("TeLaiDian: 价格入口模板匹配失败")
|
||||
logger.error(f"[详情页] 连续 {max_search_rounds} 轮滚动后仍未找到价格入口,本次流程直接中止。")
|
||||
raise RuntimeError("TeLaiDian: 价格入口多轮搜索失败")
|
||||
|
||||
before_price_path = take_screenshot(d, f"tld_detail_price_before_{int(time.time())}.jpg")
|
||||
before_md5 = get_image_content_md5(
|
||||
@@ -315,8 +343,15 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
logger.error("[电价页] 多轮尝试后页面仍未变化,疑似点击未生效或入口不可用。")
|
||||
raise RuntimeError("TeLaiDian: 价格入口点击后页面未变化")
|
||||
|
||||
logger.info("[电价页] 已成功进入电价详情页,调试模式下在此主动停止,供人工检查页面内容。")
|
||||
raise RuntimeError("TeLaiDian: 调试模式已在电价页入口处停止")
|
||||
logger.info("[电价页] 已成功进入电价详情页,等待小程序自动滚动定位完成 (4秒)...")
|
||||
await asyncio.sleep(4.0)
|
||||
logger.info("[电价页] 开始执行多次向下滑动,让上方时段露出")
|
||||
for idx in range(3):
|
||||
logger.info(f"[电价页] 调试模式第 {idx+1} 次向下滑动(d.swipe_ext(\"down\", scale=0.9))")
|
||||
d.swipe_ext("down", scale=0.9)
|
||||
await asyncio.sleep(1.0)
|
||||
logger.info("[电价页] 调试模式滑动完成,在此主动停止,供人工检查页面内容。")
|
||||
raise RuntimeError("TeLaiDian: 调试模式已在电价页滑动后停止")
|
||||
|
||||
# 4. 进入分时电价页面后的处理
|
||||
try:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user