TL;DR:手里有台 24 小时在线的 Linux 小鸡,却还在每天手动点网页签到?这篇用纯 Python(只依赖
requests)直接打 API 完成登录+签到,支持多账号、带飞书加签卡片推送,1 核 512M 也能秒级跑完。核心难点是网站的FingerprintJS浏览器指纹——用「抓一次、长期复用」绕过。脚本可直接抄。
为什么不用 Selenium
很多签到教程让你上 Selenium 模拟浏览器,但它太吃内存,无头(Headless)模式还容易报错,在小内存 VPS 上很难受。
我的做法是直接模拟 API 请求:抓清楚登录/签到接口要哪些字段,用 requests 构造 HTTP 请求发过去。好处很直接:
- 资源占用极低(几 MB 内存)
- 速度快(秒级完成)
- 稳定(不受网页加载影响)
唯一的小坎是网站用了 FingerprintJS(浏览器指纹)做风控。但指纹只要环境不变就基本固定,所以抓一次、长期复用即可。
第一步:抓到关键的 Fingerprint
这步最关键。因为登录成功后页面会瞬间跳转,普通抓包根本看不清,得讲点顺序:
🚨 严格按顺序操作,顺序错了就抓不到。
- 用电脑浏览器(Chrome/Edge)打开登录页。
- 按 F12 打开开发者工具,切到 Network(网络) 面板。
- 确保左上角圆点是红色(正在录制)。
- 务必勾选 "Preserve log"(保留日志)——防止页面跳转后登录请求被清空,这是最容易漏的一步。
- 点 "Fetch/XHR" 筛选,只看数据请求。
- 输入账号密码,点登录。
- 列表里会出现名为
login(或auth/login)的请求,点开它,在右侧 Payload 里找到fingerprint,把那串长字符复制下来备用。
第二步:准备配置文件
为了安全,账号密码和代码分开。在服务器上建个目录,比如 /root/scripts/neworld/,创建 config.json:
{
"url_base": "https://neworld.cloud",
"feishu": {
"enable": true,
"webhook": "https://open.feishu.cn/open-apis/bot/v2/hook/你的Webhook地址",
"secret": "你的加签密钥(在飞书机器人安全设置里看)"
},
"accounts": [
{
"email": "user1@gmail.com",
"password": "mypassword123",
"fingerprint": "这里填刚刚抓到的那一串字符_1",
"note": "我的主力号"
},
{
"email": "user2@qq.com",
"password": "mypassword456",
"fingerprint": "这里填刚刚抓到的那一串字符_2",
"note": "我的小号"
}
]
}
💡 多账号就在
accounts里复制粘贴大括号块,想加几个加几个。
第三步:部署核心脚本
脚本集成了三块:飞书 HmacSHA256 加签、每账号独立 Session(会话隔离)顺序执行、以及飞书卡片生成。先装依赖:
pip install requests
创建 auto_sign.py:
# -*- coding: utf-8 -*-
import requests, json, logging, time, random, os, hashlib, base64, hmac
# ==================== 基础配置 ====================
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILE = os.path.join(BASE_DIR, 'config.json')
LOG_FILE = os.path.join(BASE_DIR, 'sign_task.log')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filename=LOG_FILE, filemode='a')
console = logging.StreamHandler()
logging.getLogger('').addHandler(console)
# ==================== 飞书签名算法 ====================
def gen_sign(timestamp, secret):
string_to_sign = '{}\n{}'.format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
return base64.b64encode(hmac_code).decode('utf-8')
# ==================== 发送飞书美化卡片 ====================
def send_feishu_card(config, results):
feishu = config.get('feishu', {})
if not feishu.get('enable'): return
timestamp = str(int(time.time()))
sign = gen_sign(timestamp, feishu['secret']) if feishu.get('secret') else ""
# 构建卡片元素
elements = [{"tag": "div", "text": {"tag": "lark_md", "content": f"📅 **执行时间**: {time.strftime('%Y-%m-%d %H:%M:%S')}"}}, {"tag": "hr"}]
for res in results:
status_icon = "🟢" if res['login'] else "🔴"
# 结果图标逻辑:成功🎉 / 重复🔁 / 失败📝
msg_icon = "🎉" if "成功" in res['msg'] else ("🔁" if "已经" in res['msg'] else "📝")
elements.append({
"tag": "div",
"text": {"tag": "lark_md", "content": f"👤 **{res['name']}**\n{status_icon} {'登录成功' if res['login'] else '登录失败'} | {msg_icon} {res['msg']}"}
})
elements.append({"tag": "hr"})
elements.append({"tag": "note", "elements": [{"tag": "plain_text", "content": "来自 Linux 最强自动签到脚本"}]})
payload = {
"timestamp": timestamp, "sign": sign, "msg_type": "interactive",
"card": {"config": {"wide_screen_mode": True}, "header": {"template": "blue", "title": {"content": "☁️ 新界云 自动签到报告", "tag": "plain_text"}}, "elements": elements}
}
try:
requests.post(feishu['webhook'], json=payload)
logging.info("🔔 飞书通知已发送")
except Exception as e:
logging.error(f"🔔 发送失败: {e}")
# ==================== 机器人逻辑 ====================
class Bot:
def __init__(self, acc, url):
self.acc, self.url = acc, url
self.sess = requests.Session()
self.sess.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/115.0.0.0 Safari/537.36", "Content-Type": "application/json", "Origin": url, "Referer": f"{url}/auth/login"})
def run(self):
res = {"name": self.acc.get('note', self.acc['email']), "login": False, "msg": "未执行"}
try:
# 1. 登录
logging.info(f"[{res['name']}] 正在登录...")
login_resp = self.sess.post(f"{self.url}/auth/login", data=json.dumps({
"email": self.acc['email'], "passwd": self.acc['password'], "fingerprint": self.acc['fingerprint'], "code": "", "remember_me": "false"
}), timeout=15).json()
if login_resp.get("ret") == 1:
res['login'] = True
time.sleep(random.uniform(2, 5)) # 模拟人类延迟
# 2. 签到
self.sess.headers.update({"Referer": f"{self.url}/user"})
check_resp = self.sess.post(f"{self.url}/user/checkin", timeout=15).json()
res['msg'] = check_resp.get('msg', '未知返回')
logging.info(f"[{res['name']}] ✅ 结果: {res['msg']}")
else:
res['msg'] = f"登录失败: {login_resp.get('msg')}"
logging.error(f"[{res['name']}] ❌ {res['msg']}")
except Exception as e:
res['msg'] = f"异常: {str(e)}"
logging.error(f"[{res['name']}] 💥 {res['msg']}")
return res
def main():
logging.info("🚀 任务启动")
if not os.path.exists(CONFIG_FILE): return logging.error("找不到配置文件")
with open(CONFIG_FILE, 'r', encoding='utf-8') as f: config = json.load(f)
results = []
for i, acc in enumerate(config.get('accounts', [])):
results.append(Bot(acc, config['url_base']).run())
if i < len(config['accounts']) - 1: time.sleep(random.randint(5, 10)) # 多号间隔防止封IP
send_feishu_card(config, results)
logging.info("🏁 任务结束")
if __name__ == "__main__":
main()
几个值得留意的设计点:
- 飞书加签:
gen_sign按飞书要求用timestamp\nsecret做 HmacSHA256 再 base64,对应机器人「加签」安全模式。 - 顺序执行 + 随机间隔:多账号是
for循环依次跑的(不是多线程),每个账号一个独立requests.Session,账号之间sleep(5~10)随机间隔降低风控风险。 - 登录判据:接口返回
ret == 1视为登录成功,再带着同一 Session 去打/user/checkin。
第四步:挂上定时任务(crontab)
让它每天 8:30 自动跑。crontab -e 加一行:
# 每天 08:30 运行
30 8 * * * /usr/bin/python3 /root/scripts/neworld/auto_sign.py
效果
每天早上飞书会收到这样一张卡片:
☁️ 新界云 自动签到报告 📅 执行时间: 2026-01-23 08:30:15 ────────────────────── 👤 我的主力号 🟢 登录成功 | 🎉 签到成功 (获得 500MB) ────────────────────── 👤 我的小号 🟢 登录成功 | 🔁 今天已经签到过了
常见问题(FAQ)
Q:Fingerprint 会过期吗? A:基本不会。只要那台电脑硬件和浏览器不升级,指纹就固定。我实测用了一年都没变。
Q:日志提示「环境异常」?
A:极少数情况。可能是脚本里写的 User-Agent 和你抓指纹时的浏览器差太多。把脚本里的 User-Agent 换成你自己抓包看到的那个即可。
Q:配置文件安全吗?
A:建议 chmod 600 config.json,只有你自己能读,防止同机其他用户偷看密码。
小结
整套方案的核心就一句话:与其模拟浏览器,不如直接打 API——前提是花点功夫把 fingerprint 抓出来复用。配好之后挂 crontab,服务器替你每天签到,结果直接推到飞书。这类「让 24 小时在线的机器替你打工」的玩法,前提通常是能远程管到那台机器——如果你也在折腾内网设备,可以看看我另一篇 用 FRP 给内网设备做 SSH 穿透。