重要提醒:本帖内容仅做技术学习交流,本社区自动签到属于违规行为,长期仅签到,无社区贡献的签到积分会定期清理!!!
📋 脚本简介
这是一个基于 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",
}
如需使用代理,取消注释并修改即可。
🚀 部署步骤
- 复制代码:将下方完整代码保存为
fnbbs_sign.py
- 上传脚本:上传至青龙面板
scripts 目录
- 配置依赖:确保已安装
selenium、requests、beautifulsoup4
- 设置变量:在青龙面板添加
fn_username 和 fn_password
- 修改配置:填写 PushPlus Token 和验证码识别 Token
- 添加定时任务:
- 命令:
task fnbbs_sign.py
- 定时规则:
0 9 * * *(每天上午9点执行,建议错开高峰期)
📱 推送效果预览
签到成功推送:
- 最近打卡时间
- 本月打卡天数
- 连续打卡天数
- 累计打卡天数
- 累计/最近奖励(飞牛币)
- 当前打卡等级
失败推送:包含失败原因及截图路径(如适用)
⚠️ 注意事项
- 安全性:建议将敏感信息(Token、密码)存储在青龙环境变量中,不要硬编码在脚本内
- 验证码识别:免费验证码识别接口有额度限制,但赠送额度够用很久了,无需关注余额
- 稳定性:脚本已添加重试机制(最多3次),如遇网络波动会自动重试
- 反爬策略:脚本设置了合理的等待时间和 User-Agent,但请勿过于频繁执行
- 截图排查:如签到失败,检查青龙
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()