1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/PfsP97若失效,可用地址
阿里云:
服务器购买地址
https://t.aliyun.com/U/PfsP97
若失效,可用地址
https://www.aliyun.com/activity/wuying/dj?source=5176.29345612&userCode=49hts92d
腾讯云:
https://curl.qcloud.com/wJpWmSfU
若失效,可用地址
https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console
华为云
https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905
2.部署教程
3.代码如下
// 飞牛社区自动签到脚本
const axios = require('axios');
const cheerio = require('cheerio');
const notify = require('./sendNotify'); // 青龙面板内置通知函数
// 从环境变量获取完整Cookie字符串
const fullCookieString = process.env.FN_COOKIE || '';
/**
* 获取动态的sign参数[3](@ref)
* @returns {Promise<string>} 动态的sign参数值
*/
async function getDynamicSign() {
try {
console.log('开始获取动态sign参数...');
const response = await axios.get('https://club.fnnas.com/plugin.php?id=zqlj_sign', {
headers: {
'Cookie': fullCookieString,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
});
const $ = cheerio.load(response.data);
// 尝试从签到按钮的链接中提取sign参数[3](@ref)
const signLink = $('a.btna').attr('href');
if (!signLink) {
throw new Error('无法从页面中找到签到链接(可能Cookie失效或页面改版)');
}
const signMatch = signLink.match(/sign=([a-f0-9]+)/);
if (signMatch && signMatch[1]) {
console.log('动态sign参数获取成功:', signMatch[1]);
return signMatch[1];
} else {
throw new Error('从签到链接中提取sign参数失败');
}
} catch (error) {
console.error('日志信息 获取动态sign参数失败:', error.message);
await notify.sendNotify('飞牛签到失败', `获取动态sign参数失败: ${error.message}`);
throw error; // 重新抛出错误,阻止后续签到执行
}
}
/**
* 执行签到操作
* @param {string} dynamicSign 动态获取的sign参数
*/
async function signIn(dynamicSign) {
try {
const signUrl = `https://club.fnnas.com/plugin.php?id=zqlj_sign&sign=${dynamicSign}`;
console.log(' 发送签到请求:', signUrl);
const response = await axios.get(signUrl, {
headers: {
'Cookie': fullCookieString,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
});
if (response.data.includes('恭喜您,打卡成功!')) {
console.log(' 打卡成功');
await getSignInInfo(); // 获取并推送签到详情
} else if (response.data.includes('您今天已经打过卡了')) {
console.log(' 已经打过卡了');
await notify.sendNotify('飞牛论坛', '您今天已经打过卡了'); // 推送已签到通知
} else {
// 可能的情况:Cookie失效、签到链接错误、网站改版
const errorMsg = '打卡失败, cookies可能已经过期或站点更新.';
console.log('日志信息', errorMsg);
await notify.sendNotify('飞牛论坛', errorMsg);
}
} catch (error) {
console.error('日志信息 签到请求失败:', error.message);
await notify.sendNotify('飞牛论坛', `签到请求失败: ${error.message}`);
}
}
/**
* 获取签到详情信息并推送[1,3](@ref)
*/
async function getSignInInfo() {
try {
console.log(' 获取签到详情信息...');
const response = await axios.get('https://club.fnnas.com/plugin.php?id=zqlj_sign', {
headers: {
'Cookie': fullCookieString,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
});
const $ = cheerio.load(response.data);
const content = []; // 存储提取的签到信息
// 定义要提取的信息项及其选择器[1](@ref)
const patterns = [
{ name: '最近打卡', selector: 'li:contains("最近打卡")' },
{ name: '本月打卡', selector: 'li:contains("本月打卡")' },
{ name: '连续打卡', selector: 'li:contains("连续打卡")' },
{ name: '累计打卡', selector: 'li:contains("累计打卡")' },
{ name: '累计奖励', selector: 'li:contains("累计奖励")' },
{ name: '最近奖励', selector: 'li:contains("最近奖励")' },
{ name: '当前打卡等级', selector: 'li:contains("当前打卡等级")' }
];
// 提取数据
patterns.forEach(pattern => {
const elementText = $(pattern.selector).text();
if (elementText) {
// 提取冒号后的值部分[3](@ref)
const value = elementText.replace(/.*:/, '').trim(); // 注意正则表达式修改,匹配中文冒号
content.push(`${pattern.name}: ${value}`);
}
});
if (content.length > 0) {
const message = content.join('\n');
console.log(' 签到详情:\n' + message);
// 推送签到成功及详情[1](@ref)
await notify.sendNotify('飞牛论坛打卡成功', message);
} else {
throw new Error('未找到签到详情信息,页面结构可能已变更');
}
} catch (error) {
console.error(' 获取打卡信息失败:', error.message);
await notify.sendNotify('飞牛论坛', `获取打卡信息失败: ${error.message}`);
}
}
/**
* 主执行函数
*/
async function main() {
console.log(' 开始执行飞牛社区自动签到任务...');
console.log(' 当前时间:', new Date().toLocaleString('zh-CN'));
// 1. 检查Cookie是否配置
if (!fullCookieString) {
const errorMsg = '未设置环境变量 FN_COOKIE,请先在青龙面板中配置。';
console.error('', errorMsg);
await notify.sendNotify('飞牛签到配置错误', errorMsg);
return;
}
console.log(' FN_COOKIE 环境变量已设置');
try {
// 2. 动态获取sign参数[3](@ref)
const dynamicSign = await getDynamicSign();
// 3. 执行签到
await signIn(dynamicSign);
} catch (error) {
// getDynamicSign 中的错误已处理,此处捕获其他潜在错误
console.error(' 任务执行过程中发生未预期错误:', error.message);
} finally {
console.log(' 任务执行完毕。');
}
}
// 执行主函数
main();
解析
该脚本为飞牛社区自动签到脚本,主要作用包括:
自动完成飞牛社区(club.fnnas.com)每日签到:
通过携带环境变量里的 FN_COOKIE(完整 Cookie)访问签到页面,先抓取当日动态 sign 参数,再构造签到请求完成打卡。结果通知:
结合青龙面板的sendNotify
,在成功、已签或失败等场景推送消息(如"打卡成功/已打过/失败原因"等)。
关键依赖 & 配置
依赖:
axios
(HTTP 请求)、cheerio
(HTML 解析)、sendNotify
(青龙通知)。环境变量:
FN_COOKIE
(必须),为飞牛社区的完整 Cookie 字符串。
主要方法作用
getDynamicSign()
访问签到页
plugin.php?id=zqlj_sign
,解析 HTML。用
cheerio
找到签到按钮链接a.btna
的href
,从中提取当日动态 sign 参数(正则匹配sign=xxxx
)。失败会调用通知并抛错,阻止后续流程。
signIn(dynamicSign)
包含"恭喜您,打卡成功!"→ 视为成功,并调用
getSignInInfo()
拉取详情并通知。包含"您今天已经打过卡了"→ 推送"已签到"通知。
否则视为失败(可能 Cookie 失效、站点改版或 sign 错误)并通知。
以
https://club.fnnas.com/plugin.php?id=zqlj_sign&sign=${dynamicSign}
发送 GET 请求完成签到。
根据返回页面内容判断:
getSignInInfo()
再次访问签到页,抽取打卡统计信息,如:最近打卡、本月打卡、连续打卡、累计打卡、累计/最近奖励、当前打卡等级等。
解析方式:用选择器定位
li
,把文本中冒号后的值提取出来,拼成多行消息,通过通知推送。若页面结构变更导致解析不到信息,会通知失败。
main()
(主流程)检查
FN_COOKIE
是否存在;调用
getDynamicSign()
拿到 sign;用
signIn(sign)
完成签到;全程日志输出,结束后打印"任务执行完毕"。
运行流程概览
读取环境变量
FN_COOKIE
。抓签到页 → 解析签到链接 → 提取 sign。
带
sign
访问签到接口 → 判断结果:成功/已签/失败。成功则抓取并推送签到详情;其他情况推送错误或已签通知。
常见失败原因(脚本内已有处理/提示)
Cookie 过期/错误(未登陆态)。
页面结构调整(找不到签到链接或统计信息)。
sign 规则变化或接口调整。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
【相关文章】
没有评论:
发表评论