feat(rainyun): 完成雨云纯协议自动登录签到脚本及青龙单目录部署包

- 逆向分析雨云登录与签到接口,打通腾讯天御点选验证码全协议过码闭环
- 支持 RAINYUN_ACCOUNT='账号#密码' 极简配置 (多账号支持 & 与换行分割)
- 增加积分提现金额换算展示 (2000积分 = 1元现金) 及青龙系统通知推送
- 新增 dist/rainyun_qinglong 单层平铺部署目录与专属 README
- 增强 solver.py 在模板缺失时的 ResNet18 分类器双模降级能力
This commit is contained in:
yml2213
2026-09-12 10:56:25 +08:00
parent da62cb7e09
commit 5835d7cb15
15 changed files with 2837 additions and 9 deletions
+20 -9
View File
@@ -79,19 +79,30 @@ class CaptchaSolver:
def parse_prompt_targets(self, prompt_img: str | Path | bytes | Image.Image) -> List[int]:
"""
自动识别并解析提示图中 3 个目标图标的真实类别 ID (0~11)
支持干净模板匹配与 ResNet18 分类器自动双模降级
"""
crops = slice_prompt_image(prompt_img)
target_classes = []
for crop_img, _ in crops[:3]:
arr = np.array(crop_img.convert("L"))
bg = np.median(arr)
bin_c = cv2.resize(((arr < bg - 20).astype(np.uint8) * 255), (48, 48), interpolation=cv2.INTER_AREA)
if not crops:
return []
scores = [cv2.matchTemplate(bin_c, t[1], cv2.TM_CCOEFF_NORMED)[0, 0] for t in self.templates]
best_cid = int(np.argmax(scores))
target_classes.append(best_cid)
if self.templates:
target_classes = []
for crop_img, _ in crops[:3]:
arr = np.array(crop_img.convert("L"))
bg = np.median(arr)
bin_c = cv2.resize(((arr < bg - 20).astype(np.uint8) * 255), (48, 48), interpolation=cv2.INTER_AREA)
return target_classes
scores = [cv2.matchTemplate(bin_c, t[1], cv2.TM_CCOEFF_NORMED)[0, 0] for t in self.templates]
best_cid = int(np.argmax(scores))
target_classes.append(best_cid)
return target_classes
# 模板缺失时自动使用 ResNet18 分类器直接预测提示小图类别
patch_tensors = torch.stack([self.transform(c[0].convert("RGB")) for c in crops[:3]]).to(self.device)
with torch.no_grad():
logits = self.classifier(patch_tensors)
probs = torch.softmax(logits, dim=1).cpu().numpy()
return [int(np.argmax(p[:12])) for p in probs]
def _extract_candidates(self, bg_img: str | Path | bytes | Image.Image) -> List[Tuple[int, int, Image.Image]]:
"""从背景图中提取所有去重后的候选图标 (cx, cy, patch)"""