This commit is contained in:
HuangHai
2026-01-12 21:33:21 +08:00
parent 2051cb61c2
commit 4612ee2d81
18 changed files with 457 additions and 191 deletions

View File

@@ -23,7 +23,9 @@ from Apps.AiTeJiYiChong.Config.Setting import (
SCROLL_DISTANCE_RATIO,
MAX_SCROLLS, REDIS_STATION_EXPIRE,
WAIT_AFTER_SCROLL,
MAX_CRAWL_DISTANCE
MAX_CRAWL_DISTANCE,
SAFE_EXCLUDE_RATIO,
BOTTOM_SAFE_EXCLUDE_RATIO
)
logger = logging.getLogger("AiTeJiYiChongCrawler")
@@ -66,10 +68,14 @@ async def get_station_list(d, service, max_scrolls=MAX_SCROLLS):
image_uuid = str(uuid.uuid4())
screenshot_path = take_screenshot(d, image_uuid, save_dir=TEMP_IMAGE_DIR)
# 检查是否已经滚动到底部 (截图内容与上次一致)
current_md5 = Kit.get_file_md5(screenshot_path)
# 检查是否已经滚动到底部 (排除状态栏后,内容与上次一致)
current_md5 = Kit.get_image_content_md5(
screenshot_path,
top_ratio=SAFE_EXCLUDE_RATIO,
bottom_ratio=BOTTOM_SAFE_EXCLUDE_RATIO
)
if last_list_md5 and current_md5 == last_list_md5:
logger.info("检测到列表截图内容无变化,已到达底部或加载完成,提前结束。")
logger.info("检测到列表核心内容无变化,已到达底部或加载完成,提前结束。")
if os.path.exists(screenshot_path): os.remove(screenshot_path)
break
last_list_md5 = current_md5
@@ -123,41 +129,58 @@ async def get_station_list(d, service, max_scrolls=MAX_SCROLLS):
task_detail = asyncio.create_task(detail_task_wrapper(detail_path, station_name))
background_tasks.append(task_detail)
# 4. 寻找 timePrice.jpg 图标并进入三级页面
time_price_template = os.path.join(os.path.dirname(__file__), "BiaoShi", "timePrice.jpg")
coords = Kit.find_template_coords(detail_path, time_price_template)
# 4. 寻找分时价格入口并进入三级页面
# 优先使用 VL 模型精准识别,避免误判导致退回微信
res = await ReadImageKit.find_time_price_button_coordinate(detail_path, device_info=device_info)
pos = (res.get("uia_center_x"), res.get("uia_center_y")) if res.get("uia_center_x") else None
if coords:
cx, cy, conf = coords
logger.info(f"找到分时价格图标,进入三级页面...")
d.click(cx, cy)
entered_price_page = False
if pos and pos[0] is not None and pos[1] is not None:
ex, ey = pos
logger.info(f"找到 '分时价格' 按钮: ({ex}, {ey})")
# 记录点击前的页面特征,用于验证是否成功进入三级页面
before_click_md5 = Kit.get_image_content_md5(detail_path)
d.click(ex, ey)
await asyncio.sleep(2)
# 抓取三级页面图片
price_screenshots = []
price_detail_uuid = f"price_detail_{station_name}_{image_uuid}"
price_path = take_screenshot(d, price_detail_uuid, save_dir=TEMP_IMAGE_DIR)
price_screenshots.append(price_path)
# 检查页面是否真的变化了
after_click_path = take_screenshot(d, f"check_{detail_uuid}", save_dir=TEMP_IMAGE_DIR)
after_click_md5 = Kit.get_image_content_md5(after_click_path)
# 滑动处理
last_price_md5 = Kit.get_file_md5(price_path)
for scroll_idx in range(2):
d.swipe(w // 2, int(h * 0.7), w // 2, int(h * 0.3), duration=0.4)
await asyncio.sleep(1)
scroll_path = take_screenshot(d, f"price_scroll_{scroll_idx}_{station_name}", save_dir=TEMP_IMAGE_DIR)
curr_price_md5 = Kit.get_file_md5(scroll_path)
if curr_price_md5 == last_price_md5: break
price_screenshots.append(scroll_path)
last_price_md5 = curr_price_md5
if before_click_md5 != after_click_md5:
entered_price_page = True
# 抓取三级页面图片
price_screenshots = []
price_screenshots.append(after_click_path)
# 滑动处理
last_price_md5 = after_click_md5
for scroll_idx in range(2):
d.swipe(w // 2, int(h * 0.7), w // 2, int(h * 0.3), duration=0.4)
await asyncio.sleep(1)
scroll_path = take_screenshot(d, f"price_scroll_{scroll_idx}_{station_name}", save_dir=TEMP_IMAGE_DIR)
curr_price_md5 = Kit.get_image_content_md5(
scroll_path,
top_ratio=SAFE_EXCLUDE_RATIO,
bottom_ratio=BOTTOM_SAFE_EXCLUDE_RATIO
)
if curr_price_md5 == last_price_md5: break
price_screenshots.append(scroll_path)
last_price_md5 = curr_price_md5
# 后台处理价格图片
logger.info(f"已启动后台分析价格页: {station_name},共 {len(price_screenshots)} 张图")
task_price = asyncio.create_task(analyze_prices_background(service, station_name, price_screenshots))
background_tasks.append(task_price)
# 立即返回
d.press("back")
await asyncio.sleep(0.5)
# 后台处理价格图片
logger.info(f"已启动后台分析价格页: {station_name},共 {len(price_screenshots)} 张图")
task_price = asyncio.create_task(analyze_prices_background(service, station_name, price_screenshots))
background_tasks.append(task_price)
# 立即返回
d.press("back")
await asyncio.sleep(0.5)
else:
logger.warning(f"点击 '{station_name}' 的 '分时价格' 按钮后页面无明显变化,跳过三级页面处理。")
if os.path.exists(after_click_path): os.remove(after_click_path)
else:
logger.warning(f"场站 {station_name} 未找到分时价格入口。")