From 4612ee2d8141c47b533120420a224aba1211014f Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Mon, 12 Jan 2026 21:33:21 +0800 Subject: [PATCH] 'commit' --- Apps/AiTeJiYiChong/Crawler.py | 91 +++++---- Apps/AiTeJiYiChong/Kit.py | 23 +++ Apps/AiTeJiYiChong/ReadImageKit.py | 107 ++++++++++- Apps/AiTeJiYiChong/Service.py | 65 ++++++- .../__pycache__/Crawler.cpython-310.pyc | Bin 7340 -> 7492 bytes .../__pycache__/Kit.cpython-310.pyc | Bin 10697 -> 11224 bytes .../__pycache__/ReadImageKit.cpython-310.pyc | Bin 10898 -> 14418 bytes .../__pycache__/Service.cpython-310.pyc | Bin 6506 -> 7340 bytes Apps/XinDianTu/Crawler.py | 75 ++++++-- Apps/XinDianTu/Kit.py | 22 +++ Apps/XinDianTu/Opener.py | 53 ++---- Apps/XinDianTu/ReadImageKit.py | 35 +++- Apps/XinDianTu/Service.py | 177 ++++++++++-------- .../__pycache__/Crawler.cpython-310.pyc | Bin 15040 -> 9743 bytes .../XinDianTu/__pycache__/Kit.cpython-310.pyc | Bin 19428 -> 21007 bytes .../__pycache__/Opener.cpython-310.pyc | Bin 5629 -> 5859 bytes .../__pycache__/ReadImageKit.cpython-310.pyc | Bin 34817 -> 32109 bytes .../__pycache__/Service.cpython-310.pyc | Bin 10672 -> 11824 bytes 18 files changed, 457 insertions(+), 191 deletions(-) diff --git a/Apps/AiTeJiYiChong/Crawler.py b/Apps/AiTeJiYiChong/Crawler.py index f2a94db..5c6d17e 100644 --- a/Apps/AiTeJiYiChong/Crawler.py +++ b/Apps/AiTeJiYiChong/Crawler.py @@ -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} 未找到分时价格入口。") diff --git a/Apps/AiTeJiYiChong/Kit.py b/Apps/AiTeJiYiChong/Kit.py index 24f7a87..e4e9f19 100644 --- a/Apps/AiTeJiYiChong/Kit.py +++ b/Apps/AiTeJiYiChong/Kit.py @@ -36,6 +36,29 @@ def get_file_md5(file_path): return hash_md5.hexdigest() +def get_image_content_md5(file_path, top_ratio=0.1, bottom_ratio=0.1): + """ + 计算图片核心内容的 MD5 值(排除状态栏和导航栏) + """ + img = read_image(file_path) + if img is None: + return None + + h, w = img.shape[:2] + top = int(h * top_ratio) + bottom = int(h * (1 - bottom_ratio)) + + # 裁剪中间部分 + content = img[top:bottom, :] + + # 将图片数据转换为字节流计算 MD5 + # 使用 cv2.imencode 转为 jpg 字节流,避免原始 numpy 数组可能的细微差异(虽然通常没问题) + success, encoded_img = cv2.imencode(".jpg", content) + if success: + return hashlib.md5(encoded_img.tobytes()).hexdigest() + return hashlib.md5(content.tobytes()).hexdigest() + + def read_image(path): """读取图片,支持中文路径""" if not path or not os.path.exists(path): diff --git a/Apps/AiTeJiYiChong/ReadImageKit.py b/Apps/AiTeJiYiChong/ReadImageKit.py index f57d598..2c5c735 100644 --- a/Apps/AiTeJiYiChong/ReadImageKit.py +++ b/Apps/AiTeJiYiChong/ReadImageKit.py @@ -21,6 +21,16 @@ from Apps.AiTeJiYiChong import Kit logger = logging.getLogger(__name__) +# 场站过滤黑名单 +STATION_EXCLUDED_TITLES = { + "推荐站点", "距离优先", "价格最低", "空闲较多", "筛选", "地图", "列表", + "我的订单", "收藏站点", "优惠券", "站内搜索" +} + +STATION_BLACKLIST_KEYWORDS = [ + "广告", "点击进入", "立即参与", "咨询电话", "活动详情", "导航到", "停车说明" +] + class ReadImageKit: _client = AsyncOpenAI( @@ -42,14 +52,17 @@ class ReadImageKit: " - 场站名称 (station_name);\n" " - 距离信息 (distance, 例如 '2.82km' 或 '90m'),通常位于卡片右侧蓝色胶囊区域内;\n" " - 金额/电费 (price,例如 '1.2500'),通常以红色字体显示;\n" - " - 充电枪信息 (piles,包含'快'或'慢'的类型、总枪数和空闲枪数,例如 '快 4/4')。\n" + " - **充电枪信息 (piles)**: 必须包含类型('快充'、'慢充'、'超充')、总枪数和空闲枪数。识别规则如下:\n" + " - 如果明确标有'快'、'慢'或'超',则对应为'快充'、'慢充'、'超充'。\n" + " - 如果图中只显示数字(如 '34/42')而没有明确标明类型,请统一识别为 `type: \"慢充\"`。\n" + " - 必须以 JSON 对象列表形式输出,例如:`[{\"type\": \"快充\", \"free\": 4, \"total\": 4}, {\"type\": \"慢充\", \"free\": 1, \"total\": 2}]`。\n" "3. 如果绿色方框内缺少上述任何一项要素,说明它不是真正的场站卡片,请直接跳过。\n" "\n" "JSON对象字段要求:\n" "1. b_use: 状态标识(1或0)。如果场站名称为灰色或带有“暂停使用”等标签,则为0,否则为1。\n" "2. station_name: 场站名称;\n" "3. price: 一度电的价格(数字,如 1.2500);\n" - "4. piles: 充电枪列表 [{type: '快', free: 4, total: 4}];\n" + "4. piles: 充电枪列表 [{type: '快'|'慢'|'超', free: 4, total: 4}];\n" "5. parking: 停车费用描述(通常在蓝色'P'图标后,例如 '免费停车三小时');\n" "6. distance: 距离信息字符串(例如 '2.82km' 或 '90m');\n" "7. bounds: {x1,y1,x2,y2} 区域像素坐标(0-1000);\n" @@ -303,15 +316,27 @@ class ReadImageKit: img_input = {"url": f"data:image/jpeg;base64,{encoded}"} prompt = ( - "请识别图片中的充电站卡片信息,并以 JSON 格式输出:\n" + "你是一个专业的充电桩信息提取助手。请识别图片中充电站卡片的核心信息。\n" + "注意以下识别规则:\n" + "1. **场站名称 (station_name)**: 场站名称通常位于卡片的第一行(左上角),字体最大且加粗。严禁提取'距离优先'、'空闲较多'、'价格最低'等筛选标签。严禁将卡片中下部的描述信息(如'导航到...'、'停车说明...'、'距您...'等)识别为名称。名称通常是一个具体的地点或品牌名。\n" + "2. **价格 (price)**: 提取数字部分,通常以'元/度'结尾,字体颜色通常为红色或加粗。\n" + "3. **桩数 (piles)**: 识别所有类型的充电桩。请提取'快'、'慢'或'超'字样及其对应的'空闲/总数'(如 '快 4/4')。\n" + " - 如果明确标有'快'、'慢'或'超',则对应为'快充'、'慢充'、'超充'。\n" + " - 如果图中只显示数字(如 '34/42')而没有明确标明类型,请统一识别为 `type: \"慢充\"`。\n" + " - 必须以 JSON 对象列表形式输出,例如:`[{\"type\": \"快充\", \"free\": 4, \"total\": 4}]`。\n" + "4. **距离 (distance)**: 提取如 '2.5km' 格式,通常在蓝色胶囊背景内。\n" + "5. **停车 (parking)**: 简要描述停车收费信息,通常在蓝色'P'图标后。\n\n" + "请以 JSON 格式输出:\n" "{\n" " \"station_name\": \"场站名称\",\n" - " \"price\": \"价格(数字)\",\n" - " \"piles\": \"空闲/总数(如 4/4)\",\n" - " \"distance\": \"距离(如 2.5km)\",\n" - " \"parking\": \"停车描述\"\n" + " \"price\": \"价格\",\n" + " \"piles\": [\n" + " {\"type\": \"快\", \"free\": 4, \"total\": 4}\n" + " ],\n" + " \"distance\": \"距离\",\n" + " \"parking\": \"停车信息\"\n" "}\n" - "只输出 JSON,不要有其他文字。" + "只输出 JSON,不要有任何解释文字。" ) try: @@ -410,6 +435,20 @@ class ReadImageKit: except: pass + # 3. 后置过滤 + if final_stations: + processed_excluded_titles = {str(x).replace(" ", "").strip() for x in STATION_EXCLUDED_TITLES} + filtered = [] + for item in final_stations: + name = item.get("station_name") + normalized_name = str(name).replace(" ", "").strip() + if normalized_name in processed_excluded_titles: + continue + if any(kw in normalized_name for kw in STATION_BLACKLIST_KEYWORDS): + continue + filtered.append(item) + final_stations = filtered + return final_stations @classmethod @@ -460,3 +499,55 @@ class ReadImageKit: except Exception as e: logger.error(f"Error calling VL model: {e}") return [] + + @classmethod + async def find_time_price_button_coordinate(cls, image_path: str, device_info=None): + """ + 使用 VL 模型定位详情页中的 '分时价格' 按钮 + """ + if not os.path.exists(image_path): + return {} + + with open(image_path, "rb") as f: + encoded = base64.b64encode(f.read()).decode("utf-8") + img_input = {"url": f"data:image/jpeg;base64,{encoded}"} + + prompt = ( + "请识别图片中 '分时价格' 或 '查看分时电价' 按钮的中心坐标。\n" + "该按钮通常位于充电站详情页,可能是一个带有价格图标或箭头的小型矩形区域。\n" + "请直接以 JSON 格式输出该按钮的中心点坐标:\n" + "{\"uia_center_x\": 500, \"uia_center_y\": 500}\n" + "注意:坐标系为 0-1000 归一化坐标,其中 (0,0) 为左上角,(1000,1000) 为右下角。\n" + "只输出 JSON,不要有任何解释文字。" + ) + + try: + resp = await cls._client.chat.completions.create( + model=VL_MODEL_NAME, + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": prompt}, + {"type": "image_url", "image_url": img_input} + ] + } + ], + max_tokens=100, + temperature=0.01 + ) + content = resp.choices[0].message.content.strip() + raw = cls._extract_json(content) + res = json.loads(raw) + + # 转换 0-1000 坐标到实际像素坐标 + if res.get("uia_center_x") is not None and device_info: + w = device_info.get("width", FALLBACK_WIDTH) + h = device_info.get("height", FALLBACK_HEIGHT) + res["uia_center_x"] = int(res["uia_center_x"] * w / 1000) + res["uia_center_y"] = int(res["uia_center_y"] * h / 1000) + + return res + except Exception as e: + logger.error(f"VL find_time_price_button_coordinate error: {e}") + return {} diff --git a/Apps/AiTeJiYiChong/Service.py b/Apps/AiTeJiYiChong/Service.py index 6253d01..733a9c9 100644 --- a/Apps/AiTeJiYiChong/Service.py +++ b/Apps/AiTeJiYiChong/Service.py @@ -36,6 +36,25 @@ class AiTeJiYiChongService: def get_hash(self, s: str) -> str: return hashlib.md5(s.encode('utf-8')).hexdigest() + def _to_float(self, value) -> float: + """ + 从字符串中提取浮点数,过滤掉非数字字符 + """ + if value is None: + return 0.0 + if isinstance(value, (int, float)): + return float(value) + + import re + try: + # 提取第一个匹配的数字部分(包含小数点) + match = re.search(r"[-+]?\d*\.?\d+", str(value)) + if match: + return float(match.group()) + return 0.0 + except: + return 0.0 + async def init_db(self): await self.db.init_db() @@ -163,10 +182,23 @@ class AiTeJiYiChongService: # 处理 piles 字段 piles_data = station.get("piles") total, free = 0, 0 + standardized_piles = [] if isinstance(piles_data, list): - for p in piles_data: - total += int(p.get("total", 0)) - free += int(p.get("free", 0)) + for idx, p in enumerate(piles_data): + try: + t = int(p.get("total", 0)) + f = int(p.get("free", 0)) + total += t + free += f + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": p.get("type", "未知"), + "power": "", + "status_text": f"空闲{f}/总{t}", + "remark": "列表页VL" + }) + except: + pass await self.station_status_model.save( session=session, @@ -174,8 +206,8 @@ class AiTeJiYiChongService: station_hash=station_hash, total_piles=total, free_piles=free, - piles_detail_json=piles_data, - current_price=float(station.get("price", 0)) if station.get("price") else 0.0, + piles_detail_json=standardized_piles if standardized_piles else None, + current_price=self._to_float(station.get("price")), parking_info=station.get("parking", ""), distance=station.get("distance", ""), valid_start_time=now @@ -234,10 +266,23 @@ class AiTeJiYiChongService: # 处理 piles 字段 piles_data = station.get("piles") total, free = 0, 0 + standardized_piles = [] if isinstance(piles_data, list): - for p in piles_data: - total += int(p.get("total", 0)) - free += int(p.get("free", 0)) + for idx, p in enumerate(piles_data): + try: + t = int(p.get("total", 0)) + f = int(p.get("free", 0)) + total += t + free += f + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": p.get("type", "未知"), + "power": "", + "status_text": f"空闲{f}/总{t}", + "remark": "列表页VL" + }) + except: + pass await self.station_status_model.save( session=session, @@ -245,8 +290,8 @@ class AiTeJiYiChongService: station_hash=station_hash, total_piles=total, free_piles=free, - piles_detail_json=piles_data, - current_price=float(station.get("price", 0)) if station.get("price") else 0.0, + piles_detail_json=standardized_piles if standardized_piles else None, + current_price=self._to_float(station.get("price")), parking_info=station.get("parking", ""), distance=station.get("distance", ""), valid_start_time=now diff --git a/Apps/AiTeJiYiChong/__pycache__/Crawler.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/Crawler.cpython-310.pyc index dd733f6ceb8d5622ea6b2ed8b2c0914a36224768..b2a2c11e892836ff38a7e47d7dda41cb7cc0182d 100644 GIT binary patch delta 2433 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 ja|kK~557fa5P39Hg&v-@IiSnpbI z*TG3!pcLAwDi!oqltT|aRjT?UA@^2}v{G+9R_}nQ$|aXxkb3BWc4jTgk5o(kc6Mgo zo4503=C_l-%q5(7T&jcLzHbe4-@)sN4sz%E;Q14h(RjH|Ng6RD4$l_axJ-c;09+T0v?zI*c}>9i-=sZN?U3D@a=mGFK;e-g@|Xu=;7ZmxM)7Uma2S z?S|dGB4`%#f>0KN*fqpK5)z}Dp_)Z4Py2W@k|slZSLDa^1_9&Wp`n#hettcfVa#FO zuC{90`EK90o29rE?RcRN+?0q}q_*xDRD?Ze*|aF@#~?Cd03e508_GKYB1kJ9+r{_9 zlH7_mlKs3A?INT6W^{q<=6^;j$qab85kLz`5Q&5cJIH_UZmC|Cc9Ovq=;Z`!g-31A zc9bxZ2$}Y>BN{Bz^$e4-F@C>sFy$Y_KSMox(f9Jt*NLmf5qOdmnd0-YL2|fyF}4tp zHv(W#nmt-9sk&wAXH~sG^|LbZcgTYge)kTsBm7~aoecA~rpamlTVDb_8v=-Wx1g1% z2zihhb`aIUn%bhY#L_57EYo&Nnob$!P=pzE&2T?*{tA6*a-v%WLX5pVl#+Y#A}EgVh$j07I2k$wWN6k zwt(7`2)s77SXXzbj-5hLL7YasiBJ(|5E^0$p(6|gMJyxo{+(Y-wvvzeSIPZkrFu7c zN(%cQHOyb`ERI^>CI>f~;IZ)!F0pHh8z`gE2YCGO$jEGdx3jaE!MnK#*S3MJ#T*{% z$|NvRG7%xIV!Euz)vk5IxafL?jPNbpH+QdrSp--G{%a!0^mB*;dmA^1A+SBz1;9SY zF}nygIJy1Z|Ey2D8~~RGST-GSEj-&ZPLA_yJxfp=4|;mYIB!jTnZ~tpKm^=9@E>_5 zM($CJjv@B`(?R|(<^nGHfTz+cbx&!m)p*H)$`keKvZdvfpt@?U*AK0@jxESJKGyq&@wmdDX}-s0<`;5AU-c#& z%VA1RiCKAH2el#-m796y#-$7g4AGmGlnvFX{Vj1pUN%C-U9=BVBV8Nm&*j;&DU zh)|JgHk;+u?IQzw@DoD1Q(6;IYL}t6FkEvr|gx= zo(dnXNH9XFYS5)}zBUX=f!)MCg9Ue0L|qs(nr%}{Y0zxF;4rt=h0uFXw%!?hJ;|@^ zxIr}D(RXy{5-Q$9Tt-|0C=#t`x~JmN*g9(80*C;u2!6e9lnDNF-$SyO|J1+G{0^GW zBd#Jo;RA9P`M!EwK0zja1&thFIFtR!14Gd7t3Y;M-U`Fk$>$+$waMdOe?6q7v{suq zQ@H9Dzdumi>sL<#-@6fh&5WYt568nO6%Z>349a5uxcFi)LHhYOgWD33#z=E45o?e( INyCZMzn-Jl2mk;8 diff --git a/Apps/AiTeJiYiChong/__pycache__/ReadImageKit.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/ReadImageKit.cpython-310.pyc index 46ca2e7de21d73c400aeaaea5b6f5d64d7747d0c..100e953e9d18fc94d060f205f9202b4f2b9e6e33 100644 GIT binary patch delta 6037 zcmcgQYiv_jn)h74t{umDze6yA;)dyjDbSskVPJT5Cev)7g_h!J$8~*g5(mFHzTtU2 z4un7ggg`GXuh6xb@-7V}w1gxOY39#rq?J~ykw&^&X;&Iw+mTj6yV@V4)h@f=cWx3= z%I?oK%Evk1ch2`Z=X{U*$-Dm$b43da9UT08|0V`M{_8WYdh+*Ye&9`#kkjiFInfj< z47nBwJY3S5!&Tm@aJ9FZ;jN*XaILqN zaFRV$C)KBkcR?p7+I~yC4IP{)Tp`|tKj%cd=s3cOj$YpD7RffQsbCtkIrEqMNz+?F zd2Inqx}5-Ww=d{N`?9BpbN8=w+X0c8JfH1N>HTAjob5l8yLcr3)fIj4({3w}_5O4D z^bLb{>PCL>G%&~=erWKzIX->vUjA{f{>4SMICtmLbk6{zWhNeEQCbAmkoyZC-mchyOv$l+sEwGM<(X5~g?ANayb|cjdu3fc!mFLOiz@K{#12+5lF!(Ps zc1It&l|BDB_r-Yj)4Teeb5ACXJu6}L3S6G=Ihnne&JGWNZMpPU+0-!{d_AFme&WgG z$^6KJ+{E8x#(MH2NA>>OnXz&ANAmudwA$SWy6}x3jsC6W3@K2UW(w*x`o68zVy%G7 zKr7T+&P^nsK5>3ciqv%BM-2uVY1IIxxGsZKDfai+Ilpq>xUHgz0n3 z3w(0a7Y;_cWhs78?I<2xy$aWwezZcQE0HO#Z!*!J;P`a}Z_Hv1R!peb*B+LSjy9Kk zL#)k6|B*Ufx`3=xZDp_h@MnlvKf9}mXk_2>S_o@G{_w}5f9)4)u&gbKD$rU0ZS-e2 z#Lb|C!5IFCOTW#O{!Uj$5&+b8z%@xzpk* z0>(Fa&5Q?0i_}{+%dPJLitbSVsphiblXdFh+CPgeG%_|8&x zR5_>fCK&%35k6IFc+)JwQ2m#s8`OVosE}mDcOyVG=pF=yhB(@b;2;2SyMp7b2oeZ> zgCL23ZR~-OW)&sb9}Im@adp?iM&3-+p@qAX0Rk&$e;5cceE%N);(q~fh{#+QN%0Do zCUH9kRN16(BHzmo)g*{)PFWO^vZjHWvWccNN${dsv?%-~?lK=F3DXWvBxcUc^_mD5 z5nkou%k~n&;lG{mCt4E=%mv zL3aY^Zm~e#c$CVXAAvZM8M~DkQ!`^1A#u#az4T2Z?q!Eg>qDRE$8Tl_PCyWY&||QJ zI0jNMl(9I8If+RJ4%yV0KGkb%hb@lm=#A`=q0Ge9Omggmu{(eLh~9tU$>c@HtIckR zwZr4c;Phbb`d#t`Pq!c^xV9>$PjbM z5OSd>cW1!JlMtA5cOK7i)9)TNbOOI*#!gK4-avN@4dtiqGIu0Lj7aa9%Vf>X&5XT1 zFPY8aK&kBE8#n`bm=tECz2PX3Y77jQ%$=m(_W&%$lN`PaX&y3@t{%z_oP@HhmK~yOZ;hs9{ZZpa-&?k=f>7K2Q{{+RW*^Akli@T(hYM`p|K` z?_0e3<7Z*J$2hj-*`5gy2Z{7qDrR{&$r3R>nIF3UztVBzN9c4zWOAx+Iz0g|!6?b} zM_2U8q5NZ2KQ?YSV&-l2-vwg~r{LyQ=tAR)x?dK9@IE5nIW$&ptZ061SJ>l*iVb+q z9i2XWBd=bDGs*XUt6xeU&-b3pUKoM$5&6Ex-X6Poa1;D=S1{7S9$fCLo;CNz7w}Wjw>Kzv`u2p}5~WeP z+TB!5G1Jm^1Rd&sEnSdgl}i-oF$B92Py|@<)8|rg9pYY)ifJbjf&d^XV?NeMyJnLj zfv6~nUVAXy;R{A$-Lhtl(P%g(Yi1~LVwk0qP%%;e-tVPnU>>~R35poY7|iB7pFRh;I!N<< z3Zx=^_d2<$K)EiccwdI^rT*vhi88NV%VM-8_WGJxyxkccKXNx+_AfgULIKdY#v>MKHfmjcM z3}-I@dL_E}GI$TFyaIOK&*%-8p)Q1?%*76>0euJNEs<@h0wY+$a2Q9?a$cgSa*5>ogNI zJDQD3v5-F?QH*v?@QmRxc8t**v*Sz&P~$BRG868<9F@7 zNxVgoC=L5V5b{M<=^9!#AS2DbrbCKAw@BAcpn_(=@jaCLRA0-j9xeH#pfuO-HkH%P%$UP*SY^=8WcP6mZ0zW9>HQIE|ZHmh?$s8 zW>N{`V%`afwV5=U0Lw$7CBoBEbFs2%XA+DMEfH1uD4F^pjV)ipa65qdO z^BL8~^HmJH2QR2%njG^!DBMGS|JzpuuP}E!>v7$4fuTyh=cyvUQ~%(J+2}AVXsT7$ zy}Ufh$}If8K(UZ8RDJ}bna~!1`_dT|jl0M6!&<|*yIAkAPe=3sjFd{<5O(ia0YzCk5TKlz}T@UJ@wzq67sO4B0E0`DodU*jV& z&9t?p)p)F|fV>6UG+U=X-WdvhOx-Z^+Wf(2r!2=bTPWJmfzN*zqD_H4E9h1AY*UwC zD_tLp#hcd$w@bea?hJ11jKU%eDViPbVk_)|GIa{(MmafxqpuOL8ugj-Y{c%cuqGVE hFJNoo-g5D!YIs>ysQ^`8IjJ@|%?@5L36@gJ{{TI9CN=;7 delta 2585 zcma)8Yi!%r73SqbZ^^PO*_P#poHp}>&hg^fP2w0y{73>XhLbvV*K%zcR+pCPlA>}+ zJC9LQTPJP0CBqzU`;o+j)B;1-bZ9f9|AuD31{B!OVL&nd8PHX318f+upWA-y9!jx| z3(tX?+LQfSm!1(bh*5&oZl$M& z#NLw(4&dMw1_#$zu@9rOOfK{QQkcsjSD4Y|f|7IM=)Ha6f?`QVo=C5#7FBVlR4Wg5 zyB~ozj?vfrlk-pZgTW;3!zm@a$l?s{z9Ot4u|wJ6dT_7Db>c1>H0ylEU1vY{Zz}v_ z>=X5?SHJw}$6If||Hb{<)@vVTzgbc>#r(%_uGg<$t^efiK>hyRfvsylAK1G3j&t8P zkhuQECqJtH;`J;jvLizy1G&wDe;sY|!Bc{-on}PZorTymdfvGeyNBY=Y|FXc1`WD2 z1ve@w7cC;^Eos>_iqo5aXz6DMo&*hAa*<9RF%L_YA?a#y#Zt`kP9kw*Y!qy{Zx3TK z0#3m`$B}W64*`rlWE-x$puDuGTlVIk6Cb0;hd{p{08vn@bTVC`MAW>J<6LCANFm3Z zUnfTgC%|SBz>9%gbn(&b0^^#jzl`N0x13~Zt^%o%423ze-I?aL6Y&_;<$@#zc84jr z99?af)8&g~FK~Up@uop6S0Hk+ppYY!$wkRgPz2SYrI1xwqe+sT2(FJP=89$!bjbNU zH5}eGgHB(22CZ!#ZjT7DICb$$*5$2BC56PDh0KueyObi&IX}#7_`DpCIfLDwwY~_k zc(u4_kYOpb??XMJ=vy3Gy`)q_+%-vwioXwFwo2&XUUqj|MEUp^B zLJc9tvkX>4Hmad&82f6d%v+H)rYsbgvd`u)pJt|+7jKvSwjcY`OgUil)u^i%nsaUHmEsbY@wR8 zL$qVq4wFyqFioZZ3pPrPrv+f>IJqODMzjLMq(A* zmSpTmhFL=%MZ0)Rbeo|WKVn0(-?1t1)OC`&_EkIVFeK@vpW05po$6a)AdMlMKj6*i zLwy^AJ2p7zcK(3vqxG(H<&5*UZ#}tp>&^%DJ0E4w$QWzN>8bhbS0BDnzjim2Z9W7x zsdI4f=uwxOKRN00M9I?=MM>{KKVYf!0M>q`jl$Ni-mTwxui>J8qxR)nZ)ROq#h2N! ztWzI6h}N9meKTyX)A?wms}iLh#8jRbB`GfxY)XrCCrc`nd~%ZNT>k}`6xCvZKoIhZ zN9B#;szNLhfff&)T`s>mEC%wc)|8?kTSUj zSqLTB$}fol?<3_`U5?fr7hPzS-Q88^FZ(-Z_R_gCp?a~eMua%xQA~)T5dFqkAL7}F z5I}p_B-h1-P>hYUaTGuyF2N=c`~v?8`Ln2#<=M+w=iX3u^VaY>a{j$16#x1HLSBOL zH4BJ7a;U>iNhc;|XD277PD#_ppPiXHF3rrHI8E1Na#vyTHw(-ET~R{2D$36wEDravR_d1vlck$?J->WMG$ry6aWC zD`4R*DqJPrO+mg7(is4Yf*a0jvS~JYlGlNL1K<|G2Efj$B|Q;tOYeFD!93!8`qbg) z5{MmZM;@EYx1=!~rrOCSU(t+iQ*t%e;+P>{`N&oIN_IzTZR5JHXsLv?hQJ+_*mJHetPLdm> zSLQ5rq!98p_)!788+B(e+hcJ94-%{{{8I BfT92Z diff --git a/Apps/AiTeJiYiChong/__pycache__/Service.cpython-310.pyc b/Apps/AiTeJiYiChong/__pycache__/Service.cpython-310.pyc index 5a6a5d565aa8729e3e61b83033b712bb3b5ebf21..5566fa3271900e0ec1019f0d2f4f54507a53af81 100644 GIT binary patch delta 2687 zcmb`JU2GiH702h!&dlzPcV}n6*LJXCJ{oOe@>TPZG)YO5HV{IZ;E*)NiCKKdn+f*r z`p&q3b+;Q~3sSZDP_IgmNXV{45h+OvM2JABqNqjU4aDO-fRGZK@Pb5@zVxN%TyN}9 ziHAy^(fsF}d(S;{cjo-=-EY>OUuRY0aZ`cg?tfA@+4qk1IU%ozugJ=V;e@$GLv z`u*2eUYfo9`t0%F-Z=9bv_SBD{6dDEWymKFM&LGOJ$dhn13w+2%ZFBit|*2B)Aihn z=a(uYP7rFi6+h5N$EqbiP?-}Lo>O8YhgcrQ26~xQCu>EGrKI=k(%7WK?veI*$%m*k z*z=OX*66Tb9hSM4f$J4OBAP}l5+M;)CANyTAxXixnqG= zDUCa~&2)`e9lxJ2QI0bUUpW52zr*EyC+6ZCqMz1v9@?rL_(1eoFEq+ZJ>kcB%(tLk z-|`bYHcg;&&dBp-{wiESd(_N)M-*rwf$JzPxClWJ)qR%+~R4tTRhQB(m1!N zl~-O>&Zu%U;MtN`^7N|;P4g7=Xo%(MhTb9sN`7MeR>4nvFjFhM(;@R(>g+#_B-)KqI?#!KuO=)=Md z!ZmQ*N;!y7*Go%^&zZMRSj^au<(`CW3?~~z+qqm?%!)aCX+u^eu5hdu1=qiMq9ill zuhbywdezY?1KQc0m`xjVJwJ##l}RYflJBs)u+=ElYEFeR3v(?;!3r;CZma7@FfImj z5i`l2gGgHt#+kX*3i~;ZSmaT@-UAq6;>+=dX~{3K$1rFowx(cQg_am~ryM#gLxPY? zp9@GWAbvnb#aGF`xPVaaHz4Yfj3)k;Tf1E&Cb0=DLvX@^L^KkE78RBxmBjvSgf(Ko zB6aIDq1}}Iv42HkG1XS>tJ>z=6>am>YSD_{BhKb@@kT10$iXufK>U#^K1q!OiD9lw z5;vtKiAg`rEk6S!{=?65Yk|a6Jq;x0c)Drg#wSV4wEaZe&+-J%0D%c^^DNwv+dQ>- ziYD76;%M09fJ7jVXMw~V&qxyUw6I9xi?=wKco9e}9JYBFC^R8Gq-3A*B#@{BiJd$G z2|Fc;Xm!yHkcd{dv^wY#Nun-EjPnS+14uNQc^;7@uH)fmmn2a}h)Sj>canIq?}2Cl zh&`g2@f#1r3*0%sjLIU|4t|?4v~Yi9J5Xc^Aa1e_*e}uAg@Wv`$594Q_Mkk0vKM6^ z%6^nV6p6+VT3BPnZc)oFncrhJi9ckQmH!t$*g?#LWUyhBr%(_HRzmqN9&)$yAi8sR z?S2}gMo^FlMp1r<2IgSz0tRdpUEJ*1Aru$ou-w3o=L*J`;Ce^J`P`QOOWhZ+?)%zx z9}Y7t`eIr?L+@W(ULdve?7!z~SMsYPk#x9~(z6-hlw6>IWbIjuHH;660%*4CNGdaaWlCkw-a02Q5=+A zDE;E^$pS4clrN4iHTD+fVAZ&VbpOm=lK z!WuS&(kr^`Q?JRDS?D)bkwPn1A-nXW9YlE?q>x}4jQ66*88uoCJ--sgs@`mQ(<*z! z9s3DV5=n>II1t|4x9|-<6CXJH5}#j;^QJLn@+0x1b7?+IaVxYht89T=kj!6ncq(+b zvlOEyO)jgK$zJ7RirZ^BYdvSr`COTCXG|XFNp5hc;TG4RUuv1Kt6{nkH|nc|+S0?u zFRL<2%cwg+Gas5q6sjIphynv?w0WPxV@nyXEfb>5b@BL8vpAG4h*G!G9;wnZsOtq z7FoCwU;NtKIfAT4y7aXw+XrqFC-UxJzzVbOSIR+&dZEY0u;>}glDe44_Gt?c2UNV5 z9U3r+L9!%IG*u-VS0^#yQi=7CVOgrHy5GkJ^S5Jz7Y4+NmJ=(MA-3nb9He(0#XCft z%*_IeI*&^hZ|8u;X5cIfEPl#u$zqy2VUDMlOgui;Sai6%mUGr~?%X9{F+byS9XK>O z)BueJ^mBp5FT$2a+^7c@)6&DC11w@yRz}@Pnv*QXC5tI;&^)lHEwyq(vN*)`r8aS} zr6(KQy$41OU~CZ!E#dqK+~m>5%P!yjr@^mbhS5QkQ55-@2}by=*&&o?Q4XUVL6K}d zj}dNCp*_-BxnA+6%8^p}}XaN5$*fx+T_Ij;WVUMAgcm1SHQhzFB zPhs*D%A`2c*>a2}A#Q_jkOwgogBW_I$$-mlvh!}IyCpj!YYGpuhoB str: return hashlib.md5(s.encode('utf-8')).hexdigest() + def _to_float(self, value) -> float: + """ + 从字符串中提取浮点数,过滤掉非数字字符 + """ + if value is None: + return 0.0 + if isinstance(value, (int, float)): + return float(value) + + import re + try: + # 提取第一个匹配的数字部分(包含小数点) + match = re.search(r"[-+]?\d*\.?\d+", str(value)) + if match: + return float(match.group()) + return 0.0 + except: + return 0.0 + async def init_db(self): await self.db.init_db() @@ -129,12 +148,7 @@ class XinDianTuService: }) price_str = station.get("price", "") - current_price = None - try: - price_match = re.search(r"\d+\.\d+", str(price_str)) - if price_match: - current_price = float(price_match.group()) - except: pass + current_price = self._to_float(price_str) await self.station_status_model.save( session=session, @@ -193,32 +207,47 @@ class XinDianTuService: # 2. 保存 Status (解析价格和电桩) status_id = self.generate_id() - piles_str = station.get("piles", "0/0") + + # 处理 piles 字段 (由 VL 返回的列表结构) + piles_data = station.get("piles") total, free = 0, 0 standardized_piles = [] - if "/" in piles_str: + if isinstance(piles_data, list): + for idx, p in enumerate(piles_data): + try: + t = int(p.get("total", 0)) + f = int(p.get("free", 0)) + total += t + free += f + + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": p.get("type", "未知"), + "power": "", + "status_text": f"空闲{f}/总{t}", + "remark": "列表页VL" + }) + except: + pass + elif isinstance(piles_data, str) and "/" in piles_data: + # 兼容旧格式或意外返回的字符串格式 try: - parts = piles_str.split("/") - free = int(parts[0]) - total = int(parts[1]) + parts = piles_data.split("/") + free = int(re.search(r"\d+", parts[0]).group()) + total = int(re.search(r"\d+", parts[1]).group()) standardized_piles.append({ "pile_no": "G1", "type": "未知", "power": "", "status_text": f"空闲{free}/总{total}", - "remark": "列表页VL" + "remark": "列表页VL(兼容)" }) except: pass price_str = station.get("price", "") - current_price = None - try: - price_match = re.search(r"\d+\.\d+", str(price_str)) - if price_match: - current_price = float(price_match.group()) - except: pass + current_price = self._to_float(price_str) await self.station_status_model.save( session=session, @@ -299,20 +328,10 @@ class XinDianTuService: continue price = station.get("price") - current_price = None - if price is not None and price != "": - try: - current_price = float(price) - except (ValueError, TypeError): - current_price = None + current_price = self._to_float(price) if price is not None and price != "" else None pro_price_val = station.get("pro_price") - pro_price = None - if pro_price_val is not None and pro_price_val != "": - try: - pro_price = float(pro_price_val) - except (ValueError, TypeError): - pro_price = None + pro_price = self._to_float(pro_price_val) if pro_price_val is not None and pro_price_val != "" else None await self.station_status_model.save( session=session, @@ -414,44 +433,64 @@ class XinDianTuService: # 2. 保存 Status status_id = self.generate_id() - # 解析电桩数量 (支持多组,如 "快:2/10 慢:1/5") - piles_str = station_info.get("piles", "") + # 解析电桩数量 (支持由 VL 返回的列表或字符串) + piles_data = station_info.get("piles", []) total, free = 0, 0 standardized_piles = [] - # 尝试匹配 "快:2/10" 或 "2/10" 这种格式 - # 模式 1: 有类型,如 "快:2/10" - matches_with_type = re.findall(r"(\w+):(\d+)/(\d+)", piles_str) - if matches_with_type: - for idx, (p_type, f, t) in enumerate(matches_with_type): - f_int, t_int = int(f), int(t) - free += f_int - total += t_int - standardized_piles.append({ - "pile_no": f"G{idx+1}", - "type": p_type, - "power": "", - "status_text": f"空闲{f_int}/总{t_int}", - "remark": "列表页VL" - }) - else: - # 模式 2: 无类型,仅 "2/10" - matches_simple = re.findall(r"(\d+)/(\d+)", piles_str) - for idx, (f, t) in enumerate(matches_simple): - f_int, t_int = int(f), int(t) - free += f_int - total += t_int - standardized_piles.append({ - "pile_no": f"G{idx+1}", - "type": "未知", - "power": "", - "status_text": f"空闲{f_int}/总{t_int}", - "remark": "列表页VL" - }) + if isinstance(piles_data, list): + # 模式 1: VL 返回的结构化列表 + for idx, p in enumerate(piles_data): + if isinstance(p, dict): + try: + t = int(p.get("total", 0)) + f = int(p.get("free", 0)) + total += t + free += f + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": p.get("type", "未知"), + "power": "", + "status_text": f"空闲{f}/总{t}", + "remark": "列表页VL" + }) + except: + pass + elif isinstance(piles_data, str): + # 模式 2: 字符串格式 (兼容) + piles_str = piles_data + # 尝试匹配 "快:2/10" 或 "2/10" 这种格式 + matches_with_type = re.findall(r"(\w+):(\d+)/(\d+)", piles_str) + if matches_with_type: + for idx, (p_type, f, t) in enumerate(matches_with_type): + f_int, t_int = int(f), int(t) + free += f_int + total += t_int + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": p_type, + "power": "", + "status_text": f"空闲{f_int}/总{t_int}", + "remark": "列表页VL(兼容)" + }) + else: + # 模式 3: 无类型,仅 "2/10" + matches_simple = re.findall(r"(\d+)/(\d+)", piles_str) + for idx, (f, t) in enumerate(matches_simple): + f_int, t_int = int(f), int(t) + free += f_int + total += t_int + standardized_piles.append({ + "pile_no": f"G{idx+1}", + "type": "未知", + "power": "", + "status_text": f"空闲{f_int}/总{t_int}", + "remark": "列表页VL(兼容)" + }) - if not standardized_piles: + if not standardized_piles and isinstance(piles_data, str): # 兜底匹配所有数字 - nums = re.findall(r"(\d+)", piles_str) + nums = re.findall(r"(\d+)", piles_data) if len(nums) >= 2: free = int(nums[0]) total = int(nums[1]) @@ -463,17 +502,9 @@ class XinDianTuService: "remark": "列表页VL兜底" }) - # 解析价格 + # 解析价格 price_val = station_info.get("price") - current_price = None - if price_val: - try: - # 提取数字部分 - price_match = re.search(r"(\d+(\.\d+)?)", str(price_val)) - if price_match: - current_price = float(price_match.group(1)) - except: - pass + current_price = self._to_float(price_val) await self.station_status_model.save( session=session, diff --git a/Apps/XinDianTu/__pycache__/Crawler.cpython-310.pyc b/Apps/XinDianTu/__pycache__/Crawler.cpython-310.pyc index 4b4cf41696a1f1c99c2d7e72bb58406d55d1c121..eb757722460e960df81ce44c46ecc1d94de0ea1d 100644 GIT binary patch literal 9743 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 L+*h*5`ZxazD@)}U literal 15040 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 diff --git a/Apps/XinDianTu/__pycache__/Kit.cpython-310.pyc b/Apps/XinDianTu/__pycache__/Kit.cpython-310.pyc index 5ef23a8a737d1a78a87a5ba7ae50bfc2af4900cb..b395b42b6bc34f64f29895abb1ce2851fafae303 100644 GIT binary patch delta 5662 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 Br$GP! delta 3884 zcmZ`+YitzP6`nh@kJ+_%S?~ita9F@L9t`Gb4AjLYJj~06+9s66WHa77UXQ&yv%NFM zkD6?h&__}bN^S~jQxc=5KZq1a>pp%YYSbuggPP<=A{A+Vr2SDTb&FJ0X{0LZ>zq4a z8%v$letYK3xv%ej=iJ#VuaZAqBXK(xi%M|)_y9HUzVLi}mHdhH{Kid1ITy-@Q(+=e zi7GiYA4x@sWJn`X_?FNB4PKVp|xPH1Zx$o1FMQ^^bxum ztZJI1Yhaifx`D2v_28+cq)*bC`4)2ZiLb(Predx%LtJ@8nU(+plw6jnd_z7h^+^HA z4Nf)_=>j3r)CxB=6Q&ULl0*a3QE*M$@CmhFs&h5lf6JecZWS<+?3b~zC~#(#$W|b96*+9NSsu{SA9zU4=V>(Mh19r1;D`V z+Yeud0Zi4n(g>N6r==T&l4|LKJS{shDqoOYWhO8!Pm>!m`e%X|f$OA-U?eoT3m8!Z zBU{5WDv*Jc1gDjUC<$Fqo>XWUC=r&RLJbh$q_)OTdk%I)$9+8WS#yz->x3^M;kNso{lOd&tZg45?s9g%>oCVlCh|RLp$V zQ?TK3j94K_y97$C41=REu#pzqPzm=Af-EOU06vu@w3yU7{)2G;S`6sFNj%ksH37p!VL;Y6Yp9)M zE&8;$=+<9ENDStP^|58}l>a)?c1$d}24jP)0e-vyGT}uK(`UObg}CTHj@ z?Hc()8s^;0_eGn@*4cb?QjzCm{^!^l(!itfB&p!d@xlNuP|Sp_M+<2d(-1=Qg3hpB zFuZ^Zo5C9LnF0XroM99g%Fa`BrsWj$j3Ktq3o*knrwmUqEth{D-?Xe*G|1%4%&1n) z*72>&{$8?(J-#VXP1<=^B1_K9-cEd7COdd@+5X~gXf_o~HuVofhr@P`?n$ye;L~CY zc`X=DfS#&e_b1?>}+;L~r`huHJ23z5C9vPK*(A4&)8pT3D+V^P)m0 zKDAvCSHfzsGXgm|&i_?*>Y*tQlvk7I`1x{;7_&3wRDmf6t2W2BLkmrw3*s;%d|y>P zY2`yz>kjM!$5ceynCt^$_9Q(r(a%b;k6`RM@n7bqk74Cj@%YDTCQgI%kf;_S%-=uu^`Yx>&LxfHnNX z>bmuH5X>|Ht(K*+VT2lkV_B4zpol$z0Xkn%Gfi^*N=;qzG&-;VKL~|1U7Roc{hCL} z8~m>|S@O(mU+rh1iXGUZ6=5g9oLE-{KfAWQUZ^0vF?rHz0I6_c%8bVFj ziKk+PvvjC7$bzR7;FMT0p|S@PvL@#zb)DPVYVz{z745pxBINWp6r9es@!{1ZBv+ zgK(M4Ev+S(%f8g|{Lz+rZHcmkoP~HgF;GkdbCsRrS6a3dQBhuy*<%*Qi7*9_f}zaxu&2Ne8-&8Lck|hX z@4^EwK;hJ5FJjDhsS%^N!QtZm;reU43| zE0G?`=~;fLbw}&}C3_Li&?FVyuUppS{WE~yZmsKnI59;AdNPBP%NZL4a2acdhVXjg zvLSK)X>jYaJzpfXhWnKB>YcTTC7ciP13TX)MILC|nZSDJXPTh(=lp2fj)%^aXWNn_ z%3o{a4FV!9_%hJ zKWY-4KY4T|Im@peJyo3Fv!!K97gC@hW=Bb0a;}^IpY=j4c7cs0csCZBag$l(% zAe6}q41sUBqbH%%mM}`*f6TjC}Lw-0L zKEX-%zad(a**0u1-h2p4p^Nlrau2&Gp7x;KudVXJ_;&{nR*|kqwikpo7bboF+W9|E zQh$fUZitd5UN^U5_h%3cgl7=0A-s(6I>NgMxK|9Pv}n3QcxB-8)b_kh$8yGA%pzwC rfGVlP|CEwal8~cBty9!UX}mNXT^{X;Hb(oTVzd_Q0ja14;+6jc@ROUU diff --git a/Apps/XinDianTu/__pycache__/Opener.cpython-310.pyc b/Apps/XinDianTu/__pycache__/Opener.cpython-310.pyc index ca86a99a1e8c87bb1718efff8f04571003a0a56b..d23bbb3b0ddb3c11c8b95faae3e006b29c396f60 100644 GIT binary patch delta 2319 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 H{2%`ScUpHe diff --git a/Apps/XinDianTu/__pycache__/ReadImageKit.cpython-310.pyc b/Apps/XinDianTu/__pycache__/ReadImageKit.cpython-310.pyc index ac8642abb2185e33e265ef55c93829a9173d5225..a7e139665c2c1813c19b260f4c18f87d13319ceb 100644 GIT binary patch delta 12004 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 Xor|}K{p_X1A1J4xl|IGxMjrb=Avgek delta 4274 zcmbVPYit}>6`nhu-JPA?+4sX<+wt0o9dGYqYXr3zI2(F%ScAykkUe!!19q(2ZyPysEaoO9RD zG)M)n{M~b3=f2K&&Y4%oUcE0+F-=2(KYc$fMi2ie;1F_AyhlbGUTQp{WIfbJ{ZQ(( zm%0ny36%zD@CjGeprL|GwrDg=BTr~qAB>1XTdd%h?QR;U2^eWYdlK5)SNr@EI_;n- z=nK%!f**8t(QeQXTpqcp;H9w$bhv2`O~bGdHSbe0edpg+7gce}(=LLZ{jSZh>8;|Z z=VsC;p7&hq-UfBHMZDt~4s?MSg#WkT-+EO9^qYM{bvM^;RnCxOvGYguGo(S)dTKsm zN1F-SV@G($0$Eh+oxGEMY$thVvwcxnAobJ{rK}MJe@7LrOm$2d+|B*m%L6>fLp;Sj zO^v1(i7b1U%RVR#y7?L3oeEX&fVnWkL$}1u|#XOR$P zrjNUuDe?H$E-_~Wqladpt+hO;altJNinB(|Cl4FK6K6!HuaAt1y}py=I`NvX$NfRu zj_o_RUP4gh32#n1f@H5{X870WQFJYI0LQqi&< zZ=qb9F0i~^aN3Gx+i~Zs)k2xFBPKiJR3jmxF$-KyzRIq zS*2EG0UYceuS`!D?MxSoKsD<>S;`fs^OJ>Kjg_+IlvOGFa?=GnPxE%34T^K-z#crD zN2XuQo+i}nb%d&PX* zRR2xHsoUNH%}_; zTk~7E*)*vE6T)_YhpDdvEjB1+zmx+!)C^J+8B0Svcvhid9yqI<(`bZ7UvQzhZLn{& z8H~buscA^c-cBWVc!}}K95zjD0VM`+zuMw zx*^z`Ns1eyJ&i-ya~Po)K}C>8n?lJ%xE~>e@Bo10vZ|$`&5mM27U3a;FCrkWE7nA$YbyXz>Pzp!|^uk{N z{{0{79>2PQaKsHGSAGUaI*$9h?$bfiiC+z=p`U2CB`#{Wi5>Cl$)K2ucaxuq)A7BX zyXr39CWAv7_~-^2AP<3&*0A_}{ORa9Zr-XK%hW@*$wPK(UIKLph`Ugd{t_My$@yZL>qg5-fhQu z82B3jN|~!_|JG8AGma`{GONhVgc8aYE)CrF?NC8;S2nqr_Su%hVFT6*E)A72rVw%>3-@<;Lw6}qe+0{~@^FhH3uVu%x|V`&ZI4;Vcl82`scn?_=?9+7o-oA_m_*ZYcg zr2S>>$bA2DQ1YuRbH2Cp5^>8{pA%;HgCWUs$?ewT3ak5`omV)ujc=dzj8`g*<{nuQ z=GdtCOZPX^b=az-$&&HnjP;%tyIckn0E|FEAlP5<*M)uj;B_IAYY&@Un*ZE3hg4_vzZ(g zPxibVY=jp$*pKUaK)Wb1S`?;SzZUZh5 za2TU7#vE(I$Sqw*aDku$SsY8Q+Av#zd*)Diw_G?N7mmWBKzdkoL@uiSe@jB5@W~}tR{R?GS?@OFq9M6x z%ntI{0-@m(F7_^*EJh_&tqn^EdrB;eu_SL7eDDV@8xhqu9%8r;VdRF%q;ka^%D z?NDm8V_jnIYQ`6pl{DQ>G?O&NRoG-F$E|j8*edPj3BXO~U`?Wk8#nhx?^*9NsR}-` zN6c(~IDw{lfXQTI2Z*f{VyD=&CE2(Z>zH7yODX(NT{`{T<;9oYTYL?27nw}V`vxH? z&uo_{Gm&{$OTGnXOK)m}BomVLvzMNHVd>(xrTdsSamJub?=v@LAl2}~)H`whUE;AV z*EB2;=e@(}gZL@1C(Ry*dZzuVnFel>NpE_!oI_?8V>sjs2y1D_F|7W#w4)*O4u+nA zeHj3jj-Y%R;fl0EI-OO=d9~ak83$WHkd0}G{-NR3h#P!t zNOePEqMZU+ygra7FN)s|44&`E+)v0>QQp?mmvLPYIq^9Lwq4hdH`t4tQW4gCI&pwo=BSxzffDG)_$lf7r3@-lKG%B)5E%sY4~ch% U_mQk