标签 青龙面板 下的文章

接:雨云无限白嫖 FRP 服务器攻略(无 aff)

@fatekey 大佬的方案是单独开一个容器,我想着反正我有青龙面板在跑脚本,站在巨人的肩膀上顺手写了一个,把多账户也写进来了

一、运行效果

先看实际运行的效果吧
【前两个账号运行已签到,仅测试多账户切换功能,临时注册的第三个号用于测试签到功能】

## 开始执行... 2026-01-23 16:57:53

2026-01-23 16:57:54.116950139 [W:onnxruntime:Default, cpuid_info.cc:91 LogEarlyWarning] Unknown CPU vendor. cpuinfo_vendor value: 16
2026-01-23 16:57:54,191 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,191 - INFO - 雨云签到工具 by SerendipityR ~
2026-01-23 16:57:54,191 - INFO - Github发布页: https://github.com/SerendipityR-2022/Rainyun-Qiandao
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO - 雨云签到工具容器版 by fatekey ~
2026-01-23 16:57:54,192 - INFO - Github发布页: https://github.com/fatekey/Rainyun-Qiandao
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO -                    项目为二次开发青龙脚本化运行
2026-01-23 16:57:54,192 - INFO -                      本项目基于上述项目开发
2026-01-23 16:57:54,192 - INFO -                 本项目仅作为学习参考,请勿用于其他用途
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO - ✅ 成功解析3个账号
2026-01-23 16:57:54,192 - INFO - 
================= 处理第1个账号 ==================
2026-01-23 16:57:54,192 - INFO - 
========== 开始处理账号:TACGN ==========
2026-01-23 16:57:54,192 - INFO - ⏳ 随机延时 0 分钟 35 秒
2026-01-23 16:58:29,794 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 16:58:29,809 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 16:58:29,809 - INFO - ⏳ 发起登录请求
2026-01-23 16:58:29,810 - INFO - 🌐 访问雨云登录页
2026-01-23 16:58:31,258 - INFO - 页面标题:登录 | 雨云
2026-01-23 16:58:31,258 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 16:58:31,376 - INFO - 📝 输入账号密码
2026-01-23 16:58:31,775 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 16:58:54,899 - INFO - ✅ 未触发登录验证码
2026-01-23 16:58:59,906 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 16:58:59,910 - INFO - 页面标题: 总览 | 雨云
2026-01-23 16:58:59,940 - INFO - ✅ 账号登录成功:TACGN
2026-01-23 16:58:59,940 - INFO - 🌐 访问赚取积分页
2026-01-23 16:59:00,958 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 16:59:00,962 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 16:59:00,962 - INFO - 🔍 查找每日签到按钮
2026-01-23 16:59:01,016 - INFO - 📌 签到状态:已完成,无需重复签到
2026-01-23 16:59:01,047 - INFO - 💰 当前积分:700(约0.35元)
2026-01-23 16:59:01,131 - INFO - ✅ 账号TACGN浏览器已关闭
2026-01-23 16:59:01,131 - INFO - ✅ 临时文件清理完成
2026-01-23 16:59:01,131 - INFO - 
========== 账号TACGN处理完成 ==========

2026-01-23 16:59:05,996 - INFO - 
================= 处理第2个账号 ==================
2026-01-23 16:59:05,996 - INFO - 
========== 开始处理账号:ACGN_T ==========
2026-01-23 16:59:05,996 - INFO - ⏳ 随机延时 4 分钟 3 秒
2026-01-23 17:03:09,549 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 17:03:09,564 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 17:03:09,564 - INFO - ⏳ 发起登录请求
2026-01-23 17:03:09,564 - INFO - 🌐 访问雨云登录页
2026-01-23 17:03:11,015 - INFO - 页面标题:登录 | 雨云
2026-01-23 17:03:11,016 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 17:03:11,155 - INFO - 📝 输入账号密码
2026-01-23 17:03:11,584 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 17:03:34,692 - INFO - ✅ 未触发登录验证码
2026-01-23 17:03:39,699 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 17:03:39,703 - INFO - 页面标题: 总览 | 雨云
2026-01-23 17:03:39,733 - INFO - ✅ 账号登录成功:ACGN_T
2026-01-23 17:03:39,733 - INFO - 🌐 访问赚取积分页
2026-01-23 17:03:40,777 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 17:03:40,782 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 17:03:40,783 - INFO - 🔍 查找每日签到按钮
2026-01-23 17:03:40,858 - INFO - 📌 签到状态:已完成,无需重复签到
2026-01-23 17:03:40,881 - INFO - 💰 当前积分:4684(约2.34元)
2026-01-23 17:03:40,966 - INFO - ✅ 账号ACGN_T浏览器已关闭
2026-01-23 17:03:40,966 - INFO - ✅ 临时文件清理完成
2026-01-23 17:03:40,966 - INFO - 
========== 账号ACGN_T处理完成 ==========

2026-01-23 17:03:43,883 - INFO - 
================= 处理第3个账号 ==================
2026-01-23 17:03:43,883 - INFO - 
========== 开始处理账号:ACGN ==========
2026-01-23 17:03:43,883 - INFO - ⏳ 随机延时 4 分钟 50 秒
2026-01-23 17:08:34,684 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 17:08:34,698 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 17:08:34,699 - INFO - ⏳ 发起登录请求
2026-01-23 17:08:34,699 - INFO - 🌐 访问雨云登录页
2026-01-23 17:08:36,143 - INFO - 页面标题:登录 | 雨云
2026-01-23 17:08:36,143 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 17:08:36,285 - INFO - 📝 输入账号密码
2026-01-23 17:08:36,657 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 17:08:59,802 - INFO - ✅ 未触发登录验证码
2026-01-23 17:09:04,809 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 17:09:04,813 - INFO - 页面标题: 总览 | 雨云
2026-01-23 17:09:04,842 - INFO - ✅ 账号登录成功:ACGN
2026-01-23 17:09:04,842 - INFO - 🌐 访问赚取积分页
2026-01-23 17:09:05,841 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 17:09:05,871 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 17:09:05,871 - INFO - 🔍 查找每日签到按钮
2026-01-23 17:09:05,940 - INFO - 📌 签到状态:领取奖励,开始领取
2026-01-23 17:09:06,072 - INFO - ⚠️ 触发签到验证码
2026-01-23 17:09:06,253 - INFO - 🔄 验证码处理第1次尝试(最大10次)
2026-01-23 17:09:06,810 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=02680900003d283800000015123b75d53fed&sess=s0HtD0kpY6pcWGI6FzFpt6ZiszTr2EhH-VfdHwPwxIdqv34Z-7I44K0-_RhKCQ_D1pczn56AhHTy7TzWXqVjayAnecALMlUWYf152tXUBM_URxYIPDxvoDD7jXbk7mwSIeJKDAUtmTTnuuaRcoqdw3DlBpEXv3Xc4RbCewuRGJZUAkZPrzzB8njktvXIOPrqAhs4UafKm96GgAUPJExW9_2PkkRGBKSTS43H1uLzB9el3g70xLMDYSd2TywoxM5Ps2idtfMPBn_aMw93gVXYLGwpX0Iztn4QG1vFv9VJj6NgCvOU2YSfCmTrGyEXxdzPnGglGJAKJFB0FfuxP4bM3-0O4DQt4l-5NsT52KR_8WcG7rvohxQXZy1sRw9MY84c31oFqKfUyPsa49v1VdtmranaOtiaDLX6SjgI6rJPvt2_kSelSHRNUWtA**
2026-01-23 17:09:07,077 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=02680900003d283800000015123b75d53fed&sess=s0HtD0kpY6pcWGI6FzFpt6ZiszTr2EhH-VfdHwPwxIdqv34Z-7I44K0-_RhKCQ_D1pczn56AhHTy7TzWXqVjayAnecALMlUWYf152tXUBM_URxYIPDxvoDD7jXbk7mwSIeJKDAUtmTTnuuaRcoqdw3DlBpEXv3Xc4RbCewuRGJZUAkZPrzzB8njktvXIOPrqAhs4UafKm96GgAUPJExW9_2PkkRGBKSTS43H1uLzB9el3g70xLMDYSd2TywoxM5Ps2idtfMPBn_aMw93gVXYLGwpX0Iztn4QG1vFv9VJj6NgCvOU2YSfCmTrGyEXxdzPnGglGJAKJFB0FfuxP4bM3-0O4DQt4l-5NsT52KR_8WcG7rvohxQXZy1sRw9MY84c31oFqKfUyPsa49v1VdtmranaOtiaDLX6SjgI6rJPvt2_kSelSHRNUWtA**
2026-01-23 17:09:07,375 - ERROR - ⚠️ 图案2识别率0.0000低于阈值0.4
2026-01-23 17:09:07,376 - ERROR - ❌ 验证码坐标重复,答案无效
2026-01-23 17:09:07,376 - ERROR - ❌ 验证码处理失败:验证码答案无效
2026-01-23 17:09:07,376 - ERROR - ⏳ 刷新验证码中,稍后重试……
2026-01-23 17:09:13,495 - INFO - 🔄 验证码处理第2次尝试(最大10次)
2026-01-23 17:09:13,518 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=0268090000946c2b0000000bb5e61fd63312&sess=s0_hrS7I5bVMRdivCWNVX_5xijZd5qBztok8b_H7bwMciiNFNIe3KMmj4IPktJO-cbs-8dl7upCI40ZosuxWWRjpXlIbF-P3ZWNoFjjg5G9dMFSybpTUgmgQO1lGEy1QSjGIghi44ITJTpCGcF4ym8wD4iU0xLCVakXfJvTvPiJbxl055LMVFM8W1FM1TtThPXpkg5h9JgYXRHols_wYhIgOI_dRxdgl3r_h-dSKI109RxypesTYee-w0m-Lw_41AM1etin4G_Iamp3lveRUaOtNV1JT4ssYxJ3DR1NZ8SEfN3yxvn9Z-_dxfifqGBxz8hkBmv4vsmx4M9imY60mxrr32HJt0K1ODVgIkzXKA0mgcq1DsSXM0AlcE765_pI_-NP9BgOPXEivjsEDpnxrS-nUFA1DJEz6urpWBwjgZN80OGgAAIs1XL1A**
2026-01-23 17:09:13,731 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=0268090000946c2b0000000bb5e61fd63312&sess=s0_hrS7I5bVMRdivCWNVX_5xijZd5qBztok8b_H7bwMciiNFNIe3KMmj4IPktJO-cbs-8dl7upCI40ZosuxWWRjpXlIbF-P3ZWNoFjjg5G9dMFSybpTUgmgQO1lGEy1QSjGIghi44ITJTpCGcF4ym8wD4iU0xLCVakXfJvTvPiJbxl055LMVFM8W1FM1TtThPXpkg5h9JgYXRHols_wYhIgOI_dRxdgl3r_h-dSKI109RxypesTYee-w0m-Lw_41AM1etin4G_Iamp3lveRUaOtNV1JT4ssYxJ3DR1NZ8SEfN3yxvn9Z-_dxfifqGBxz8hkBmv4vsmx4M9imY60mxrr32HJt0K1ODVgIkzXKA0mgcq1DsSXM0AlcE765_pI_-NP9BgOPXEivjsEDpnxrS-nUFA1DJEz6urpWBwjgZN80OGgAAIs1XL1A**
2026-01-23 17:09:14,002 - ERROR - ⚠️ 图案2识别率0.1515低于阈值0.4
2026-01-23 17:09:14,003 - ERROR - ❌ 验证码坐标重复,答案无效
2026-01-23 17:09:14,003 - ERROR - ❌ 验证码处理失败:验证码答案无效
2026-01-23 17:09:14,003 - ERROR - ⏳ 刷新验证码中,稍后重试……
2026-01-23 17:09:23,108 - INFO - 🔄 验证码处理第3次尝试(最大10次)
2026-01-23 17:09:23,131 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=0268090000f13d2300000015123b75d53f2f&sess=s02qPcN6ye2H2TPQfQ9ghy_0L3jB722YFRMCmx-rWnjm4UgxUo3F4WLoUzz5JczVgNJMtQwRWLFRo4OvXls1zjaajvPXch4RMoo6YZOavScFvdGaB-9B-ecxWvfcPx7ZTEb03-5MTmG-P2LipAwhLGAYKO0JOK6Rb6z3KYkAy9pxHIXYP9FaLlwdRvLsEDbqKWJZKCP4IHJ9mav4XH2EoTFfWGYMR-sA53gKcavXkSbzg2J_3ntSL6rszaLREZi9ZCSn1bPIDt16NYUXhHhlPFCJmBzIh41fG-nFTtpB-A8_i_vPaNo3mwlxJ9KojhSP37q7CfeASWq8-DTtI3OnT-mZbyVzoDHvBgQOiiQu5o0_VxQtxzWD9vNmVbErvVsP1VxQEVv0GCFywapI0H-R2DimaJI87vvVkVIzVce2MZQJ_lxWICubZ-RA**
2026-01-23 17:09:23,352 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=0268090000f13d2300000015123b75d53f2f&sess=s02qPcN6ye2H2TPQfQ9ghy_0L3jB722YFRMCmx-rWnjm4UgxUo3F4WLoUzz5JczVgNJMtQwRWLFRo4OvXls1zjaajvPXch4RMoo6YZOavScFvdGaB-9B-ecxWvfcPx7ZTEb03-5MTmG-P2LipAwhLGAYKO0JOK6Rb6z3KYkAy9pxHIXYP9FaLlwdRvLsEDbqKWJZKCP4IHJ9mav4XH2EoTFfWGYMR-sA53gKcavXkSbzg2J_3ntSL6rszaLREZi9ZCSn1bPIDt16NYUXhHhlPFCJmBzIh41fG-nFTtpB-A8_i_vPaNo3mwlxJ9KojhSP37q7CfeASWq8-DTtI3OnT-mZbyVzoDHvBgQOiiQu5o0_VxQtxzWD9vNmVbErvVsP1VxQEVv0GCFywapI0H-R2DimaJI87vvVkVIzVce2MZQJ_lxWICubZ-RA**
2026-01-23 17:09:23,677 - INFO - 🎯 图案 1 坐标(37,277),匹配率:0.6552
2026-01-23 17:09:23,677 - INFO - 🎯 图案 2 坐标(598,114),匹配率:0.5641
2026-01-23 17:09:23,677 - INFO - 🎯 图案 3 坐标(437,197),匹配率:0.6207
2026-01-23 17:09:26,517 - INFO - 📤 提交验证码
2026-01-23 17:09:31,670 - INFO - ✅ 验证码验证通过
2026-01-23 17:09:36,676 - INFO - ✅ 签到奖励领取成功
2026-01-23 17:09:36,699 - INFO - 💰 当前积分:700(约0.35元)
2026-01-23 17:09:36,788 - INFO - ✅ 账号ACGN浏览器已关闭
2026-01-23 17:09:36,788 - INFO - ✅ 临时文件清理完成
2026-01-23 17:09:36,788 - INFO - 
========== 账号ACGN处理完成 ==========

2026-01-23 17:09:40,305 - INFO - 
🎉 所有账号处理完成!

## 执行结束... 2026-01-23 17:09:40  耗时 707 秒   

二、前置条件

青龙面板:我是直接用的 1panel 应用商店里的青龙面板
雨云账号密码:自个注册去

三、准备工作

青龙面板安装依赖:安装不上的,不会的请自行搜索教程或者请教 AI 了哦
—— NodeJs:chromium
—— Python3:selenium
—— Linux:chromium-driver
青龙面板配置环境变量:想设置多少自己设置就好了
—— RAINYUN_ACCOUNT
—— [[“账号 1”,“账号 1 密码”],[“账号 2”,“账号 2 密码”]]

四、创建文件

同目录下创建以下两个文件

stealth.min.js
stealth.min.js.txt

rainyun.py
rainyun.py.txt

删掉 [.txt] 后缀上传就好了,顺便贴出 rainyun.py 的代码如下

import json
import logging
import os
import random
import re
import sys
import time
from typing import Tuple, Optional, List

import cv2
import ddddocr
import requests
from selenium import webdriver
from selenium.common import TimeoutException, WebDriverException, NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

# ===================== 青龙面板专属配置(常量不抽离) =====================
CONFIG = {
    "timeout": 20,  # 青龙面板网络可能不稳定,延长超时时间
    "max_delay": 5,  # 最大随机等待分钟数
    "max_captcha_retry": 10,  # 验证码最大重试次数(防止递归栈溢出)
    "similarity_threshold": 0.4,  # 降低阈值提升识别率
    "script_path": os.path.dirname(os.path.abspath(__file__)),  # 青龙脚本所在目录
    "temp_path": os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp"),  # 临时文件路径
    "rainyun_login_url": "https://app.rainyun.com/auth/login",
    "rainyun_earn_url": "https://app.rainyun.com/account/reward/earn"
}

# 全局日志对象(仅日志全局化,核心变量均函数内初始化)
logger = logging.getLogger(__name__)

def init_logger():
    """初始化青龙面板日志格式(增强版)"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        handlers=[logging.StreamHandler(sys.stdout)]
    )
    # 打印项目信息
    logger.info("-"*80)
    logger.info("雨云签到工具 by SerendipityR ~")
    logger.info("Github发布页: https://github.com/SerendipityR-2022/Rainyun-Qiandao")
    logger.info("-"*80)
    logger.info("雨云签到工具容器版 by fatekey ~")
    logger.info("Github发布页: https://github.com/fatekey/Rainyun-Qiandao")
    logger.info("-"*80)
    logger.info("                   项目为二次开发青龙脚本化运行")
    logger.info("                     本项目基于上述项目开发")
    logger.info("                本项目仅作为学习参考,请勿用于其他用途")
    logger.info("-"*80)

def init_selenium() -> WebDriver:
    """初始化青龙面板专用Selenium驱动(每次调用新建实例,避免缓存污染)"""
    ops = Options()
    # 容器环境必需配置
    ops.add_argument("--no-sandbox")
    ops.add_argument("--disable-dev-shm-usage")
    ops.add_argument("--headless=new")
    ops.add_argument("--disable-gpu")
    ops.add_argument("--window-size=1920,1080")
    ops.add_argument("--user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
    # 反爬配置
    ops.add_experimental_option("excludeSwitches", ["enable-automation"])
    ops.add_experimental_option('useAutomationExtension', False)
    ops.add_argument("--disable-blink-features=AutomationControlled")
    
    # 青龙面板固定驱动路径校验
    driver_path = "/usr/bin/chromedriver"
    if not os.path.exists(driver_path) or not os.access(driver_path, os.X_OK):
        raise FileNotFoundError(
            f"青龙面板未安装chromium-driver!\n"
            f"请在青龙终端执行:apt update && apt install -y chromium-driver"
        )

    try:
        service = Service(executable_path=driver_path)
        driver = webdriver.Chrome(service=service, options=ops)
        # 清空缓存(双重保障)
        driver.delete_all_cookies()
        logger.info(f"✅ Selenium驱动初始化成功,路径:{driver_path}")
        return driver
    except WebDriverException as e:
        logger.error(f"❌ 驱动启动失败:{str(e)}")
        raise

def check_stealth_js() -> str:
    """检查青龙脚本目录下的stealth.min.js"""
    js_path = os.path.join(CONFIG["script_path"], "stealth.min.js")
    if not os.path.exists(js_path):
        logger.error(f"❌ 未找到stealth.min.js!请将文件上传到青龙脚本目录:{CONFIG['script_path']}")
        logger.info("📥 下载地址:https://raw.githubusercontent.com/berstend/puppeteer-extra/master/packages/puppeteer-extra-plugin-stealth/evasions/stealth.min.js")
        sys.exit(1)
    return js_path

def inject_stealth_js(driver: WebDriver):
    """注入反检测脚本(传入driver实例,解耦全局变量)"""
    js_path = check_stealth_js()
    with open(js_path, "r", encoding="utf-8") as f:
        js = f.read()
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": js})
    logger.info("✅ 已注入stealth.min.js反检测脚本")

def download_image(url: str, filename: str, img_index: int) -> bool:
    """下载图片(带URL日志+青龙面板加请求头防拦截)"""
    os.makedirs(CONFIG["temp_path"], exist_ok=True)
    try:
        logger.info(f"开始下载验证码图片({img_index}):{url}")
        headers = {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Referer": "https://app.rainyun.com/"
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        path = os.path.join(CONFIG["temp_path"], filename)
        with open(path, "wb") as f:
            f.write(response.content)
        return True
    except Exception as e:
        logger.error(f"❌ 下载图片失败 {url}:{str(e)}")
        return False

# ========== 工具函数(精简+健壮性优化) ==========
def get_url_from_style(style: str) -> Optional[str]:
    """从style属性提取URL"""
    try:
        match = re.search(r'url\(["\']?(.*?)["\']?\)', style)
        return match.group(1) if match else None
    except Exception:
        return None

def get_width_from_style(style: str) -> str:
    """从style属性提取宽度"""
    match = re.search(r'width:\s*([\d.]+)px', style)
    return match.group(1) if match else "300"

def get_height_from_style(style: str) -> str:
    """从style属性提取高度"""
    match = re.search(r'height:\s*([\d.]+)px', style)
    return match.group(1) if match else "150"

def compute_similarity(img1_path: str, img2_path: str) -> Tuple[float, int]:
    """青龙面板适配:SIFT不可用时用ORB(增加异常兜底)"""
    try:
        img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
        img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
        if img1 is None or img2 is None:
            logger.warning(f"❌ 图片读取失败:{img1_path} 或 {img2_path}")
            return 0.0, 0

        # 优先SIFT,降级ORB
        try:
            sift = cv2.SIFT_create()
            norm = cv2.NORM_L2
        except AttributeError:
            sift = cv2.ORB_create()
            norm = cv2.NORM_HAMMING
            logger.warning("⚠️ SIFT不可用,使用ORB匹配")

        kp1, des1 = sift.detectAndCompute(img1, None)
        kp2, des2 = sift.detectAndCompute(img2, None)
        if des1 is None or des2 is None:
            return 0.0, 0

        bf = cv2.BFMatcher(norm, crossCheck=False)
        matches = bf.knnMatch(des1, des2, k=2)
        good = [m for m, n in matches if m.distance < 0.8 * n.distance]
        similarity = len(good) / len(matches) if matches else 0.0
        return similarity, len(good)
    except Exception as e:
        logger.error(f"❌ 相似度计算失败:{str(e)}")
        return 0.0, 0

def download_captcha_img(driver: WebDriver, wait: WebDriverWait) -> bool:
    """下载并分割验证码图片(解耦全局变量)"""
    try:
        # 清空旧临时文件
        if os.path.exists(CONFIG["temp_path"]):
            for f in os.listdir(CONFIG["temp_path"]):
                os.remove(os.path.join(CONFIG["temp_path"], f))

        # 定位验证码背景图
        slideBg = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBg"]')))
        img1_url = get_url_from_style(slideBg.get_attribute("style"))
        if not img1_url or not download_image(img1_url, "captcha.jpg", 1):
            return False

        # 定位验证码碎片图
        sprite = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="instruction"]/div/img')))
        if not download_image(sprite.get_attribute("src"), "sprite.jpg", 2):
            return False

        # 分割碎片图
        raw = cv2.imread(os.path.join(CONFIG["temp_path"], "sprite.jpg"))
        if raw is None:
            logger.error("❌ 验证码碎片图读取失败")
            return False
        w = raw.shape[1]
        for i in range(3):
            cv2.imwrite(
                os.path.join(CONFIG["temp_path"], f"sprite_{i+1}.jpg"),
                raw[:, w//3*i : w//3*(i+1)]
            )
        return True
    except TimeoutException:
        logger.error("❌ 验证码图片加载超时")
        return False
    except Exception as e:
        logger.error(f"❌ 验证码图片处理失败:{str(e)}")
        return False

def check_answer(result: dict) -> bool:
    """检查验证码答案有效性(带识别率日志)"""
    valid = True
    for i in range(3):
        sim = float(result.get(f"sprite_{i+1}.similarity", 0))
        if sim < CONFIG["similarity_threshold"]:
            logger.error(f"⚠️ 图案{i+1}识别率{sim:.4f}低于阈值{CONFIG['similarity_threshold']}")
            valid = False
            break
    # 检查坐标唯一性
    positions = [result.get(f"sprite_{i+1}.position") for i in range(3)]
    if len(set(positions)) != 3:
        logger.error("❌ 验证码坐标重复,答案无效")
        valid = False
    return valid

def process_captcha(driver: WebDriver, wait: WebDriverWait) -> bool:
    """处理验证码(改递归为循环,提升健壮性,解耦全局变量)"""
    captcha_retry_count = 0
    ocr = ddddocr.DdddOcr(ocr=True, show_ad=False)
    det = ddddocr.DdddOcr(det=True, show_ad=False)

    while captcha_retry_count < CONFIG["max_captcha_retry"]:
        captcha_retry_count += 1
        logger.info(f"🔄 验证码处理第{captcha_retry_count}次尝试(最大{CONFIG['max_captcha_retry']}次)")
        try:
            # 下载验证码图片
            if not download_captcha_img(driver, wait):
                raise Exception("验证码图片下载失败")

            # 校验验证码有效性
            valid = True
            for i in range(3):
                sprite_path = os.path.join(CONFIG["temp_path"], f"sprite_{i+1}.jpg")
                with open(sprite_path, "rb") as f:
                    if ocr.classification(f.read()) in ["0", "1"]:
                        valid = False
                        break
            if not valid:
                raise Exception("验证码碎片无效")

            # 识别验证码
            captcha = cv2.imread(os.path.join(CONFIG["temp_path"], "captcha.jpg"))
            if captcha is None:
                raise Exception("验证码背景图读取失败")
            with open(os.path.join(CONFIG["temp_path"], "captcha.jpg"), "rb") as f:
                bboxes = det.detection(f.read())
            if not bboxes:
                raise Exception("未检测到验证码图案")

            # 匹配碎片与背景图
            result = {}
            for i, (x1, y1, x2, y2) in enumerate(bboxes):
                # 裁剪背景图中的图案
                cv2.imwrite(os.path.join(CONFIG["temp_path"], f"spec_{i+1}.jpg"), captcha[y1:y2, x1:x2])
                # 计算与每个碎片的相似度
                for j in range(3):
                    sim, _ = compute_similarity(
                        os.path.join(CONFIG["temp_path"], f"sprite_{j+1}.jpg"),
                        os.path.join(CONFIG["temp_path"], f"spec_{i+1}.jpg")
                    )
                    key_sim = f"sprite_{j+1}.similarity"
                    key_pos = f"sprite_{j+1}.position"
                    if sim > float(result.get(key_sim, 0)):
                        result[key_sim] = sim
                        result[key_pos] = f"{int((x1+x2)/2)},{int((y1+y2)/2)}"

            # 校验答案
            if not check_answer(result):
                raise Exception("验证码答案无效")

            # 打印匹配结果
            for i in range(3):
                pos = result[f"sprite_{i+1}.position"]
                sim = result[f"sprite_{i+1}.similarity"]
                x, y = pos.split(",")
                logger.info(f"🎯 图案 {i+1} 坐标({x},{y}),匹配率:{sim:.4f}")

            # 点击验证码图案
            slideBg = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBg"]')))
            style = slideBg.get_attribute("style")
            width, height = float(get_width_from_style(style)), float(get_height_from_style(style))
            width_raw, height_raw = captcha.shape[1], captcha.shape[0]

            for i in range(3):
                pos = result[f"sprite_{i+1}.position"]
                x, y = map(int, pos.split(","))
                # 计算实际点击坐标(适配页面缩放)
                final_x = int(-width/2 + x/width_raw * width) + random.randint(-1, 1)
                final_y = int(-height/2 + y/height_raw * height) + random.randint(-1, 1)
                ActionChains(driver).move_to_element_with_offset(slideBg, final_x, final_y).click().perform()
                time.sleep(random.uniform(0.5, 1))

            # 提交验证码
            logger.info("📤 提交验证码")
            confirm = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="tcStatus"]/div[2]/div[2]/div/div')))
            confirm.click()
            time.sleep(5)

            # 校验验证码结果
            tc_operation = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="tcOperation"]')))
            if tc_operation.get_attribute("class") == "tc-opera pointer show-success":
                logger.info("✅ 验证码验证通过")
                return True
            else:
                raise Exception("验证码验证失败")

        except Exception as e:
            logger.error(f"❌ 验证码处理失败:{str(e)}")
            # 刷新验证码重试
            try:
                logger.error("⏳ 刷新验证码中,稍后重试……")
                reload = driver.find_element(By.XPATH, '//*[@id="reload"]')
                time.sleep(3)
                reload.click()
                time.sleep(min(3 * (2 ** (captcha_retry_count - 1)), 30))  # 指数退避重试间隔,上限30秒
            except NoSuchElementException:
                logger.error("❌ 验证码刷新按钮未找到,重试失败")
                return False

    logger.error(f"❌ 验证码重试{CONFIG['max_captcha_retry']}次仍失败,放弃")
    return False

def clean_temp():
    """清理青龙面板临时文件(增加容错)"""
    try:
        if os.path.exists(CONFIG["temp_path"]):
            for f in os.listdir(CONFIG["temp_path"]):
                file_path = os.path.join(CONFIG["temp_path"], f)
                try:
                    os.remove(file_path)
                except Exception as e:
                    logger.warning(f"⚠️ 删除临时文件{file_path}失败:{str(e)}")
            os.rmdir(CONFIG["temp_path"])
        logger.info("✅ 临时文件清理完成")
    except Exception as e:
        logger.warning(f"⚠️ 清理临时文件失败:{str(e)}")

def parse_accounts() -> List[List[str]]:
    """解析青龙面板RAINYUN_ACCOUNT环境变量"""
    account_str = os.getenv("RAINYUN_ACCOUNT")
    if not account_str:
        logger.error("❌ 未配置RAINYUN_ACCOUNT环境变量!格式应为[[账号1,密码1],[账号2,密码2]]")
        sys.exit(1)
    
    try:
        # 解析JSON格式的账号列表(兼容单引号/双引号)
        account_str = account_str.replace("'", "\"")  # 统一为双引号
        accounts = json.loads(account_str)
        # 校验格式
        if not isinstance(accounts, list):
            raise ValueError("环境变量值不是列表类型")
        for idx, account in enumerate(accounts):
            if not isinstance(account, list) or len(account) != 2:
                raise ValueError(f"第{idx+1}个账号格式错误,应为[账号,密码]")
            if not account[0] or not account[1]:
                raise ValueError(f"第{idx+1}个账号/密码为空")
        logger.info(f"✅ 成功解析{len(accounts)}个账号")
        return accounts
    except json.JSONDecodeError as e:
        logger.error(f"❌ RAINYUN_ACCOUNT格式解析失败:{str(e)},请检查格式是否为合法JSON")
        sys.exit(1)
    except ValueError as e:
        logger.error(f"❌ RAINYUN_ACCOUNT格式错误:{str(e)}")
        sys.exit(1)

def sign_in_rainyun(username: str, password: str):
    """单账号签到核心逻辑(独立封装,支持多账号循环调用)"""
    driver = None
    try:
        logger.info(f"\n========== 开始处理账号:{username} ==========")
        # 随机延时(可选)
        delay = random.randint(0, CONFIG["max_delay"])
        delay_sec = random.randint(0, 60)
        logger.info(f"⏳ 随机延时 {delay} 分钟 {delay_sec} 秒")
        time.sleep(delay * 60 + delay_sec)

        # 初始化Selenium(每次新建实例,清空缓存)
        driver = init_selenium()
        inject_stealth_js(driver)
        wait = WebDriverWait(driver, CONFIG["timeout"])

        # 访问登录页
        logger.info("⏳ 发起登录请求")
        logger.info("🌐 访问雨云登录页")
        driver.get(CONFIG["rainyun_login_url"])
        logger.info(f"页面标题:{driver.title}")

        # 输入账号密码
        logger.info("⏳ 等待登录表单元素加载...")
        username_elem = wait.until(EC.visibility_of_element_located((By.NAME, "login-field")))
        password_elem = wait.until(EC.visibility_of_element_located((By.NAME, "login-password")))
        login_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div[1]/div[1]/div/div[2]/fade/div/div/span/form/button')))
        logger.info("📝 输入账号密码")
        username_elem.send_keys(username)
        password_elem.send_keys(password)
        login_btn.click()
        logger.info("⏳ 正在登录中,耗时较长请稍等……")
        time.sleep(3)

        # 处理登录验证码
        try:
            wait.until(EC.visibility_of_element_located((By.ID, "tcaptcha_iframe_dy")))
            logger.warning("⚠️ 触发登录验证码")
            driver.switch_to.frame("tcaptcha_iframe_dy")
            if not process_captcha(driver, wait):
                raise Exception("登录验证码验证失败")
        except TimeoutException:
            logger.info("✅ 未触发登录验证码")

        # 校验登录状态
        time.sleep(5)
        driver.switch_to.default_content()
        logger.info(f"当前页面: {driver.current_url}")
        logger.info(f"页面标题: {driver.title}")
        if driver.current_url != "https://app.rainyun.com/dashboard":
            raise Exception("登录失败!请检查账号密码或网络")
        user_name = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/nav/div[1]/ul/div[6]/li/a/div/div/p').text.strip()
        logger.info(f"✅ 账号登录成功:{user_name}")
        
        # 访问签到页
        logger.info("🌐 访问赚取积分页")
        driver.get(CONFIG["rainyun_earn_url"])
        driver.implicitly_wait(5)
        logger.info(f"当前页面: {driver.current_url}")
        logger.info(f"页面标题: {driver.title}")

        # 查找并点击签到按钮
        logger.info("🔍 查找每日签到按钮")
        earn_btn_qddiv = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[3]/div[2]/div/div/div[2]/div[2]/div/div/div/div[1]/div')
        earn_btn_qd = earn_btn_qddiv.find_element(By.XPATH, './/span[contains(text(),"每日签到")]')
        status_elem = earn_btn_qd.find_element(By.XPATH, './following-sibling::span[1]')
        status_text = status_elem.text.strip()

        if status_text == "领取奖励":
            earn_btn = status_elem.find_element(By.XPATH, './a')
            logger.info(f"📌 签到状态:{status_text},开始领取")
            earn_btn.click()

            # 处理签到验证码
            logger.info("⚠️ 触发签到验证码")
            driver.switch_to.frame("tcaptcha_iframe_dy")
            if not process_captcha(driver, wait):
                raise Exception("签到验证码验证失败")
            driver.switch_to.default_content()

            # 校验签到结果
            time.sleep(5)
            logger.info("✅ 签到奖励领取成功")
        else:
            logger.info(f"📌 签到状态:{status_text},无需重复签到")

        # 获取当前积分
        try:
            points_elem = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[3]/div[2]/div/div/div[2]/div[1]/div[1]/div/p/div/h3')
            current_points = int(''.join(re.findall(r'\d+', points_elem.text)))
            logger.info(f"💰 当前积分:{current_points}(约{current_points/2000:.2f}元)")
        except Exception as e:
            logger.warning(f"⚠️ 积分获取失败:{str(e)}")

        

    except Exception as e:
        logger.error(f"❌ 账号{username}处理失败:{str(e)}", exc_info=True)
    finally:
        # 关闭浏览器,彻底清空缓存
        if driver:
            try:
                driver.quit()
                logger.info(f"✅ 账号{username}浏览器已关闭")
            except Exception as e:
                logger.warning(f"⚠️ 关闭浏览器失败:{str(e)}")
        # 清理临时文件
        clean_temp()
    logger.info(f"\n========== 账号{username}处理完成 ==========\n")

def main():
    """主函数:解析多账号,依次执行签到"""
    init_logger()
    # 解析账号列表
    accounts = parse_accounts()
    # 依次处理每个账号
    for idx, (username, password) in enumerate(accounts, 1):
        logger.info(f"\n================= 处理第{idx}个账号 ==================")
        sign_in_rainyun(username, password)
        # 账号间间隔(可选)
        time.sleep(random.uniform(2, 5))
    
    logger.info("\n🎉 所有账号处理完成!")

if __name__ == "__main__":
    main()

五、最后

后面的设置定时任务之类的就懒得写啦,顺便我也懒得写通知之类的了,感谢前人的开发让我站于巨人肩膀上,要是有后来者优化了就更好了

哦,对了,懒得上传 github 了,就丢 linux.do 里好了


📌 转载信息
原作者:
T_ACGN
转载时间:
2026/1/24 07:01:47

小安装青龙面板并配置 iKuu 自动签到

今晚买了个 42 的小鸡,不知道该咋玩,哈基米说可以搞个自动签到。于是就有了这篇文章,写下来是为了记录一下,万一有谁也需要呢?

购买小鸡的情况:1c0.5G

安装 Docker

# 1. 安装基础依赖
apt update && apt install -y curl

# 2. 使用官方脚本安装 Docker
curl -fsSL https://get.docker.com | bash -s docker

# 3. 启动 Docker 并查看状态
systemctl enable --now docker
docker ps

部署青龙面板

因为内存很小,且没办法添加交换分区,所以这是哈基米给我的命令:

docker run -dit \
  -v $PWD/ql/data:/ql/data \
  -p 5700:5700 \
  --name qinglong \
  --hostname qinglong \
  --restart always \
  --memory=300m \
  whyour/qinglong:latest

添加端口规则

添加一条规则:

  • 内网端口5700
  • 外网端口:随便填一个(比如 15700),或者面板会自动给你分配一个。
  • 协议:TCP。

完成后,你在浏览器访问:http://主机的公网IP:分配给你的外网端口

确认容器状态

# 查看状态
docker ps -a

# 查看日志
docker logs -f qinglong

到此基本就可以正常访问青龙面板了

那么如何配置自动签到脚本呢?可以参考 https://blog.uptoz.cn/archives/vVNl4laL

需要注意的是

脚本里面使用到了 requests、beautifulsoup4。青龙面板虽然有 python,但是这些包没有安装,你可以在终端手动安装:

# 进入青龙容器内部安装
docker exec -it qinglong pip3 install requests beautifulsoup4 -i https://pypi.tuna.tsinghua.edu.cn/simple

尝试

接下来就可以在面板-定时任务 运行一下看看啦

纯纯纯纯纯新手,大家还有什么好玩的东西或者脚本可以介绍一下嘛

📌 转载信息
原作者:
JackyLiii
转载时间:
2026/1/20 10:20:33

自己日常用青龙面板搞自动化,看到好项目都忍不住想往上搬

这次发现佬友 mumuladu 的 A 股 AI 分析神器,可惜不支持青龙,于是手痒改了一版,分享给同样用青龙的朋友们~

  • 适配青龙定时任务,收盘自动跑
  • 支持 20+ 推送渠道,报告直达手机

感谢原作者开源!开源精神万岁!

daily_stock_analysis_ql

附上几个截图


📌 转载信息
转载时间:
2026/1/18 09:09:09

HidenCloud 全自动续期 & 账单自动支付脚本 (青龙面板版)

这是一个用于 HidenCloud 免费服务器自动续期和自动支付账单的青龙面板脚本。

原帖:https://linux.do/t/topic/1393805
感谢 Y 佬的教程

HidenCloud 的免费机器虽然好用,但机制比较繁琐,本脚本实现了全流程自动化,自动续期 + 支付 + 自动读写 cookie。

建议手动续期 84 天后,每 7 天执行一次,避免错过续期窗口


功能特点

  1. 全流程自动化:自动识别账号下的所有服务 → 自动提交续期请求 → 自动跳转账单页 → 自动完成 0 元支付
  2. 智能支付逻辑
    • 脚本会自动解析账单页面 HTML。
    • 动态提取隐藏的支付参数。
  3. Cookie 自动续命 (持久化)
    • 脚本运行期间会自动捕获服务器返回的新 Cookie。
    • 将最新 Cookie 保存到本地 hiden_cookies.json 文件。
    • 优势:只要脚本每天运行,理论上无需再手动更新环境变量中的 Cookie。
  4. 多账号支持:支持无限个账号,通过换行或 & 符号分隔。
  5. 防检测机制
    • 内置随机延迟(3-8 秒),模拟真人操作。
    • 伪装完整的 Chrome 浏览器 Headers,降低被 Cloudflare 拦截的风险。
  6. 消息推送:对接青龙面板的通知系统,任务完成后发送续期结果。


使用方法

1. 准备工作

确保你的青龙面板已安装以下 Node.js 依赖(在 依赖管理NodeJs 中添加):

  • axios
  • cheerio

2. 添加脚本

在青龙面板 脚本管理 中新建脚本,名称随意(例如 hiden_renew.js),将代码完全粘贴进去。

自定义续期天数:脚本第 23 行,将数字 10 修改为你想要的天数即可。
const RENEW_DAYS = 10;

青龙脚本 hiden_renew.js
/*
new Env('HidenCloud 自动续期-毕业版');
cron: 0 0 10 * * ?
checks: 自动续期、自动支付、Cookie自动持久化、消息推送
*/

const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');

// 尝试加载 notify,如果没有也不影响运行
let sendNotify = () => {};
try {
    const notify = require('./sendNotify');
    sendNotify = notify.sendNotify;
} catch (e) {
    console.log('未找到 sendNotify,跳过推送');
}

// 环境变量
const HIDEN_COOKIES_ENV = process.env.HIDEN_COOKIE ? process.env.HIDEN_COOKIE.split(/[&\n]/) : [];
const RENEW_DAYS = 10;
const CACHE_FILE = path.join(__dirname, 'hiden_cookies.json');

// 汇总消息
let summaryMsg = '';

const sleep = (min = 3000, max = 8000) => {
    const delay = Math.floor(Math.random() * (max - min + 1)) + min;
    return new Promise(resolve => setTimeout(resolve, delay));
};

// 本地缓存管理
const CacheManager = {
    load() {
        if (fs.existsSync(CACHE_FILE)) {
            try {
                return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
            } catch (e) {
                console.log('读取缓存文件失败,将重新创建');
            }
        }
        return {};
    },
    save(data) {
        fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));
    },
    get(index) {
        const data = this.load();
        return data[index] || null;
    },
    update(index, cookieStr) {
        const data = this.load();
        data[index] = cookieStr;
        this.save(data);
        console.log(`💾 [账号 ${index + 1}] 最新 Cookie 已保存到本地缓存`);
    }
};

class HidenCloudBot {
    constructor(envCookie, index) {
        this.index = index + 1;
        this.envCookie = envCookie;
        this.cookieData = {};
        this.logMsg = []; // 存储该账号的日志用于推送
        
        // 优先尝试读取缓存
        const cachedCookie = CacheManager.get(this.index - 1);
        if (cachedCookie) {
            console.log(`[账号 ${this.index}] 发现本地缓存 Cookie,优先使用...`);
            this.parseCookieStr(cachedCookie);
        } else {
            console.log(`[账号 ${this.index}] 使用环境变量 Cookie...`);
            this.parseCookieStr(envCookie);
        }

        this.commonHeaders = {
            'Host': 'dash.hidencloud.com',
            'Connection': 'keep-alive',
            'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
            'sec-ch-ua-mobile': '?0',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
            'Referer': 'https://dash.hidencloud.com/',
        };

        this.client = axios.create({
            baseURL: 'https://dash.hidencloud.com',
            maxRedirects: 0, 
            validateStatus: status => status >= 200 && status < 500,
            timeout: 30000 
        });
        
        this.services = [];
        this.csrfToken = ''; 
    }

    log(msg) {
        console.log(`[账号 ${this.index}] ${msg}`);
        this.logMsg.push(msg);
    }

    parseCookieStr(str) {
        if (!str) return;
        str.split(';').forEach(pair => {
            const idx = pair.indexOf('=');
            if (idx > 0) {
                const key = pair.substring(0, idx).trim();
                const val = pair.substring(idx + 1).trim();
                if (!['path', 'domain', 'expires', 'httponly', 'secure', 'samesite'].includes(key.toLowerCase())) {
                    this.cookieData[key] = val;
                }
            }
        });
    }

    updateCookiesFromResponse(headers) {
        const setCookie = headers['set-cookie'];
        if (setCookie) {
            setCookie.forEach(sc => {
                const firstPart = sc.split(';')[0];
                const idx = firstPart.indexOf('=');
                if (idx > 0) {
                    const key = firstPart.substring(0, idx).trim();
                    const val = firstPart.substring(idx + 1).trim();
                    this.cookieData[key] = val;
                }
            });
            // 每次更新 Cookie 都保存到本地
            CacheManager.update(this.index - 1, this.getCookieStr());
        }
    }

    getCookieStr() {
        return Object.keys(this.cookieData).map(k => `${k}=${this.cookieData[k]}`).join('; ');
    }

    async request(method, url, data = null, extraHeaders = {}) {
        let currentUrl = url;
        let methodToUse = method;
        let finalResponse = null;

        const requestHeaders = {
            ...this.commonHeaders,
            ...extraHeaders,
            'Cookie': this.getCookieStr()
        };

        if (methodToUse === 'POST' && !requestHeaders['Content-Type']) {
            requestHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
        }

        try {
            const res = await this.client({
                method: methodToUse,
                url: currentUrl,
                headers: requestHeaders,
                data: data
            });
            
            this.updateCookiesFromResponse(res.headers);
            res.finalUrl = currentUrl; 
            finalResponse = res;

            if (res.status === 301 || res.status === 302) {
                const location = res.headers['location'];
                if (location) {
                    this.log(`🔄 重定向 -> ${location}`);
                    currentUrl = location.startsWith('http') ? location : `https://dash.hidencloud.com${location.startsWith('/') ? '' : '/'}${location}`;
                    return this.request('GET', currentUrl);
                }
            }
            finalResponse.finalUrl = currentUrl;
            return finalResponse;
        } catch (err) {
            throw err;
        }
    }

    extractTokens($) {
        const metaToken = $('meta[name="csrf-token"]').attr('content');
        if (metaToken) this.csrfToken = metaToken;
    }

    async init() {
        this.log('正在验证登录状态...');
        try {
            const res = await this.request('GET', '/dashboard');
            
            // 检查失效
            if (res.headers.location && res.headers.location.includes('/login')) {
                 this.log('❌ 当前 Cookie 已失效');
                 return false;
            }

            const $ = cheerio.load(res.data);
            this.extractTokens($);

            // 解析服务列表
            $('a[href*="/service/"]').each((i, el) => {
                const href = $(el).attr('href');
                const match = href.match(/\/service\/(\d+)\/manage/);
                if (match) {
                    this.services.push({ id: match[1], url: href });
                }
            });
            this.services = this.services.filter((v, i, a) => a.findIndex(t => t.id === v.id) === i);

            this.log(`✅ 登录成功,发现 ${this.services.length} 个服务。`);
            return true;
        } catch (e) {
            this.log(`❌ 初始化异常: ${e.message}`);
            return false;
        }
    }

    // 重置为环境变量 Cookie (用于缓存失效时重试)
    resetToEnv() {
        this.cookieData = {};
        this.parseCookieStr(this.envCookie);
        console.log(`[账号 ${this.index}] 切换回环境变量原始 Cookie 重试...`);
    }

    async processService(service) {
        await sleep(2000, 4000);
        this.log(`>>> 处理服务 ID: ${service.id}`);

        try {
            const manageRes = await this.request('GET', `/service/${service.id}/manage`);
            const $ = cheerio.load(manageRes.data);
            const formToken = $('input[name="_token"]').val();

            this.log(`提交续期 (${RENEW_DAYS}天)...`);
            await sleep(1000, 2000); 

            const params = new URLSearchParams();
            params.append('_token', formToken);
            params.append('days', RENEW_DAYS);

            const res = await this.request('POST', `/service/${service.id}/renew`, params, {
                'X-CSRF-TOKEN': this.csrfToken,
                'Referer': `https://dash.hidencloud.com/service/${service.id}/manage`
            });
            
            if (res.finalUrl && res.finalUrl.includes('/invoice/')) {
                this.log(`⚡️ 续期成功,前往支付`);
                await this.performPayFromHtml(res.data, res.finalUrl);
            } else {
                this.log('⚠️ 续期后未跳转,检查列表...');
                await this.checkAndPayInvoices(service.id);
            }

        } catch (e) {
            this.log(`处理异常: ${e.message}`);
        }
    }

    async checkAndPayInvoices(serviceId) {
        await sleep(2000, 3000);
        try {
            const res = await this.request('GET', `/service/${serviceId}/invoices?where=unpaid`);
            const $ = cheerio.load(res.data);
            
            const invoiceLinks = [];
            $('a[href*="/invoice/"]').each((i, el) => {
                const href = $(el).attr('href');
                if (href && !href.includes('download')) invoiceLinks.push(href);
            });

            const uniqueInvoices = [...new Set(invoiceLinks)];
            if (uniqueInvoices.length === 0) {
                this.log(`✅ 无未支付账单`);
                return;
            }

            for (const url of uniqueInvoices) {
                await this.paySingleInvoice(url);
                await sleep(3000, 5000); 
            }
        } catch (e) {
            this.log(`查账单出错: ${e.message}`);
        }
    }

    async paySingleInvoice(url) {
        try {
            this.log(`📄 打开账单: ${url}`);
            const res = await this.request('GET', url);
            await this.performPayFromHtml(res.data, url);
        } catch (e) {
            this.log(`访问失败: ${e.message}`);
        }
    }

    async performPayFromHtml(html, currentUrl) {
        const $ = cheerio.load(html);
        
        let targetForm = null;
        let targetAction = '';
        
        $('form').each((i, form) => {
            const btnText = $(form).find('button').text().trim().toLowerCase();
            const action = $(form).attr('action');
            if (btnText.includes('pay') && action && !action.includes('balance/add')) {
                targetForm = $(form);
                targetAction = action;
                return false; 
            }
        });

        if (!targetForm) {
            this.log(`⚪ 页面未找到支付表单 (可能已支付)。`);
            return;
        }

        const payParams = new URLSearchParams();
        targetForm.find('input').each((i, el) => {
            const name = $(el).attr('name');
            const value = $(el).val();
            if (name) payParams.append(name, value || '');
        });

        this.log(`👉 提交支付...`);
        
        try {
            const payRes = await this.request('POST', targetAction, payParams, {
                'X-CSRF-TOKEN': this.csrfToken,
                'Referer': currentUrl
            });

            if (payRes.status === 200) {
                 this.log(`✅ 支付成功!`);
            } else {
                this.log(`⚠️ 支付响应: ${payRes.status}`);
            }
        } catch (e) {
            this.log(`❌ 支付失败: ${e.message}`);
        }
    }
}

(async () => {
    if (HIDEN_COOKIES_ENV.length === 0) {
        console.log('❌ 未配置环境变量 HIDEN_COOKIE');
        return;
    }
    
    console.log(`=== HidenCloud 续期脚本启动 (账号数: ${HIDEN_COOKIES_ENV.length}) ===\n`);

    for (let i = 0; i < HIDEN_COOKIES_ENV.length; i++) {
        const bot = new HidenCloudBot(HIDEN_COOKIES_ENV[i], i);
        
        // 第一次尝试(可能用的是缓存)
        let success = await bot.init();
        
        // 如果失败,且当前用的是缓存,则回退到环境变量重试
        if (!success && CacheManager.get(i)) {
            bot.resetToEnv();
            success = await bot.init();
        }

        if (success) {
            for (const svc of bot.services) {
                await bot.processService(svc);
            }
            summaryMsg += `账号 ${i + 1}: 成功续期 ${bot.services.length} 个服务\n`;
        } else {
            summaryMsg += `账号 ${i + 1}: 登录失败,请更新 Cookie\n`;
        }
        
        console.log('\n----------------------------------------\n');
        if (i < HIDEN_COOKIES_ENV.length - 1) await sleep(5000, 10000);
    }

    // 发送推送
    if (summaryMsg) {
        await sendNotify('HidenCloud 续期报告', summaryMsg);
    }
})();

3. 设置环境变量

环境变量 中添加变量:

变量名必填说明
HIDEN_COOKIE你的 HidenCloud 面板 Cookie

如何获取 Cookie:

  1. 浏览器打开并登录 HidenCloud Dashboard
  2. F12 打开开发者工具,点击 网络 (Network) 标签。
  3. 刷新页面,点击第一个请求( dashboardmanage)。
  4. 在右侧 请求头 (Request Headers) 中找到 Cookie,复制后面的一长串内容。

多账号设置:
如果有多个账号,直接新建多个同名变量 HIDEN_COOKIE,或者在一个变量值里用 & 或换行符分隔。

4. 设置定时任务

建议手动续期 84 天后,每 7 天执行一次,避免错过续期窗口。
Cron 表达式示例:0 10 */7 * * (每 7 天上午 10 点执行)


消息推送配置说明

本脚本已深度集成青龙面板自带的通知系统 (sendNotify.js)。你只需要在青龙面板配置好推送方式,脚本运行结束后就会自动发送报告。

支持的推送渠道

微信 (Server 酱 / 企业微信)、Telegram、钉钉、飞书、Bark、PushPlus 等青龙支持的所有渠道。

配置步骤

  1. 打开青龙面板 → 系统设置通知设置
  2. 选择你喜欢的推送方式(例如 PushPlusTelegram)。
  3. 填入相应的 Token 或 Key,点击保存并测试。
  4. 无需修改脚本代码。脚本会自动检测青龙的通知配置。

推送效果预览

任务完成后,你会收到类似如下的通知:

HidenCloud 续期报告

账号 1: 成功续期 2 个服务
账号 2: 成功续期 1 个服务
账号 3: 登录失败,请更新 Cookie


脚本逻辑说明

  1. 初始化:脚本启动时,优先读取本地缓存文件 hiden_cookies.json 中的 Cookie。如果缓存不存在或失效,则回退使用环境变量 HIDEN_COOKIE
  2. 检测:登录 Dashboard,自动扫描账号下所有活跃的服务 ID。
  3. 续期:进入管理页面,获取 CSRF Token,提交续期 10 天的请求。
  4. 支付
    • 续期成功后,脚本会自动检测是否跳转到了 Invoice 页面。
    • 如果是,直接在当前页面提取表单参数并提交支付。
    • 如果未跳转,脚本会额外检查 “未支付账单” 列表,确保没有漏网之鱼。
  5. 保存:运行结束时,将最新的有效 Cookie 写入本地缓存,供下次使用。


常见问题

Q: 提示 403 Forbidden / Cloudflare 拦截?
A: 这通常是因为你的青龙面板服务器 IP (如阿里云、腾讯云数据中心 IP) 被 Cloudflare 拉黑了。

  • 解决方法:尝试在本地电脑(家庭宽带)运行脚本,或者给青龙面板配置代理。

Q: 为什么日志显示 “支付成功” 但网页看还是未支付?
A: HidenCloud 后端偶尔有延迟。只要日志显示 Status 200支付成功,通常稍等几分钟刷新网页即可变更为 Paid。

Q: 必须要手动抓包 Cookie 吗?
A: 第一次必须手动抓取。之后脚本会自动维护 Cookie,除非服务器强制登出所有会话,否则不需要频繁更新。


免责声明

本脚本仅供学习交流使用,请勿用于非法用途。使用本脚本产生的任何后果由使用者自行承担。



📌 转载信息
转载时间:
2026/1/14 10:45:15

之前说过了,最近在折腾这玩意儿,刚好这里有视频教程,就分享到这儿来了,当然,视频是群友分享的,不是我自己做的。

1.宝塔和青龙面板的安装

视频教程
[bsplayer url="https://blog.xiaohack.org/usr/uploads/2023/06/baota.mp4" image="视频封面图地址"]
**1.准备一个服务器
2.用宝塔终端 连接服务器
3.安装宝塔**

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh

外网面板地址: https://175.178.154.165:15358/4c62bbe1
内网面板地址: https://10.0.12.10:15358/4c62bbe1
username: ret7agyh
password: b60feda5

4.安装青龙面板 http://175.178.154.165:8082

docker run -dit \
-v /root/ql/config:/ql/config \
-v /root/ql/log:/ql/log \
-v /root/ql/db:/ql/db \
-v /root/ql/scripts:/ql/scripts \
-v /root/ql/jbot:/ql/jbot \
-v /root/ql/repo:/ql/repo \
-p 5701:5700 \
-e ENABLE_HANGUP=true \
-e ENABLE_WEB_PANEL=true \
--name ql \
--hostname ql \
--privileged=true \
--restart always \
whyour/qinglong:2.10.13
(想改青龙面板端口的话就把其中的  5701:5700 改成 XXXX:5700即可,冒号后的5700别动!)
"http://gh.301.ee/"        #代理

京东库

faker3.

ql repo https://github.com/shufflewzc/faker3.git "jd_|jx_|gua_|jddj_|jdCookie" "activity|backUp" "^jd[^_]|USER|function|utils|sendNotify|ZooFaker_Necklace.js|JDJRValidator_|sign_graphics_validate|ql|JDSignValidator" "main" 

怨念

ql repo https://github.com/yuannian1112/jd_scripts.git "jd_|jx_|getJDCookie" "activity|backUp" "^jd[^_]|USER|utils"

青蛙

ql repo https://github.com/smiek2121/scripts.git "jd_|gua_" "" "ZooFaker_Necklace.js|JDJRValidator_Pure.js|sign_graphics_validate.js"

6dylan6

ql repo https://js.nbplay.site/https://github.com/6dylan6/jdpro.git "jd_|jx_|jddj_" "backUp" "^jd[^_]|USER|JD|function|sendNotify"    

2.奥特曼+机器人登录

前面的 宝塔加青龙面板 默认安装完成的
[bsplayer url="https://blog.xiaohack.org/usr/uploads/2023/06/jiqiren.mp4" image="视频封面图地址"]

1.奥特曼一键指令

s=autMan;f=fanli;a=arm64;if [[ $(uname -a | grep "x86_64") != "" ]];then a=amd64;fi ;if [ ! -d $s ];then mkdir $s;fi ;cd $s;wget https://github.com/hdbjlizhe/${f}/releases/download/main/autMan_$a.tar.gz && tar -zxvf autMan_$a.tar.gz && rm -rf autMan_$a.tar.gz && chmod 777 $s;pkill -9 $s;$(pwd)/$s -t;

2.上面设置完毕后

1.输入青龙管理 2.在输入0(就是增加容器) 3.按照提示输入

设置完毕 自己访问外网地址
Web后台外网地址:http://175.178.154.165:8080
Web后台内网地址:http://10.0.12.10:8080

奥特曼 一键重启指令 (不掉线的话基本不用)

/root/autMan/autMan -t

3.短信登录+对接奥特曼+掉线说明

[bsplayer url="https://blog.xiaohack.org/usr/uploads/2023/06/duanxin.mp4" image="视频封面图地址"]

  1. 在root创立go-cqhttp文件夹
  2. 上传go-cqhttp_linux_amd64.tar压缩包到go-cqhttp文件夹
  3. 解压go-cqhttp
    tar xvf go-cqhttp_linux_amd64.tar.gz
  4. cd /root/go-cqhttp
    ./go-cqhttp
  5. ./go-cqhttp -d #后台运行

127.0.0.1:8080/qq/receive

4.短信登录

键安装docker版本MaiARK脚本:
bash <(curl -s -S -L https://maiark-1256973477.cos.ap-shanghai.myqcloud.com/kiss.sh)
选择11
选择1
剩下默认
全部默认回车

安装完毕后
然后去改一下配置文件arkconfig.json 默认的话在/root/MaiARK这个路径。

服务器地址写青龙ip:端口
青龙客户端id以及秘钥就是青龙面板里面添加应用出来的(看视频)

http://175.178.154.165:8082

5.奥特曼autman命令大全

基础配置

set autMan name 奥特曼 #设置奥特曼机器人名
set autMan port 8080 #设置奥特曼http服务端口
set autMan duration 5 #奥特曼消息撤回等待时间,单位秒
set autMan update_notify false #奥特曼自动升级是否通知
set autMan auto_update true #是否开启奥特曼自动更新
set reply 打赏 [CQ:image,file=https://xxxxxxx] #奥特曼内置赞赏码
set autMan enable_http_server true #是否启动http服务,对接微信公众号等需要,建议开启
set autMan ignore_notify true # 奥特曼忽略通知命令,默认忽略。
set qq spy_on ? # 返利间谍模式
set autMan pushplus [token] # 管理员推送绑定pushplus指令
set autMan recall 关键词1&关键词2... # 关键词撤回功能#关键词支持正则表达式。
set reply ? ? ## 关键词回复功能 第一个问号是支持正则的关键词,第二个问号是回复的内容。
delete reply ? #删除用set设置的关键词回复
reply ? ? ## 关键词回复功能 第一个问号是支持正则的关键词,第二个问号是回复的内容。
reply ? nil ##删除reply设置的关键词回复,请区别于用set reply设置关键词的删除方法。
set autMan recall [\s\S]1[0-9a-zA-Z]{14}2[\s\S] # 屏蔽京东口令小妙招
重启 #重启并静默运行
命令 #获取奥特曼的命令列表
守护奥特曼 #解决开机自启和崩溃重启
systemctl disable autMan #linux命令,关闭守护模式,守护模式会导致没法自动升级
systemctl stop autMan && systemctl disable autMan #linux命令,遇见奥特曼被被杀死,请执行命令
docker-compose up -d --build #linux命令,docker运行

对接qq

set qq tempMessageGroupCode ? #设置qq临时消息默认群号
set qq onGroups g1&g2&g3... #指定要监听的qq群
set qq auto_friend false #设置是否自动同意好友请求,似乎没用,不用在意。
set qq onself true #设置是否对监听自身消息
set qq default_bot 主机器人账号 #奥特曼支持对接多个qq,设置主qq机器人
set qq masters q1&q2&q3... 设置qq管理员
set qq notifier q1&q2&q3... 设置接受通知的qq账号

对接telegtam

set tg token ? #设置telegram机器人token
set tg http_proxy ? #设置telegram机器人代理
set tg masters t1&t2&t3... #设置telegram机器人管理员
set tg notifier t1&t2&t3... 设置接受通知的telegram账号

对接微信公众号

set wxmp app_id ? #设置微信公众平台app_id
set wxmp app_secret ? #设置微信公众平台app_secret
set wxmp token ? #设置微信公众平台token
set wxmp encoding_aes_key ? #设置微信公众平台encoding_aes_key
set wxmp masters w1&w2&w3 #设置微信公众平台管理员
set wxmp subscribe_reply ? #设置公众号关注事件回复
set wxmp default_reply 无法回复该消息 设置公众号默认回复

对接微信-可爱猫

set wx api_url ? #设置插件调用地址,确保奥特曼可以访问可爱猫端口
set wx keaimao_dynamic_ip true #设置可爱猫是否动态网络地址,适用于可爱猫家庭宽带而奥特曼在云服务器的情况下
set wx keaimao_port ? #设置可爱猫端口
set wx relay_mode true #设置图片转发模式,否则可能会出现此图片来自xx未经允许不得使用的提示
set wx relaier ? #设置指定转发地址,格式为 https://域名/relay?url=%s,不知道不用填
set wx autMan_dynamic_ip true #设置奥特曼是否动态网络地址,适用于奥特曼家庭宽带而可爱猫在云服务器的情况下
set autMan enable_http_server true #启动http服务,一定要打开

对接微信-vlw

set wx vlw_addr http://vlw插件ip:端口 #设置插件调用地址,对应之前插件配置的 序号3 HTTP 外网API调用地址
set wx vlw_token XXX #设置对接vlw插件的token,对应之前插件配置的 序号2 API调用Token,例如autMan
set wx relay_mode true #设置图片转发模式,否则可能会出现此图片来自xx未经允许不得使用的提示。不懂就不要设置了。
set wx relaier ? #设置指定转发地址,格式为 https://域名/relay?url=%s,这个我也不知道干嘛的,不知道就别设置了。
set autMan enable_http_server true #启动http服务,一定要打开

对接青龙

青龙管理 #多容器青龙配置
ql spy #自定义监听变量运行青龙指定脚本功能

使用命令

ql config #获取青龙config.sh设置的内容,但我没测试出来结果,等猫咪大佬解惑
ql envs #获取青龙config.sh内设置的所有环境变量内容,但我没测试出来结果,等猫咪大佬解惑
ql env get ? #获取青龙config.sh内指定环境变量的内容,仅精确匹配
ql env find ? #查找青龙config.sh内指定的环境变量内容,支持模糊匹配
ql env set ? ? #在青龙config.sh内设置环境变量
ql env remark ? ? #字面意思是给环境变量设置备注,但我没测试出来结果,等猫咪大佬解惑
ql env disable ? #禁用(注释)在青龙config.sh内设置的环境变量
ql env enable ? #启用(取消注释)在青龙config.sh内设置的环境变量
ql raw ? #下载raw链接的js
ql task ? #在青龙里面运行指定的js
ql repo ? #在青龙里面拉库,例:ql repo https://github.com/cdle/carry.git
ql cookie status #查询青龙里cookie状态
ql crons #获取青龙所有定时任务,但我没测试出来结果,等猫咪大佬解惑
ql cron status ? #查看青龙指定定时任务的状态
ql cron run ? #运行青龙定时任务,支持模糊匹配
ql cron stop ? #停止运行青龙定时任务,支持模糊匹配
ql cron enable ? #启用青龙定时任务,支持模糊匹配
ql cron disable ? #禁用青龙定时任务,支持模糊匹配
ql cron find ? #查找青龙定时任务,支持模糊匹配
ql cron logs ? #查找青龙定时任务运行日志,支持模糊匹配
ql cron hide duplicate #隐藏青龙重复定时任务
set qinglong autoCronHideDuplicate false #关闭自动隐藏任务命令

对接芝士

h #短信登录
q #退出短信登录
登录 #短信登录
登陆 #短信登录
查询 ? #查询指定账号的资产
资产推送 #向所有绑定了账号的用户推送资产
查询 #查询当前社交账号绑定的所有账号资产
关闭?通知 #关闭指定活动任务通知
任务通知 #推送账号失效、果园和萌宠成熟以及未继续种植通知。有私聊和群聊@两种方式,默认私聊。
账号管理 #自定义任务通知等
推送管理 #用户设置推送
jd asset ? #查询指定账号的资产
jd imOf ? #获取绑定的社交账号,仅精确匹配pt_pin值
jd find ? #查找对应账号的编号、pt_pin值、备注等信息,支持编号、pt_pin值、备注查询,支持连号查询
jd exchange ? ? #交换两个账号的序号位置
jd enable ? #启用指定账号
jd disable ? #禁用指定账号
jd remark ? ? #备注指定账号
jd remove ? #跨容器删除ck,?可以匹配整个ck和相应的备注。芝士只有这一种方式删除ck
jd send ? ? #给指定账号发送消息
jd unbind #解绑该社交账号下的某栋账号
jd check ? ? #不知道干嘛的,第一个问号是pin值,第二个问号是青龙clientid
jd myCookie #查询绑定ck
pt_key=(3+); pt_pin=(4+) #发送ck提交到青龙
pin=(5+); wskey=(6+) #发送wskey提交到青龙
packetId=?(&|&)currentActId #极速推一推助力
set jd_cookie notify_mode group #任务通知设置群聊模式
set jd_cookie qqGroup ? #任务通知设置qq群聊ID
set jd_cookie wxGroup ? #任务通知设置微信群聊ID
set pinQQ pt_pin qq号码 #ck账号绑定qq号码,例 set pinQQ jd_xxxxxx 123456
delete pinQQ pt_pin,#取消ck账号绑定qq号码,例 delete pinQQ jd_xxxxxx
set pinTG pt_pin TGID #ck账号绑定TG账号,TGID找getmyid获取
delete pinTG pt_pin #取消ck账号绑定TG账号
set pinWX pt_pin 微信号 #微信给奥特曼bot发送myuid获取,其实就是你的微信号,不是微信昵称。
delete pinWX pt_pin #取消ck账号绑定微信账号
set pinWXMP pt_pin #微信公众号用户id #给公众号发送myuid获取
delete pinWXMP pt_pin #取消ck账号绑定微信公众号用户号
set jdWSCK update 56 #设置wskey自动转cooke定时:
set jd_cookie query_wait_time [限制秒数] #限制查询频率 例:set jd_cookie query_wait_time 60
set jd_cookie adong_addr 阿东ip:端口 #设置阿东登录地址,不需要http,仅支持阿东1.7及以下版本
set jd_cookie selfQid 机器人qq账号 #设置阿东qq机器人账号,仅支持阿东1.7及以下版本
set jd_cookie nolan_addr http://诺兰ip:端口 #设置诺兰登陆地址,需要http
set jd_cookie login_num ? #设置登录坑位
delete jd_cookie adong_addr 例:delete jd_cookie adong_addr ip:5701 #删除阿东地址
delete jd_cookie nolan_addr 例:delete jd_cookie nolan_addr http://ip:5701 #删除nolan地址
set jd_cookie xdd_url ? #短信登录接入xdd指令,格式http://IP地址:端口/api/login/smslogin
set jd_cookie xdd_token ? #对接xdd,额外设置参数
set jd_cookie asset_push ? #设置定时推送
set jd_cookie ad ? #自定义广告,成功登录后发送
set jd_cookie asset_query_alias xxxxxxx #自定义查询口令,变相实现屏蔽查询口令。
set jd_cookie disable_notify true #关闭推送指令,不想收到请jd unbind
set jd_cookie enable_auto_update true #自动检测ck有效性开关,关闭则设置为false。
set jd_cookie enable_yad false #跳过云上阿东。
set jd_cookie login_tip xxx #你也可以自定义登录提示
set jd_cookie sms_tip xxx #接收短信验证码提示

现在时间

time

奥特曼网址登录 设置账号
set silly name 自定义账号
设置密码
set silly password 自定义密码
查看账号
get silly name
查看密码
get silly password

新版奥特曼订阅合集
sub://T4EywWN46ztYBhHNdOl6TkE13/0LsDMMMxrMGyUvt9soogRtb7A7EGfdNQIjVeu2NHK38DucJa4jpNYfE7HSFccJIQP4Zx9GAAQqKscQvzEG+BOpX4JLr1y+iETeYJSF
sub://T4EywWN46ztYBhHNdOl6TiMeJo942S95KUAFmcfYSpAK/538Kt1mKM0XQ2ecLGP++bwq1WO4EVoV1XDl3Dgsr3Toiz6mbJWgLeafnyyLS3i8BAVtYd+2VONNz4SDqkSz
MkUmHFiNBjL7y
sub://T4EywWN46ztYBhHNdOl6Tjk2d+EtOGabIfyDREmK6J3Xvz4CK4Xe9F8q92WNeXok2H0tTGu8w2CytC7DVdiaFqr4Pa7eOcsXITA7ZhT0CjtgJ4kEL00xNYR4GkVkGmhp
sub://T4EywWN46ztYBhHNdOl6Tnc1O4R3y5GyfVG79kglc5BFQgqvuwidAE2Jcp0LaWakunhS2tn0ftD5MjD0umSE0pe+ab7wbypRAJrST/PDgN+HtgQXHK

6.掉线说明

一键重新启动奥特曼
/root/autMan/autMan -t
在输入重启 进入静默运行

机器人掉线说明
ctrl加c
cd /root/go-cqhttp
./go-cqhttp
ctrl+c在输入
./go-cqhttp -d

7.定时说明

/5 * ? #每隔 5 秒执行一次
0 /1 ? #每隔 1 分钟执行一次
0 0 2 1 ? #每月 1 日的凌晨 2 点执行一次
0 15 10 ? * #MON-FRI 周一到周五每天上午 10:15 执行
0 15 10 ? 6L #2002-2006 2002 年至 2006 年的每个月的最后一个星期五上午 10:15 执行
0 0 23 ? #每天 23 点执行一次
0 0 1 ? #每天凌晨 1 点执行一次
0 0 1 1 * ? #每月 1 日凌晨 1 点执行一次
0 0 23 L * ? #每月最后一天 23 点执行一次
0 0 1 ? * L #每周星期天凌晨 1 点执行一次
0 26,29,33 * ? #在 26 分、29 分、33 分执行一次
0 0 0,13,18,21 ? #每天的 0 点、13 点、18 点、21 点都执行一次
0 0 10,14,16 ? #每天上午 10 点,下午 2 点,4 点执行一次
0 0/30 9-17 ? #朝九晚五工作时间内每半小时执行一次
0 0 12 ? * WED #每个星期三中午 12 点执行一次
0 0 12 ? #每天中午 12 点触发
0 15 10 ? #每天上午 10:15 触发
0 15 10 ? #每天上午 10:15 触发
0 15 10 ? * #每天上午 10:15 触发
0 15 10 ? #2005 2005 年的每天上午 10:15 触发
0 14 * ? #每天下午 2 点到 2:59 期间的每 1 分钟触发
0 0/5 14 ? #每天下午 2 点到 2:55 期间的每 5 分钟触发
0 0/5 14,18 ? #每天下午 2 点到 2:55 期间和下午 6 点到 6:55 期间的每 5 分钟触发
0 0-5 14 ? #每天下午 2 点到 2:05 期间的每 1 分钟触发
0 10,44 14 ? 3 WED #每年三月的星期三的下午 2:10 和 2:44 触发
0 15 10 ? * MON-FRI #周一至周五的上午 10:15 触发
0 15 10 15 * ? #每月 15 日上午 10:15 触发
0 15 10 L * ? #每月最后一日的上午 10:15 触发
0 15 10 ? * 6L #每月的最后一个星期五上午 10:15 触发
0 15 10 ? * 6L #2002-2005 2002 年至 2005 年的每月的最后一个星期五上午 10:15 触发
0 15 10 ? * 6#3 #每月的第三个星期五上午 10:15 触发

视频里的附件:
链接: https://pan.baidu.com/s/1_Gmny6Cn9osuBK2Aa2wFnQ?pwd=ybnn 提取码: ybnn 复制这段内容后打开百度网盘手机App,操作更方便哦
解压密码:blog.xiaohack.org


  1. 0-9a-zA-Z=
  2. 0-9a-zA-Z;
  3. ;=\s
  4. ;=\s
  5. ;=\s
  6. ;=\s

钉钉日志是个很恶心的玩意,每天都要你写,写不写也无所谓,应付下而已。
但有个小爬虫来完成就很方便,也不敷衍

无法直接发送请求,所以使用了selenium库来完成。
每个模板都不一样,需要自己重新定位,只是提供一种思路,稳定使用了半年,发出来供大家参考学习
需要先抓到模板id,然后可以在web中打开看看对不对,在进行定位,main中含有linux和Windows的,自己注释测试,可以连接到已经打开的浏览器,方便调试,具体自己百度。
钉钉webCk,有效期为30天,过期要重新抓。
有两套推送,一个钉钉,一个微信,小米手机不知道什么毛病,钉钉不推送,就弄了两套,自己按需改。



下载链接: https://wwxi.lanzoum.com/iTklz0ofsnqh
ps:仅参考学习用,内容生成来源于各大论坛开源库