收起左侧

可能是最稳定的飞牛论坛自动签到脚本(青龙面板适用)

1
回复
114
查看
[ 复制链接 ]

11

主题

108

回帖

0

牛值

fnOS系统内测组

重要提醒:本帖内容仅做技术学习交流,本社区自动签到属于违规行为,长期仅签到,无社区贡献的签到积分会定期清理!!!

📋 脚本简介

这是一个基于 Selenium + Python 的飞牛社区(club.fnnas.com)自动签到脚本,支持验证码自动识别、登录状态检测、签到结果推送等功能。适用于 青龙面板 部署,实现每日定时自动签到。签到成功率99.99%

✨ 主要功能

功能 说明
🔄自动登录 支持账号密码自动登录,检测登录状态
🧩验证码识别 集成第三方验证码识别API,自动处理登录验证码
📊状态检测 智能识别签到成功/已签到/失败等多种状态
📱消息推送 支持 PushPlus 微信推送,包含详细打卡数据
🖼️失败截图 签到失败时自动保存页面截图,便于排查问题
📝数据提取 自动获取本月打卡、连续打卡、累计奖励等信息

🔧 前置依赖

如果没安装过相关依赖,需要先在青龙面板中执行以下命令安装依赖:

bash复制

# 安装 Python 依赖
pip install selenium requests beautifulsoup4

# 安装 Chrome 浏览器(青龙面板环境)
# 一般青龙面板已内置,如未安装请参考以下命令:
apk add chromium chromium-chromedriver

⚙️ 环境变量配置(青龙面板)

在青龙面板 环境变量 中添加以下变量:

表格

变量名 说明 示例
fn_username 飞牛论坛用户名 your_username
fn_password 飞牛论坛密码 your_password

配置路径:青龙面板 → 环境变量 → 添加变量

📝 脚本配置修改

使用前需要修改脚本中的以下配置项:

1. PushPlus 推送 Token(必填)

PushPlus推送Token:点我注册

Python复制

push_config = {
    "API_URL": "http://www.pushplus.plus/send",
    "TOKEN": "替换为你的推送Token",  # ← 修改这里
}

获取 Token:PushPlus 官网

2. 验证码识别 Token(必填)

验证码识别Token:点我注册

Python复制

def recognize_captcha(captcha_bytes):
    url = "http://api.jfbym.com/api/YmServer/customApi"
    data = {
        "token": "1234567890",  # ← 替换为你的验证码识别Token
        "type": "10110",  # 通用数英(≤5位)
        # ...
    }

推荐使用 极验/云码 等验证码识别平台,类型 10110 为通用数字英文识别

3. 代理设置(可选)

Python复制

proxies = {
    # "http": "http://127.0.0.1:1080",
    # "https": "http://127.0.0.1:1080",
}

如需使用代理,取消注释并修改即可。

🚀 部署步骤

  1. 复制代码:将下方完整代码保存为 fnbbs_sign.py
  2. 上传脚本:上传至青龙面板 scripts 目录
  3. 配置依赖:确保已安装 seleniumrequestsbeautifulsoup4
  4. 设置变量:在青龙面板添加 fn_usernamefn_password
  5. 修改配置:填写 PushPlus Token 和验证码识别 Token
  6. 添加定时任务
    • 命令:task fnbbs_sign.py
    • 定时规则:0 9 * * *(每天上午9点执行,建议错开高峰期)

📱 推送效果预览

签到成功推送

  • 最近打卡时间
  • 本月打卡天数
  • 连续打卡天数
  • 累计打卡天数
  • 累计/最近奖励(飞牛币)
  • 当前打卡等级

失败推送:包含失败原因及截图路径(如适用)

⚠️ 注意事项

  1. 安全性:建议将敏感信息(Token、密码)存储在青龙环境变量中,不要硬编码在脚本内
  2. 验证码识别:免费验证码识别接口有额度限制,但赠送额度够用很久了,无需关注余额
  3. 稳定性:脚本已添加重试机制(最多3次),如遇网络波动会自动重试
  4. 反爬策略:脚本设置了合理的等待时间和 User-Agent,但请勿过于频繁执行
  5. 截图排查:如签到失败,检查青龙 scripts 目录下的 签到失败_*.png 文件

🐛 常见问题

Q: 提示 "ChromeDriver 版本不匹配"? A: 确保 Chrome 浏览器和 ChromeDriver 版本一致,或使用青龙面板的内置浏览器。

Q: 推送没有收到? A: 检查 PushPlus Token 是否正确,以及微信是否已关注 PushPlus 公众号。

Q: 验证码识别一直失败? A: 检查验证码识别 Token 是否有效,是否领取了免费额度。

📎 完整代码

import os
import time
import requests
import os
import base64
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup

# 推送配置
push_config = {
    "API_URL": "http://www.pushplus.plus/send",
    "TOKEN": "替换为你的推送Token",
}

# 签到主页URL
SIGN_IN_PAGE_URL = "https://club.fnnas.com/plugin.php?id=zqlj_sign"

# 登录页面URL
LOGIN_PAGE_URL = "https://club.fnnas.com/member.php?mod=logging&action=login"

# 代理设置
proxies = {
    # "http": "http://127.0.0.1:1080",
    # "https": "http://127.0.0.1:1080",
}

# 用户名和密码,配置到青龙面板的环境变量中
USERNAME = os.environ["fn_username"]
PASSWORD = os.environ["fn_password"]

def capture_captcha(driver, captcha_img_element):
    """截图验证码"""
    try:
        # 确保验证码图片已加载
        time.sleep(1)
  
        # 截图验证码到内存
        captcha_bytes = captcha_img_element.screenshot_as_png
        print("验证码已截图")
        return captcha_bytes
    except Exception as e:
        print(f"截图验证码失败: {e}")
        return None

def recognize_captcha(captcha_bytes):
    """识别验证码"""
    try:
        # 将图片字节转换为base64
        b = base64.b64encode(captcha_bytes).decode()
  
        # 验证码识别API配置
        url = "http://api.jfbym.com/api/YmServer/customApi"
        data = {
            "token": "1234567890", #替换为你的验证码识别Token
            "type": "10110",  # 通用数英(≤5位)
            "image": b,
        }
        headers = {
            "Content-Type": "application/json"
        }
  
        response = requests.post(url, headers=headers, json=data, proxies=proxies)
        result = response.json()
  
        if result.get("code") == 10000:  # 成功状态码
            captcha_text = result.get("data", {}).get("data", "")
            print(f"验证码识别成功: {captcha_text}")
            return captcha_text
        else:
            print(f"验证码识别失败: {result}")
            return None
  
    except Exception as e:
        print(f"验证码识别异常: {e}")
        return None

def handle_captcha_page(driver, wait):
    """处理验证码页面"""
    max_retries = 3  # 最多重试3次
  
    for attempt in range(max_retries):
        try:
            print(f"=== 第 {attempt + 1} 次尝试处理验证码 ===")
  
            # 等待验证码图片加载
            print("等待验证码图片加载...")
            captcha_img = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".vm:nth-child(2)")))
  
            # 截图验证码
            captcha_bytes = capture_captcha(driver, captcha_img)
  
            if captcha_bytes:
                print("验证码截图完成,开始自动识别...")
  
                # 自动识别验证码
                captcha_code = recognize_captcha(captcha_bytes)
  
                if captcha_code:
                    print(f"准备输入验证码: {captcha_code}")
  
                    # 输入验证码
                    captcha_input = wait.until(EC.presence_of_element_located((By.NAME, "seccodeverify")))
                    captcha_input.clear()
                    captcha_input.send_keys(captcha_code)
                    print("验证码输入成功")
  
                    # 点击登录按钮
                    print("正在点击登录按钮...")
                    login_btn = wait.until(EC.element_to_be_clickable((By.NAME, "loginsubmit")))
                    login_btn.click()
  
                    # 等待登录结果
                    time.sleep(5)
  
                    # 检查是否仍然停留在验证码页面(说明验证码错误)
                    current_page_source = driver.page_source
                    if "输入下图中的字符" in current_page_source:
                        print("验证码错误,仍然停留在验证码页面")
                        if attempt < max_retries - 1:
                            print("准备换一个验证码重试...")
                            try:
                                # 点击"换一个"按钮
                                refresh_captcha_btn = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "换一个")))
                                refresh_captcha_btn.click()
                                time.sleep(2)  # 等待新验证码加载
                                continue
                            except Exception as refresh_error:
                                print(f"点击换一个验证码失败: {refresh_error}")
                                continue
                        else:
                            print("已达到最大重试次数,验证码处理失败")
                            return False
                    else:
                        print("验证码处理成功,已离开验证码页面")
                        return True
                else:
                    print("验证码识别失败")
                    if attempt < max_retries - 1:
                        print("准备换一个验证码重试...")
                        try:
                            # 点击"换一个"按钮
                            refresh_captcha_btn = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "换一个")))
                            refresh_captcha_btn.click()
                            time.sleep(2)  # 等待新验证码加载
                            continue
                        except Exception as refresh_error:
                            print(f"点击换一个验证码失败: {refresh_error}")
                            continue
                    else:
                        print("已达到最大重试次数,验证码识别失败")
                        return False
            else:
                print("验证码截图失败")
                if attempt < max_retries - 1:
                    print("准备重试...")
                    time.sleep(2)
                    continue
                else:
                    print("已达到最大重试次数,验证码截图失败")
                    return False
  
        except Exception as e:
            print(f"处理验证码页面时发生错误: {e}")
            if attempt < max_retries - 1:
                print("准备重试...")
                time.sleep(2)
                continue
            else:
                print("已达到最大重试次数,验证码处理失败")
                return False
  
    return False

def setup_driver():
    """
    设置Chrome浏览器驱动
    """
    chrome_options = Options()
    # 无头模式运行
    chrome_options.add_argument("--headless")
    # 禁用GPU加速
    chrome_options.add_argument("--disable-gpu")
    # 禁用沙盒
    chrome_options.add_argument("--no-sandbox")
    # 禁用dev-shm-usage
    chrome_options.add_argument("--disable-dev-shm-usage")
    # 设置中文显示
    chrome_options.add_argument("--lang=zh-CN")
    # 设置用户代理
    chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
  
    # 创建驱动
    driver = webdriver.Chrome(options=chrome_options)
  
    # 设置页面加载超时
    driver.set_page_load_timeout(10)
  
    driver.set_window_size(1920, 1080)  # 设置为1920x1080的分辨率
  
    return driver

def sign_in():
    """
    登录并执行签到操作 - 按照用户要求的流程实现
    1. 直接打开签到主页
    2. 点击打卡按钮
    3. 自动跳转登录页面,输入账号密码登录
    4. 登录成功后再次点击打卡按钮
    5. 判断打卡是否成功
    """
    print("===== 开始执行飞牛社区签到任务 =====")
    start_time = time.time()
  
    # 使用setup_driver函数创建浏览器驱动,利用其中的中文显示优化配置
    driver = setup_driver()
    wait = WebDriverWait(driver, 15)  # 增加等待时间以提高稳定性
  
    try:
        # 1. 直接打开签到主页
        print(f"直接访问签到主页: {SIGN_IN_PAGE_URL}")
        driver.get(SIGN_IN_PAGE_URL)
        time.sleep(3)
  
        # 2. 尝试点击打卡按钮
        print("尝试点击'点击打卡'按钮...")
        try:
            # 使用linkText定位打卡按钮
            sign_button = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "点击打卡")))
            driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", sign_button)
            time.sleep(2)
  
            try:
                sign_button.click()
                print("直接点击'点击打卡'按钮成功")
            except Exception as click_error:
                print(f"直接点击失败: {click_error},尝试使用JavaScript点击...")
                driver.execute_script("arguments[0].click();", sign_button)
                print("JavaScript点击'点击打卡'按钮成功")
        except Exception as e:
            print(f"点击'点击打卡'按钮时发生错误: {e}")
  
        # 等待页面跳转
        time.sleep(3)
  
        # 3. 检查是否跳转到登录页面并执行登录
        current_url = driver.current_url
        print(f"当前URL: {current_url}")
  
        # 判断是否需要登录(通过URL或页面内容判断)
        if "login" in current_url.lower() or "loginsubmit" in current_url.lower() or "登录" in driver.page_source:
            print("检测到需要登录,正在执行登录操作...")
  
            try:
                # 等待页面加载完成
                wait.until(lambda d: d.execute_script('return document.readyState') == 'complete')
  
                # 使用指定的XPATH定位方式输入用户名和密码
                print("使用XPATH方式输入用户名和密码...")
                try:
                    # 用户名输入框:xpath=//div[2]/div/div[2]/div/div/form/div/div/input
                    username_input = wait.until(EC.presence_of_element_located((By.XPATH, "//div[2]/div/div[2]/div/div/form/div/div/input")))
                    username_input.clear()
                    username_input.send_keys(USERNAME)
                    print("用户名输入成功")
                except Exception as e:
                    print(f"用户名输入失败: {e}")
  
                try:
                    # 密码输入框:xpath=//div[2]/input
                    password_input = wait.until(EC.presence_of_element_located((By.XPATH, "//div[2]/input")))
                    password_input.clear()
                    password_input.send_keys(PASSWORD)
                    print("密码输入成功")
                except Exception as e:
                    print(f"密码输入失败: {e}")
  
                # 查找并点击登录按钮 - 仅使用name属性定位
                try:
                    login_button = wait.until(EC.element_to_be_clickable((By.NAME, "loginsubmit")))
                    driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", login_button)
                    time.sleep(1)
                    try:
                        login_button.click()
                        print("使用name=loginsubmit定位并直接点击登录按钮成功")
                    except Exception as click_error:
                        driver.execute_script("arguments[0].click();", login_button)
                        print("使用name=loginsubmit定位并JavaScript点击登录按钮成功")
                except Exception as e:
                    print(f"使用name=loginsubmit定位失败: {e}")
                    # 尝试直接提交表单
                    try:
                        print("尝试直接提交表单...")
                        driver.execute_script("document.forms[0].submit();")
                        print("表单提交成功")
                    except Exception as form_error:
                        print(f"表单提交失败: {form_error}")
  
                # 4. 等待10秒后检查是否登录成功
                print("等待登录结果...")
                time.sleep(10)
  
                # 检查是否进入验证码页面
                current_page_source = driver.page_source
                if "输入下图中的字符" in current_page_source:
                    print("检测到验证码页面,开始处理验证码...")
                    captcha_success = handle_captcha_page(driver, wait)
                    if not captcha_success:
                        print("验证码处理失败")
                        # 创建验证码处理失败的结果
                        captcha_fail_result = {
                            'status': 'failed',
                            'message': '验证码处理失败',
                            'details': {}
                        }
                        send_checkin_result(captcha_fail_result, driver)
                        return
                    else:
                        print("验证码处理成功,继续检查登录状态...")
                        # 验证码处理后再次检查登录状态
                        time.sleep(5)
                        current_page_source = driver.page_source
  
                # 检查是否登录成功 - 使用统一的检测逻辑
                print("正在检测登录状态...")
                login_check_result = check_checkin_status(driver)
  
                if login_check_result['status'] in ['success', 'already_checked']:
                    print("登录成功!")
                else:
                    print("登录失败")
                    print(f"当前页面标题: {driver.title}")
                    print(f"当前URL: {driver.current_url}")
                    # 发送登录失败推送
                    send_checkin_result(login_check_result, driver)
                    return
  
                # 5. 再次访问签到页面并点击打卡按钮
                print("登录成功,再次访问签到页面...")
                driver.get(SIGN_IN_PAGE_URL)
                time.sleep(3)
  
                print("尝试再次点击'点击打卡'按钮...")
                try:
                    # 使用linkText定位打卡按钮
                    sign_button = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "点击打卡")))
                    driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", sign_button)
                    time.sleep(2)
  
                    try:
                        sign_button.click()
                        print("直接点击'点击打卡'按钮成功")
                    except Exception as click_error:
                        print(f"直接点击失败: {click_error},尝试使用JavaScript点击...")
                        driver.execute_script("arguments[0].click();", sign_button)
                        print("JavaScript点击'点击打卡'按钮成功")
  
                    # 等待页面响应
                    time.sleep(3)
  
                    # 6. 使用统一的签到状态检测
                    print("正在检测打卡结果...")
                    checkin_result = check_checkin_status(driver)
  
                    # 根据检测结果发送推送
                    send_checkin_result(checkin_result, driver)
                except Exception as e:
                    print(f"再次点击'点击打卡'按钮时发生错误: {e}")
                    # 使用统一的签到状态检测
                    print("正在检测当前签到状态...")
                    checkin_result = check_checkin_status(driver)
  
                    # 根据检测结果发送推送
                    send_checkin_result(checkin_result, driver)
            except Exception as login_error:
                print(f"登录过程中发生错误: {login_error}")
                # 创建登录错误的结果
                login_error_result = {
                    'status': 'failed',
                    'message': f'登录过程中发生错误: {login_error}',
                    'details': {}
                }
                send_checkin_result(login_error_result, driver)
        else:
            print("无需登录或已登录,直接检查签到状态")
            # 使用统一的签到状态检测
            print("正在检测当前签到状态...")
            checkin_result = check_checkin_status(driver)
  
            # 根据检测结果发送推送
            send_checkin_result(checkin_result, driver)
  
    except Exception as e:
        print(f"签到过程中发生错误: {e}")
        # 创建总错误的结果
        total_error_result = {
            'status': 'failed',
            'message': f'签到过程中发生错误: {e}',
            'details': {}
        }
        send_checkin_result(total_error_result, driver if 'driver' in locals() and driver else None)
    finally:
        # 关闭浏览器
        if driver:
            driver.quit()
  
    end_time = time.time()
    print(f"===== 飞牛社区签到任务执行完成,耗时 {round(end_time - start_time)} 秒 =====")


def check_checkin_status(driver):
    """
    统一的签到状态检测函数
    返回: {'status': 'success'|'already_checked'|'failed'|'unknown', 'message': str, 'details': dict}
    """
    try:
        print("正在检测签到状态...")
  
        # 获取页面内容
        page_source = driver.page_source
        current_url = driver.current_url
  
        # 初始化检测结果
        result = {
            'status': 'unknown',
            'message': '',
            'details': {}
        }
  
        # 检测各种成功标识
        success_indicators = [
            '成功',
            '我的打卡动态',
            '打卡成功',
            '签到成功'
        ]
  
        # 检测已打卡标识
        already_checked_indicators = [
            '今日已打卡',
            '今天已打卡',
            '已签到',
            '今日已签到',
            '您今天已经签到过了',
            '今日签到已完成'
        ]
  
        # 检测失败标识
        failed_indicators = [
            '签到失败',
            '打卡失败',
            '登录失败',
            '验证码错误',
            '网络错误'
        ]
  
        # 检查成功标识
        for indicator in success_indicators:
            if indicator in page_source:
                print(f"检测到成功标识: {indicator}")
                result['status'] = 'success'
                result['message'] = f'检测到成功标识: {indicator}'
                break
  
        # 如果没检测到成功,检查是否已打卡
        if result['status'] == 'unknown':
            for indicator in already_checked_indicators:
                if indicator in page_source:
                    print(f"检测到已打卡标识: {indicator}")
                    result['status'] = 'already_checked'
                    result['message'] = f'检测到已打卡标识: {indicator}'
                    break
  
        # 如果还没检测到,检查失败标识
        if result['status'] == 'unknown':
            for indicator in failed_indicators:
                if indicator in page_source:
                    print(f"检测到失败标识: {indicator}")
                    result['status'] = 'failed'
                    result['message'] = f'检测到失败标识: {indicator}'
                    break
  
        # 如果仍然未知,尝试通过页面元素检测
        if result['status'] == 'unknown':
            try:
                # 检查是否存在"点击打卡"按钮(说明未打卡)
                sign_buttons = driver.find_elements(By.LINK_TEXT, "点击打卡")
                if sign_buttons:
                    print("检测到'点击打卡'按钮,说明未打卡")
                    result['status'] = 'failed'
                    result['message'] = '检测到点击打卡按钮,但签到可能未成功'
                else:
                    # 检查是否存在打卡相关的成功元素
                    success_elements = driver.find_elements(By.XPATH, "//*[contains(text(), '打卡') or contains(text(), '签到')]")
                    if success_elements:
                        print("检测到打卡相关元素,可能已成功")
                        result['status'] = 'success'
                        result['message'] = '检测到打卡相关元素'
                    else:
                        print("无法确定签到状态")
                        result['status'] = 'unknown'
                        result['message'] = '无法确定签到状态'
            except Exception as e:
                print(f"通过页面元素检测时发生错误: {e}")
                result['status'] = 'unknown'
                result['message'] = f'页面元素检测错误: {e}'
  
        # 提取详细信息
        result['details'] = extract_checkin_dynamic_info(driver)
  
        print(f"签到状态检测结果: {result['status']} - {result['message']}")
        return result
  
    except Exception as e:
        print(f"检测签到状态时发生错误: {e}")
        return {
            'status': 'unknown',
            'message': f'检测错误: {e}',
            'details': {}
        }

def extract_checkin_dynamic_info(driver):
    """
    提取我的打卡动态信息
    """
    try:
        print("正在提取打卡动态信息...")
  
        # 获取页面内容
        page_source = driver.page_source
  
        # 初始化信息字典
        dynamic_info = {}
  
        # 使用正则表达式提取各项信息
        import re
  
        # 最近打卡时间
        recent_match = re.search(r'最近打卡:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})', page_source)
        if recent_match:
            dynamic_info['最近打卡'] = recent_match.group(1)
  
        # 本月打卡天数
        monthly_match = re.search(r'本月打卡:(\d+)天', page_source)
        if monthly_match:
            dynamic_info['本月打卡'] = monthly_match.group(1) + '天'
  
        # 连续打卡天数
        consecutive_match = re.search(r'连续打卡:(\d+)天', page_source)
        if consecutive_match:
            dynamic_info['连续打卡'] = consecutive_match.group(1) + '天'
  
        # 累计打卡天数
        total_match = re.search(r'累计打卡:(\d+)天', page_source)
        if total_match:
            dynamic_info['累计打卡'] = total_match.group(1) + '天'
  
        # 累计奖励
        total_reward_match = re.search(r'累计奖励:(\d+)飞牛币', page_source)
        if total_reward_match:
            dynamic_info['累计奖励'] = total_reward_match.group(1) + '飞牛币'
  
        # 最近奖励
        recent_reward_match = re.search(r'最近奖励:(\d+)飞牛币', page_source)
        if recent_reward_match:
            dynamic_info['最近奖励'] = recent_reward_match.group(1) + '飞牛币'
  
        # 当前打卡等级
        level_match = re.search(r'当前打卡等级:([^<\n]+)', page_source)
        if level_match:
            dynamic_info['当前打卡等级'] = level_match.group(1).strip()
  
        # 打印提取到的信息
        if dynamic_info:
            print("成功提取打卡动态信息:")
            for key, value in dynamic_info.items():
                print(f"  {key}: {value}")
        else:
            print("未找到打卡动态信息")
  
        return dynamic_info
  
    except Exception as e:
        print(f"提取打卡动态信息时发生错误: {e}")
        return {}

def get_sign_in_info_selenium(driver):
    """
    使用Selenium获取签到详情
    """
    print("正在获取签到详情...")
    try:
        # 等待页面加载完成
        time.sleep(2)
  
        # 获取页面内容
        page_source = driver.page_source
  
        # 提取打卡公告
        if "打卡公告" in page_source:
            soup = BeautifulSoup(page_source, 'html.parser')
            # 查找包含"打卡公告"的元素
            notice_elements = soup.find_all(lambda tag: tag.name and "打卡公告" in tag.text)
            if notice_elements:
                notice_text = notice_elements[0].text.strip()
                print(f"打卡公告: {notice_text}")
  
        # 推送签到结果
        pushplus_push('飞牛社区自动签到(成功)', '签到成功!')
    except Exception as e:
        print(f"获取签到详情时发生错误: {e}")


def send_checkin_result(status_result, driver=None):
    """
    根据签到状态结果发送推送消息
    """
    try:
        status = status_result['status']
        message = status_result['message']
        details = status_result.get('details', {})
  
        # 构建推送内容
        if status == 'success':
            title = '飞牛社区自动签到(成功)'
            if details:
                info_html = ""
                for key, value in details.items():
                    info_html += f"<p><b>{key}:</b>{value}</p>"
  
                content = f"""
                <h3>🎉 飞牛社区签到成功!</h3>
                <hr>
                <h4>📊 打卡动态信息</h4>
                {info_html}
                <hr>
                <p><small>执行时间:{time.strftime('%Y-%m-%d %H:%M:%S')}</small></p>
                <p><small>检测信息:{message}</small></p>
                """
            else:
                content = f"""
                <h3>🎉 飞牛社区签到成功!</h3>
                <p>签到成功,但未能获取到详细的打卡动态信息。</p>
                <p><small>执行时间:{time.strftime('%Y-%m-%d %H:%M:%S')}</small></p>
                <p><small>检测信息:{message}</small></p>
                """
  
        elif status == 'already_checked':
            title = '飞牛社区自动签到(成功)'
            if details:
                info_html = ""
                for key, value in details.items():
                    info_html += f"<p><b>{key}:</b>{value}</p>"
  
                content = f"""
                <h3>✅ 飞牛社区今日已打卡</h3>
                <hr>
                <h4>📊 打卡动态信息</h4>
                {info_html}
                <hr>
                <p><small>执行时间:{time.strftime('%Y-%m-%d %H:%M:%S')}</small></p>
                <p><small>检测信息:{message}</small></p>
                """
            else:
                content = f"""
                <h3>✅ 飞牛社区今日已打卡</h3>
                <p>今日已打卡,但未能获取到详细的打卡动态信息。</p>
                <p><small>执行时间:{time.strftime('%Y-%m-%d %H:%M:%S')}</small></p>
                <p><small>检测信息:{message}</small></p>
                """
  
        else:  # failed 或 unknown
            title = '飞牛社区自动签到(失败)'
            content = f"""
            <h3>❌ 飞牛社区签到失败</h3>
            <p><b>失败原因:</b>{message}</p>
            <p><small>执行时间:{time.strftime('%Y-%m-%d %H:%M:%S')}</small></p>
            """
  
            # 如果是失败状态,保存截图
            if driver and status == 'failed':
                timestamp = time.strftime('%Y%m%d_%H%M%S')
                screenshot_path = f'签到失败_{timestamp}.png'
                driver.save_screenshot(screenshot_path)
                print(f"已保存失败截图: {screenshot_path}")
                content += f"<p><small>已保存失败截图: {screenshot_path}</small></p>"
  
        # 发送推送
        pushplus_push(title, content)
  
    except Exception as e:
        print(f"发送签到结果推送时发生错误: {e}")
        # 发送错误推送
        pushplus_push('飞牛社区自动签到(错误)', f'发送推送时发生错误: {e}')

def pushplus_push(title: str, content: str):
    """
    使用 PushPlus 接口推送消息。
    """
    if not push_config.get("API_URL") or not push_config.get("TOKEN"):
        print("PushPlus 接口配置不完整!取消推送")
        return
    payload = {
        "token": push_config['TOKEN'],
        "title": title,
        "content": content,
        "template": "html"
    }
    response = requests.post(push_config['API_URL'], json=payload, headers={"Content-Type": "application/json"}, proxies=proxies)
    if response.status_code != 200:
        print(f"PushPlus 推送失败!状态码: {response.status_code}, 响应内容: {response.text}")
    else:
        print("PushPlus 推送成功!")

if __name__ == '__main__':
    sign_in()
收藏
送赞
分享

1

主题

80

回帖

0

牛值

初出茅庐

论坛禁止用插件自动打卡

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则