用青龙面板配置NodeSeek自动签到收鸡腿

发布时间: 2025-10-01 热度: 628

前言

NodeSeek 是MJJ们聊天吹牛消磨时间的地方。论坛每天签到送鸡腿,现在把青龙脚本签到部署方法整理分享出来。


签到效果

温馨提示: NS在墙外,签到环境也同时需要。


部署方法

1、先抓取NodeSeek社区的Cookie备用,抓取方法:打开页面登录账号按F12,刷新页面。复制Cookie,如下图:

2、进入青龙面板脚本管理里面,添加脚本nodeseek.py,如所示:

3、进环境变量添加Cookie变量。如果有多个,添加多行。格式如下:

  • NODESEEK_COOKIE1:刚才抓取的Cookie
  • NODESEEK_COOKIE2:Cookie

4、点左侧定时任务添加定时任务,名称随意,命令脚本task jiaoben/nodeseek.py(注意你的脚本路径),定时规则自行设置,也可以直接抄我的,每天早上9点18分运行。

5、添加完成后手动运行一次无报错即可。

最后,可以配置推送通知,也可以不用配置。


附上签到脚本

# -*- coding: utf-8 -*-
"""
cron "23 14 * * *" script-path=xxx.py,tag=匹配cron用
new Env('nodeseek签到')
"""
import os
import time
import random
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
import requests
import json

# ---------------- PushDeer 通知模块 ----------------
def pushdeer_send(title, content, pushkey):
    """发送PushDeer通知"""
    if not pushkey:
        print("未设置PUSHDEER_PUSHKEY,跳过通知发送")
        return False

    try:
        url = "https://api2.pushdeer.com/message/push"
        data = {
            "pushkey": pushkey,
            "text": title,
            "desp": content,
            "type": "markdown"
        }

        response = requests.post(url, data=data, timeout=10)
        result = response.json()

        if result.get("code") == 0:
            print("PushDeer通知发送成功")
            return True
        else:
            print(f"PushDeer通知发送失败: {result.get('error', '未知错误')}")
            return False

    except Exception as e:
        print(f"PushDeer通知发送异常: {str(e)}")
        return False

# ---------------- 通知模块动态加载 ----------------
hadsend = False
send = None
try:
    from notify import send
    hadsend = True
    print("检测到青龙通知模块,将使用青龙通知")
except ImportError:
    print("未加载青龙通知模块,将使用PushDeer通知")

# ---------------- 签到逻辑 ----------------
def sign(NODESEEK_COOKIE, ns_random):
    if not NODESEEK_COOKIE:
        return "invalid", "无有效Cookie"

    headers = {
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
        'origin': "https://www.nodeseek.com",
        'referer': "https://www.nodeseek.com/board",
        'Content-Type': 'application/json',
        'Cookie': NODESEEK_COOKIE
    }
    try:
        url = f"https://www.nodeseek.com/api/attendance?random={ns_random}"
        response = requests.post(url, headers=headers)
        data = response.json()
        msg = data.get("message", "")
        if "鸡腿" in msg or data.get("success"):
            return "success", msg
        elif "已完成签到" in msg:
            return "already", msg
        elif data.get("status") == 404:
            return "invalid", msg
        return "fail", msg
    except Exception as e:
        return "error", str(e)

# ---------------- 查询签到收益统计函数 ----------------
def get_signin_stats(NODESEEK_COOKIE, days=30):
    """查询前days天内的签到收益统计"""
    if not NODESEEK_COOKIE:
        return None, "无有效Cookie"

    if days <= 0:
        days = 1

    headers = {
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
        'origin': "https://www.nodeseek.com",
        'referer': "https://www.nodeseek.com/board",
        'Cookie': NODESEEK_COOKIE
    }

    try:
        # 使用UTC+8时区(上海时区)
        shanghai_tz = ZoneInfo("Asia/Shanghai")
        now_shanghai = datetime.now(shanghai_tz)

        # 计算查询开始时间:当前时间减去指定天数
        query_start_time = now_shanghai - timedelta(days=days)

        # 获取多页数据以确保覆盖指定天数内的所有数据
        all_records = []
        page = 1

        while page <= 10:  # 最多查询10页
            url = f"https://www.nodeseek.com/api/account/credit/page-{page}"
            response = requests.get(url, headers=headers)
            data = response.json()

            if not data.get("success") or not data.get("data"):
                break

            records = data.get("data", [])
            if not records:
                break

            # 检查最后一条记录的时间,如果超出查询范围就停止
            last_record_time = datetime.fromisoformat(
                records[-1][3].replace('Z', '+00:00'))
            last_record_time_shanghai = last_record_time.astimezone(shanghai_tz)
            if last_record_time_shanghai < query_start_time:
                # 只添加在查询范围内的记录
                for record in records:
                    record_time = datetime.fromisoformat(
                        record[3].replace('Z', '+00:00'))
                    record_time_shanghai = record_time.astimezone(shanghai_tz)
                    if record_time_shanghai >= query_start_time:
                        all_records.append(record)
                break
            else:
                all_records.extend(records)

            page += 1
            time.sleep(0.5)

        # 筛选指定天数内的签到收益记录
        signin_records = []
        for record in all_records:
            amount, balance, description, timestamp = record
            record_time = datetime.fromisoformat(
                timestamp.replace('Z', '+00:00'))
            record_time_shanghai = record_time.astimezone(shanghai_tz)

            # 只统计指定天数内的签到收益
            if (record_time_shanghai >= query_start_time and
                    "签到收益" in description and "鸡腿" in description):
                signin_records.append({
                    'amount': amount,
                    'date': record_time_shanghai.strftime('%Y-%m-%d'),
                    'description': description
                })

        # 生成时间范围描述
        period_desc = f"近{days}天"
        if days == 1:
            period_desc = "今天"

        if not signin_records:
            return {
                'total_amount': 0,
                'average': 0,
                'days_count': 0,
                'records': [],
                'period': period_desc,
            }, f"查询成功,但没有找到{period_desc}的签到记录"

        # 统计数据
        total_amount = sum(record['amount'] for record in signin_records)
        days_count = len(signin_records)
        average = round(total_amount / days_count, 2) if days_count > 0 else 0

        stats = {
            'total_amount': total_amount,
            'average': average,
            'days_count': days_count,
            'records': signin_records,
            'period': period_desc
        }

        return stats, "查询成功"

    except Exception as e:
        return None, f"查询异常: {str(e)}"

# ---------------- 显示签到统计信息 ----------------
def print_signin_stats(stats, account_name):
    """打印签到统计信息"""
    if not stats:
        return

    print(f"\n==== {account_name} 签到收益统计 ({stats['period']}) ====")
    print(f"签到天数: {stats['days_count']} 天")
    print(f"总获得鸡腿: {stats['total_amount']} 个")
    print(f"平均每日鸡腿: {stats['average']} 个")

# ---------------- 时间格式化函数 ----------------
def format_time_remaining(seconds):
    """格式化剩余时间显示"""
    if seconds <= 0:
        return "立即执行"

    hours = seconds // 3600
    minutes = (seconds % 3600) // 60
    secs = seconds % 60

    if hours > 0:
        return f"{hours}小时{minutes}{secs}秒"
    elif minutes > 0:
        return f"{minutes}{secs}秒"
    else:
        return f"{secs}秒"

# ---------------- 随机延迟等待函数 ----------------
def wait_with_countdown(delay_seconds, account_name):
    """带倒计时的延迟等待"""
    if delay_seconds <= 0:
        return

    print(f"{account_name} 需要等待 {format_time_remaining(delay_seconds)}")

    # 显示倒计时(每10秒显示一次,最后10秒每秒显示)
    remaining = delay_seconds
    while remaining > 0:
        if remaining <= 10 or remaining % 10 == 0:
            print(f"{account_name} 倒计时: {format_time_remaining(remaining)}")

        sleep_time = 1 if remaining <= 10 else min(10, remaining)
        time.sleep(sleep_time)
        remaining -= sleep_time

# ---------------- 主流程 ----------------
if __name__ == "__main__":
    ns_random = os.getenv("NS_RANDOM", "true")

    # 随机签到时间窗口配置(秒)
    max_random_delay = int(os.getenv("MAX_RANDOM_DELAY", "3600"))  # 默认1小时=3600秒
    random_signin = os.getenv("RANDOM_SIGNIN", "true").lower() == "true"

    # 获取PushDeer的PushKey
    pushdeer_pushkey = os.getenv("PUSHDEER_PUSHKEY", "")

    # 从环境变量读取Cookie
    cookie_list = []
    index = 1
    while True:
        # 尝试读取 NODESEEK_COOKIE1, NODESEEK_COOKIE2, NODESEEK_COOKIE3, ...
        cookie = os.getenv(f"NODESEEK_COOKIE{index}")
        if cookie is None:
            # 如果没有找到带数字的变量,尝试读取不带数字的变量(兼容旧配置)
            if index == 1:
                cookie = os.getenv("NODESEEK_COOKIE")
            else:
                break
        if cookie and cookie.strip():
            cookie_list.append(cookie.strip())
            index += 1
        else:
            break

    # 如果上面没有找到cookie,尝试从旧的格式读取(用&分隔的多个cookie)
    if not cookie_list:
        all_cookies = os.getenv("NODESEEK_COOKIE", "")
        if all_cookies:
            cookie_list = [c.strip() for c in all_cookies.split("&") if c.strip()]

    print(f"共发现 {len(cookie_list)} 个Cookie")
    print(f"随机签到: {'启用' if random_signin else '禁用'}")
    print(f"PushDeer通知: {'已配置' if pushdeer_pushkey else '未配置'}")

    if len(cookie_list) == 0:
        error_msg = "未找到任何Cookie,请设置NODESEEK_COOKIE环境变量"
        print(error_msg)
        if pushdeer_pushkey:
            pushdeer_send("NodeSeek签到错误", error_msg, pushdeer_pushkey)
        exit(1)

    # 为每个账号生成随机延迟时间
    signin_schedule = []
    current_time = datetime.now()

    if random_signin:
        print(f"随机签到时间窗口: {max_random_delay // 60} 分钟")
        print("\n==== 生成签到时间表 ====")

        for i, cookie in enumerate(cookie_list):
            account_index = i + 1
            display_user = f"账号{account_index}"

            # 为每个账号随机分配延迟时间
            delay_seconds = random.randint(0, max_random_delay)
            signin_time = current_time + timedelta(seconds=delay_seconds)

            signin_schedule.append({
                'account_index': account_index,
                'display_user': display_user,
                'cookie': cookie,
                'delay_seconds': delay_seconds,
                'signin_time': signin_time
            })

            print(f"{display_user}: 延迟 {format_time_remaining(delay_seconds)} 后签到 "
                  f"(预计 {signin_time.strftime('%H:%M:%S')} 签到)")

        # 按延迟时间排序
        signin_schedule.sort(key=lambda x: x['delay_seconds'])

        print(f"\n==== 签到执行顺序 ====")
        for item in signin_schedule:
            print(f"{item['display_user']}: {item['signin_time'].strftime('%H:%M:%S')}")
    else:
        # 不启用随机签到,立即执行所有账号
        for i, cookie in enumerate(cookie_list):
            account_index = i + 1
            display_user = f"账号{account_index}"
            signin_schedule.append({
                'account_index': account_index,
                'display_user': display_user,
                'cookie': cookie,
                'delay_seconds': 0,
                'signin_time': current_time
            })

    print(f"\n==== 开始执行签到任务 ====")

    # 汇总通知消息
    summary_messages = []

    # 按计划执行签到
    for item in signin_schedule:
        display_user = item['display_user']
        cookie = item['cookie']
        delay_seconds = item['delay_seconds']

        # 等待到指定时间
        if delay_seconds > 0:
            wait_with_countdown(delay_seconds, display_user)

        print(f"\n==== {display_user} 开始签到 ====")
        print(f"当前时间: {datetime.now().strftime('%H:%M:%S')}")

        result, msg = sign(cookie, ns_random)

        if result in ["success", "already"]:
            print(f"{display_user} 签到成功: {msg}")

            # 查询签到收益统计
            print("正在查询签到收益统计...")
            stats, stats_msg = get_signin_stats(cookie, 30)
            if stats:
                print_signin_stats(stats, display_user)
                summary_msg = f"✅ {display_user}: 签到成功\n📊 {stats['period']}已签到{stats['days_count']}天\n🎯 共获得{stats['total_amount']}鸡腿\n📈 平均{stats['average']}鸡腿/天"
            else:
                print(f"统计查询失败: {stats_msg}")
                summary_msg = f"✅ {display_user}: 签到成功\n{msg}"

            summary_messages.append(summary_msg)

            # 发送通知
            if hadsend:
                try:
                    notification_msg = f"{display_user} 签到成功:{msg}"
                    if stats:
                        notification_msg += f"\n{stats['period']}已签到{stats['days_count']}天,共获得{stats['total_amount']}个鸡腿,平均{stats['average']}个/天"
                    send("NodeSeek 签到", notification_msg)
                except Exception as e:
                    print(f"发送青龙通知失败: {e}")

        else:
            error_msg = f"❌ {display_user}: 签到失败\n{msg}"
            print(f"{display_user} 签到失败: {msg}")
            summary_messages.append(error_msg)

            if hadsend:
                try:
                    send("NodeSeek 签到失败", f"{display_user} 签到失败:{msg}")
                except Exception as e:
                    print(f"发送青龙通知失败: {e}")

    print(f"\n==== 所有账号签到完成 ====")
    print(f"完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

    # 发送PushDeer汇总通知
    if pushdeer_pushkey and summary_messages:
        try:
            title = f"NodeSeek签到完成 ({len(cookie_list)}账号)"
            content = "## 📋 NodeSeek签到汇总\n\n"
            content += "\n\n".join(summary_messages)
            content += f"\n\n⏰ 完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"

            pushdeer_send(title, content, pushdeer_pushkey)
        except Exception as e:
            print(f"发送PushDeer汇总通知失败: {e}")

    # 如果没有配置任何通知方式,但需要发送失败通知
    elif not hadsend and not pushdeer_pushkey:
        # 检查是否有失败的任务,如果有则尝试使用第一个cookie发送通知
        failed_messages = [msg for msg in summary_messages if "❌" in msg]
        if failed_messages and cookie_list:
            print("检测到签到失败但未配置通知,无法发送失败提醒")

在下方留下您的评论.加入TG群.打赏🍗