Initial Qinglong script classification corpus

This commit is contained in:
Hermes Agent
2026-05-23 18:48:48 +00:00
commit 5b4854515c
32 changed files with 15496 additions and 0 deletions

View File

@@ -0,0 +1,292 @@
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/popup.js
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/popup.js
// # Repo: huwangkeji/juejin_checkin
// # Path: juejin-extension/popup.js
// # UploadedAt: 2026-05-19T14:34:11Z
// # SHA256: 0a4d49831a306fa984f62b0d1b3f26f7fc1274a625d08b5f4622ba94121b8469
// # Category: web版/抓包
// # Evidence: web/H5关键词 + cookie/token/header
//
/**
* 掘金参数提取器 - Popup脚本
*/
// 参数配置key、显示名、青龙环境变量名
const PARAM_CONFIG = [
{ key: 'cookie', name: 'Cookie', env: 'JUEJIN_COOKIE', isLong: true },
{ key: 'aid', name: 'AID', env: 'JUEJIN_AID', isLong: false },
{ key: 'uuid', name: 'UUID', env: 'JUEJIN_UUID', isLong: true },
{ key: 'msToken', name: 'msToken', env: 'JUEJIN_MSTOKEN', isLong: true },
{ key: 'a_bogus', name: 'a_bogus', env: 'JUEJIN_A_BOGUS', isLong: true },
];
let currentData = null;
// 加载数据
async function loadData() {
return new Promise((resolve) => {
chrome.storage.local.get('juejinData', (result) => {
resolve(result.juejinData || null);
});
});
}
// 渲染界面
async function render() {
currentData = await loadData();
const emptyState = document.getElementById('emptyState');
const paramsList = document.getElementById('paramsList');
const actionsBar = document.getElementById('actionsBar');
const statusDot = document.getElementById('statusDot');
const statusText = document.getElementById('statusText');
const captureTime = document.getElementById('captureTime');
if (!currentData || !currentData.cookie) {
// 无数据
emptyState.style.display = 'block';
paramsList.style.display = 'none';
actionsBar.style.display = 'none';
statusDot.className = 'status-dot empty';
statusText.textContent = '等待捕获...';
captureTime.textContent = '';
return;
}
// 有数据
emptyState.style.display = 'none';
paramsList.style.display = 'block';
actionsBar.style.display = 'flex';
statusDot.className = 'status-dot captured';
statusText.textContent = '✅ 参数已捕获';
captureTime.textContent = currentData.captureTime || '';
// 渲染参数列表
paramsList.innerHTML = PARAM_CONFIG.map((config) => {
const value = currentData[config.key] || '';
const isEmpty = !value;
const displayValue = isEmpty ? '未捕获到' : value;
const valueClass = isEmpty ? 'param-value empty' : 'param-value';
return `
<div class="param-item">
<div class="param-header">
<span class="param-name">${config.name}</span>
<div style="display:flex;align-items:center;gap:6px;">
<span class="param-env">${config.env}</span>
<button class="copy-btn" data-key="${config.key}" title="复制${config.name}">复制</button>
</div>
</div>
<div class="${valueClass}" title="${displayValue}">${displayValue}</div>
</div>
`;
}).join('');
// 绑定复制按钮
paramsList.querySelectorAll('.copy-btn').forEach((btn) => {
btn.addEventListener('click', () => {
const key = btn.dataset.key;
const value = currentData[key] || '';
copyToClipboard(value, btn);
});
});
}
// 复制到剪贴板
function copyToClipboard(text, btn) {
navigator.clipboard.writeText(text).then(() => {
if (btn) {
const original = btn.textContent;
btn.textContent = '已复制 ✓';
btn.classList.add('copied');
setTimeout(() => {
btn.textContent = original;
btn.classList.remove('copied');
}, 1500);
}
});
}
// 生成青龙面板环境变量格式
function generateQinglongFormat() {
if (!currentData) return '';
const lines = [];
lines.push('# 掘金签到脚本 - 青龙面板环境变量');
lines.push('# 复制以下内容到青龙面板 -> 环境变量');
lines.push('');
lines.push(`JUEJIN_COOKIE='${currentData.cookie || ''}'`);
lines.push(`JUEJIN_AID='${currentData.aid || '2608'}'`);
lines.push(`JUEJIN_UUID='${currentData.uuid || ''}'`);
lines.push(`JUEJIN_MSTOKEN='${currentData.msToken || ''}'`);
lines.push(`JUEJIN_A_BOGUS='${currentData.a_bogus || ''}'`);
lines.push('');
lines.push(`# 捕获时间: ${currentData.captureTime || '未知'}`);
lines.push('# 参数有效期约30天过期需重新获取');
return lines.join('\n');
}
// 绑定事件
document.getElementById('copyAllBtn').addEventListener('click', () => {
const text = generateQinglongFormat();
copyToClipboard(text, document.getElementById('copyAllBtn'));
});
document.getElementById('goJuejinBtn').addEventListener('click', () => {
chrome.tabs.create({ url: 'https://juejin.cn' });
});
document.getElementById('refreshBtn').addEventListener('click', () => {
render();
});
// "从当前页面提取"按钮
document.getElementById('extractNowBtn').addEventListener('click', async () => {
const btn = document.getElementById('extractNowBtn');
const originalText = btn.textContent;
btn.textContent = '⏳ 提取中...';
btn.disabled = true;
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab || !tab.url || !tab.url.includes('juejin.cn')) {
alert('请先在掘金网站 (juejin.cn) 页面点击此按钮');
btn.textContent = originalText;
btn.disabled = false;
return;
}
// 在页面中执行提取脚本:主动发请求 -> 等待 hook 捕获 -> 读取 sessionStorage
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id, allFrames: false },
world: 'MAIN',
func: () => {
return new Promise((resolve) => {
const data = {
cookie: '',
aid: '',
uuid: '',
msToken: '',
a_bogus: '',
spider: '',
captureTime: new Date().toLocaleString('zh-CN'),
captureUrl: location.href,
};
// 辅助:从 URL 提取参数
function extractFromUrl(url) {
try {
const u = new URL(url);
return {
aid: u.searchParams.get('aid') || '',
uuid: u.searchParams.get('uuid') || '',
msToken: u.searchParams.get('msToken') || '',
a_bogus: u.searchParams.get('a_bogus') || '',
spider: u.searchParams.get('spider') || '',
};
} catch (e) { return null; }
}
// 1. 获取 cookie
try { data.cookie = document.cookie; } catch (e) {}
// 2. 扫描 performance entries
try {
const entries = performance.getEntriesByType('resource');
for (const entry of entries) {
if (entry.name && entry.name.includes('api.juejin.cn')) {
const p = extractFromUrl(entry.name);
if (p) {
if (p.aid) data.aid = p.aid;
if (p.uuid && p.uuid.length > 5) data.uuid = p.uuid;
if (p.msToken && p.msToken.length > 5) data.msToken = p.msToken;
if (p.a_bogus && p.a_bogus.length > 5) data.a_bogus = p.a_bogus;
if (p.spider) data.spider = p.spider;
}
}
}
} catch (e) {}
// 3. 从 content script 的 sessionStorage 读取(如果 content.js 已捕获)
try {
const stored = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
if (stored.cookie) data.cookie = stored.cookie;
if (stored.aid) data.aid = stored.aid;
if (stored.uuid) data.uuid = stored.uuid;
if (stored.msToken) data.msToken = stored.msToken;
if (stored.a_bogus) data.a_bogus = stored.a_bogus;
if (stored.spider) data.spider = stored.spider;
} catch (e) {}
// 4. 主动触发一个请求来诱捕参数content.js 的 MAIN world hook 会捕获)
const needsTrigger = !data.uuid || !data.msToken || !data.a_bogus;
if (needsTrigger) {
try {
fetch('https://api.juejin.cn/growth_api/v1/get_today_status?aid=2608', {
credentials: 'include',
headers: { 'Accept': 'application/json' },
}).catch(() => {});
fetch('https://api.juejin.cn/user_api/v1/user/get?aid=2608', {
credentials: 'include',
headers: { 'Accept': 'application/json' },
}).catch(() => {});
} catch (e) {}
// 等待 hook 处理后再读取
setTimeout(() => {
try {
const stored2 = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
if (stored2.cookie) data.cookie = stored2.cookie;
if (stored2.aid) data.aid = stored2.aid;
if (stored2.uuid) data.uuid = stored2.uuid;
if (stored2.msToken) data.msToken = stored2.msToken;
if (stored2.a_bogus) data.a_bogus = stored2.a_bogus;
if (stored2.spider) data.spider = stored2.spider;
} catch (e) {}
resolve(data);
}, 800);
} else {
resolve(data);
}
});
},
});
const extracted = results[0]?.result;
if (extracted) {
// 合并到已有数据
chrome.storage.local.get('juejinData', (result) => {
const existing = result.juejinData || {};
const merged = {
...existing,
...Object.fromEntries(
Object.entries(extracted).filter(([_, v]) => v && v !== '')
),
};
chrome.storage.local.set({ juejinData: merged }, () => {
render();
btn.textContent = '✅ 提取完成';
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 1500);
});
});
} else {
alert('未能从当前页面提取到参数,请刷新页面后重试');
btn.textContent = originalText;
btn.disabled = false;
}
} catch (e) {
console.error(e);
alert('提取失败: ' + e.message);
btn.textContent = originalText;
btn.disabled = false;
}
});
// 初始渲染
render();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,574 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/notify.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/notify.py
# Repo: lksky8/sign-ql
# Path: notify.py
# UploadedAt: 2025-01-11T18:39:35Z
# SHA256: 9961f57695cfba609fbfda0c314ab632f147c0d068b0f0338eaaa1ef796eedf8
# Category: web版/抓包
# Evidence: web/H5关键词 + cookie/token/header
#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
import base64
import hashlib
import hmac
import json
import os
import re
import threading
import time
import urllib.parse
import requests
# 原先的 print 函数和主线程的锁
_print = print
mutex = threading.Lock()
# 定义新的 print 函数
def print(text, *args, **kw):
"""
使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
"""
with mutex:
_print(text, *args, **kw)
# 通知服务
# fmt: off
push_config = {
'HITOKOTO': False, # 启用一言(随机句子)
'BARK_PUSH': '', # bark IP 或设备码https://api.day.app/DxHcxxxxxRxxxxxxcm/
'BARK_ARCHIVE': '', # bark 推送是否存档
'BARK_GROUP': '', # bark 推送分组
'BARK_SOUND': '', # bark 推送声音
'BARK_ICON': '', # bark 推送图标
'CONSOLE': True, # 控制台输出
'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
'FSKEY': '', # 飞书机器人的 FSKEY
'GOBOT_URL': '', # go-cqhttp
# 推送到个人QQhttp://127.0.0.1/send_private_msg
# 群http://127.0.0.1/send_group_msg
'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
# GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
# /send_group_msg 时填入 group_id=QQ群
'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
'GOTIFY_TOKEN': '', # gotify的消息应用token
'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
'PUSH_KEY': '', # server 酱的 PUSH_KEY兼容旧版与 Turbo 版
'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
'QYWX_AM': '', # 企业微信应用
'QYWX_KEY': '', # 企业微信机器人
'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
'TG_USER_ID': '', # tg 机器人的 TG_USER_ID1434078534
'TG_API_HOST': '', # tg 代理 api
'TG_PROXY_AUTH': '', # tg 代理认证参数
'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
}
notify_function = []
# fmt: on
# 首先读取 面板变量 或者 github action 运行变量
for k in push_config:
if os.getenv(k):
v = os.getenv(k)
push_config[k] = v
def bark(title: str, content: str) -> None:
"""
使用 bark 推送消息。
"""
if not push_config.get("BARK_PUSH"):
print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
return
print("bark 服务启动")
if push_config.get("BARK_PUSH").startswith("http"):
url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
else:
url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
bark_params = {
"BARK_ARCHIVE": "isArchive",
"BARK_GROUP": "group",
"BARK_SOUND": "sound",
"BARK_ICON": "icon",
}
params = ""
for pair in filter(
lambda pairs: pairs[0].startswith("BARK_")
and pairs[0] != "BARK_PUSH"
and pairs[1]
and bark_params.get(pairs[0]),
push_config.items(),
):
params += f"{bark_params.get(pair[0])}={pair[1]}&"
if params:
url = url + "?" + params.rstrip("&")
response = requests.get(url).json()
if response["code"] == 200:
print("bark 推送成功!")
else:
print("bark 推送失败!")
def console(title: str, content: str) -> None:
"""
使用 控制台 推送消息。
"""
print(f"{title}\n\n{content}")
def dingding_bot(title: str, content: str) -> None:
"""
使用 钉钉机器人 推送消息。
"""
if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
return
print("钉钉机器人 服务启动")
timestamp = str(round(time.time() * 1000))
secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
string_to_sign_enc = string_to_sign.encode("utf-8")
hmac_code = hmac.new(
secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}&timestamp={timestamp}&sign={sign}'
headers = {"Content-Type": "application/json;charset=utf-8"}
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
response = requests.post(
url=url, data=json.dumps(data), headers=headers, timeout=15
).json()
if not response["errcode"]:
print("钉钉机器人 推送成功!")
else:
print("钉钉机器人 推送失败!")
def feishu_bot(title: str, content: str) -> None:
"""
使用 飞书机器人 推送消息。
"""
if not push_config.get("FSKEY"):
print("飞书 服务的 FSKEY 未设置!!\n取消推送")
return
print("飞书 服务启动")
url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
response = requests.post(url, data=json.dumps(data)).json()
if response.get("StatusCode") == 0:
print("飞书 推送成功!")
else:
print("飞书 推送失败!错误信息如下:\n", response)
def go_cqhttp(title: str, content: str) -> None:
"""
使用 go_cqhttp 推送消息。
"""
if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
return
print("go-cqhttp 服务启动")
url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
response = requests.get(url).json()
if response["status"] == "ok":
print("go-cqhttp 推送成功!")
else:
print("go-cqhttp 推送失败!")
def gotify(title:str,content:str) -> None:
"""
使用 gotify 推送消息。
"""
if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
return
print("gotify 服务启动")
url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
data = {"title": title,"message": content,"priority": push_config.get("GOTIFY_PRIORITY")}
response = requests.post(url,data=data).json()
if response.get("id"):
print("gotify 推送成功!")
else:
print("gotify 推送失败!")
def iGot(title: str, content: str) -> None:
"""
使用 iGot 推送消息。
"""
if not push_config.get("IGOT_PUSH_KEY"):
print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
return
print("iGot 服务启动")
url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
data = {"title": title, "content": content}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=data, headers=headers).json()
if response["ret"] == 0:
print("iGot 推送成功!")
else:
print(f'iGot 推送失败!{response["errMsg"]}')
def serverJ(title: str, content: str) -> None:
"""
通过 serverJ 推送消息。
"""
if not push_config.get("PUSH_KEY"):
print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
return
print("serverJ 服务启动")
data = {"text": title, "desp": content.replace("\n", "\n\n")}
if push_config.get("PUSH_KEY").index("SCT") != -1:
url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
else:
url = f'https://sc.ftqq.com/${push_config.get("PUSH_KEY")}.send'
response = requests.post(url, data=data).json()
if response.get("errno") == 0 or response.get("code") == 0:
print("serverJ 推送成功!")
else:
print(f'serverJ 推送失败!错误码:{response["message"]}')
def pushdeer(title: str, content: str) -> None:
"""
通过PushDeer 推送消息
"""
if not push_config.get("DEER_KEY"):
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
return
print("PushDeer 服务启动")
data = {"text": title, "desp": content, "type": "markdown", "pushkey": push_config.get("DEER_KEY")}
url = 'https://api2.pushdeer.com/message/push'
response = requests.post(url, data=data).json()
if len(response.get("content").get("result")) > 0:
print("PushDeer 推送成功!")
else:
print("PushDeer 推送失败!错误信息:", response)
def pushplus_bot(title: str, content: str) -> None:
"""
通过 push+ 推送消息。
"""
if not push_config.get("PUSH_PLUS_TOKEN"):
print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
return
print("PUSHPLUS 服务启动")
url = "http://www.pushplus.plus/send"
data = {
"token": push_config.get("PUSH_PLUS_TOKEN"),
"title": title,
"content": content,
"topic": push_config.get("PUSH_PLUS_USER"),
}
body = json.dumps(data).encode(encoding="utf-8")
headers = {"Content-Type": "application/json"}
response = requests.post(url=url, data=body, headers=headers).json()
if response["code"] == 200:
print("PUSHPLUS 推送成功!")
else:
url_old = "http://pushplus.hxtrip.com/send"
headers["Accept"] = "application/json"
response = requests.post(url=url_old, data=body, headers=headers).json()
if response["code"] == 200:
print("PUSHPLUS(hxtrip) 推送成功!")
else:
print("PUSHPLUS 推送失败!")
def qmsg_bot(title: str, content: str) -> None:
"""
使用 qmsg 推送消息。
"""
if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
return
print("qmsg 服务启动")
url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
response = requests.post(url=url, params=payload).json()
if response["code"] == 0:
print("qmsg 推送成功!")
else:
print(f'qmsg 推送失败!{response["reason"]}')
def wecom_app(title: str, content: str) -> None:
"""
通过 企业微信 APP 推送消息。
"""
if not push_config.get("QYWX_AM"):
print("QYWX_AM 未设置!!\n取消推送")
return
QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
if 4 < len(QYWX_AM_AY) > 5:
print("QYWX_AM 设置错误!!\n取消推送")
return
print("企业微信 APP 服务启动")
corpid = QYWX_AM_AY[0]
corpsecret = QYWX_AM_AY[1]
touser = QYWX_AM_AY[2]
agentid = QYWX_AM_AY[3]
try:
media_id = QYWX_AM_AY[4]
except IndexError:
media_id = ""
wx = WeCom(corpid, corpsecret, agentid)
# 如果没有配置 media_id 默认就以 text 方式发送
if not media_id:
message = title + "\n\n" + content
response = wx.send_text(message, touser)
else:
response = wx.send_mpnews(title, content, media_id, touser)
if response == "ok":
print("企业微信推送成功!")
else:
print("企业微信推送失败!错误信息如下:\n", response)
class WeCom:
def __init__(self, corpid, corpsecret, agentid):
self.CORPID = corpid
self.CORPSECRET = corpsecret
self.AGENTID = agentid
def get_access_token(self):
url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
values = {
"corpid": self.CORPID,
"corpsecret": self.CORPSECRET,
}
req = requests.post(url, params=values)
data = json.loads(req.text)
return data["access_token"]
def send_text(self, message, touser="@all"):
send_url = (
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
+ self.get_access_token()
)
send_values = {
"touser": touser,
"msgtype": "text",
"agentid": self.AGENTID,
"text": {"content": message},
"safe": "0",
}
send_msges = bytes(json.dumps(send_values), "utf-8")
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
def send_mpnews(self, title, message, media_id, touser="@all"):
send_url = (
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
+ self.get_access_token()
)
send_values = {
"touser": touser,
"msgtype": "mpnews",
"agentid": self.AGENTID,
"mpnews": {
"articles": [
{
"title": title,
"thumb_media_id": media_id,
"author": "Author",
"content_source_url": "",
"content": message.replace("\n", "<br/>"),
"digest": message,
}
]
},
}
send_msges = bytes(json.dumps(send_values), "utf-8")
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
def wecom_bot(title: str, content: str) -> None:
"""
通过 企业微信机器人 推送消息。
"""
if not push_config.get("QYWX_KEY"):
print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
return
print("企业微信机器人服务启动")
url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
headers = {"Content-Type": "application/json;charset=utf-8"}
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
response = requests.post(
url=url, data=json.dumps(data), headers=headers, timeout=15
).json()
if response["errcode"] == 0:
print("企业微信机器人推送成功!")
else:
print("企业微信机器人推送失败!")
def telegram_bot(title: str, content: str) -> None:
"""
使用 telegram 机器人 推送消息。
"""
if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
return
print("tg 服务启动")
if push_config.get("TG_API_HOST"):
url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
else:
url = (
f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
)
headers = {"Content-Type": "application/x-www-form-urlencoded"}
payload = {
"chat_id": str(push_config.get("TG_USER_ID")),
"text": f"{title}\n\n{content}",
"disable_web_page_preview": "true",
}
proxies = None
if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
"TG_PROXY_HOST"
):
push_config["TG_PROXY_HOST"] = (
push_config.get("TG_PROXY_AUTH")
+ "@"
+ push_config.get("TG_PROXY_HOST")
)
proxyStr = "http://{}:{}".format(
push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
)
proxies = {"http": proxyStr, "https": proxyStr}
response = requests.post(
url=url, headers=headers, params=payload, proxies=proxies
).json()
if response["ok"]:
print("tg 推送成功!")
else:
print("tg 推送失败!")
def one() -> str:
"""
获取一条一言。
:return:
"""
url = "https://v1.hitokoto.cn/"
res = requests.get(url).json()
return res["hitokoto"] + " ----" + res["from"]
if push_config.get("BARK_PUSH"):
notify_function.append(bark)
if push_config.get("CONSOLE"):
notify_function.append(console)
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
notify_function.append(dingding_bot)
if push_config.get("FSKEY"):
notify_function.append(feishu_bot)
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
notify_function.append(go_cqhttp)
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
notify_function.append(gotify)
if push_config.get("IGOT_PUSH_KEY"):
notify_function.append(iGot)
if push_config.get("PUSH_KEY"):
notify_function.append(serverJ)
if push_config.get("DEER_KEY"):
notify_function.append(pushdeer)
if push_config.get("PUSH_PLUS_TOKEN"):
notify_function.append(pushplus_bot)
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
notify_function.append(qmsg_bot)
if push_config.get("QYWX_AM"):
notify_function.append(wecom_app)
if push_config.get("QYWX_KEY"):
notify_function.append(wecom_bot)
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
notify_function.append(telegram_bot)
def send(title: str, content: str) -> None:
if not content:
print(f"{title} 推送内容为空!")
return
hitokoto = push_config.get("HITOKOTO")
text = one() if hitokoto else ""
content += "\n\n" + text
ts = [
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
for mode in notify_function
]
[t.start() for t in ts]
[t.join() for t in ts]
def main():
send("title", "content")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,483 @@
# Source: https://github.com/DearSong15/ql-scripts/blob/main/ks_query.py
# Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_query.py
# Repo: DearSong15/ql-scripts
# Path: ks_query.py
# UploadedAt: 2026-05-11T14:51:55Z
# SHA256: 848504df99018b6b2f9d7bac940671dc65777b8d973c1610e2a3111c88d36480
# Category: web版/抓包
# Evidence: web/H5关键词 + cookie/token/header
import json
import os
import requests
import time
from datetime import datetime, timedelta
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, PatternFill
def print_disclaimer():
"""打印免责声明"""
print("=" * 60)
print("【免责声明】")
print("1. 本程序仅为技术学习和个人账号信息查询使用,请勿用于商业用途或非法操作。")
print("2. 使用本程序需确保您对所查询的快手账号拥有合法所有权或使用权,严禁查询他人账号信息。")
print("3. 快手平台API可能随时变更导致程序无法正常运行开发者不保证程序的稳定性和可用性。")
print("4. 任何因使用本程序违反快手平台用户协议、法律法规或侵犯他人权益的行为,均由使用者自行承担全部责任。")
print("5. 开发者对使用本程序产生的任何直接或间接损失不承担任何法律责任。")
print("6. 本程序为临时查询工具建议您在使用完毕后24小时内删除程序及相关账号配置信息以保障账号安全。")
print("确认了解并同意以上条款后,程序将继续运行...")
print("快手极速版以及普通版本cookie有的账号是通用的普通版(kpn=KUAISHOU) 极速版(kpn=NEBULA)更改cookie的kpn即可")
print("\n请设置环境变量 ksck格式为:")
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
print("=" * 60 + "\n")
# 比率映射关系
RATIO_MAP = {
19: 0.00009,
28: 0.00008,
37: 0.00007,
46: 0.00006,
55: 0.00005,
64: 0.00004,
73: 0.00003,
82: 0.00002,
91: 0.00001
}
# 读取环境变量中的参数默认46
SELECTED_PARAM = int(os.getenv("RATIO_PARAM", 46))
class KuaishouClient:
def __init__(self, index, cookie, remark=""):
self.index = index
self.remark = remark
self.cookie = cookie
self.user_name = "未知用户"
# 余额信息
self.coin_balance = 0
self.cash_balance = 0
self.total_balance = 0
# 今日和昨日金币
self.today_coin = 0
self.yesterday_coin = 0
# 兑换后金额
self.today_coin_cash = 0
self.yesterday_coin_cash = 0
# 流水记录
self.coin_records = []
self.cash_records = []
# 基础配置
self.headers = {
'User-Agent': "Mozilla/5.0 (Linux; Android 16; PTP-AN00 Build/HONORPTP-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/139.0.7258.158 Mobile Safari/537.36 Yoda/3.2.17-rc2 Kwai/13.9.30.44872 OS_PRO_BIT/64 MAX_PHY_MEM/15272 KDT/PHONE AZPREFIX/az1 ICFO/0 StatusHT/38 TitleHT/44 NetType/NR ISLP/0 ISDM/0 ISLB/0 locale/zh-cn SHP/2665 SWP/1264 SD/3.5 CT/0 ISLM/0",
'Accept-Encoding': "gzip, deflate, br, zstd",
'sec-ch-ua-platform': "\"Android\"",
'sec-ch-ua': "\"Not;A=Brand\";v=\"99\", \"Android WebView\";v=\"139\", \"Chromium\";v=\"139\"",
'sec-ch-ua-mobile': "?1",
'X-Requested-With': "com.smile.gifmaker",
'Sec-Fetch-Site': "same-origin",
'Sec-Fetch-Mode': "cors",
'Sec-Fetch-Dest': "empty",
'Referer': "https://encourage.kuaishou.com/kwai/profit?tab=coin&layoutType=4",
'Accept-Language': "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
'Cookie': self.cookie
}
def send_request(self, url, method="get", params=None):
"""发送请求"""
try:
if method == "get":
response = requests.get(url, headers=self.headers, params=params, timeout=10)
else:
response = requests.post(url, headers=self.headers, data=params, timeout=10)
if response.status_code == 200:
return response.json()
else:
print(f"请求失败,状态码: {response.status_code}")
return None
except Exception as e:
print(f"请求异常: {e}")
return None
def query_withdraw_info(self):
"""查询提现信息(包含用户名和余额)"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/withdraw/info"
params = {
"source": "normal",
"imei": "",
"oaid": "279b0911-a941-4e80-b5fd-91f1c1ea2644",
"idfa": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
# 获取用户名
self.user_name = data.get("nickname", "未知用户")
# 获取账户信息
account = data.get("account", {})
self.coin_balance = account.get("coinAmount", 0)
self.cash_balance = account.get("cashAmount", 0) # 单位:分
self.total_balance = account.get("accumulativeAmount", 0) # 单位:分
return True
return False
def query_cash_records(self):
"""查询现金流水记录"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "6272350512f90404a43e5b3d3a3b5b3320a219ee1616ba201b5f2d2d2b2b28291636",
"sigCatVer": "1",
"accountType": "cash",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records[:3]:
self.cash_records.append({
'time': self._format_timestamp(record.get("createTime", 0)),
'title': record.get("title", ""),
'amount': record.get("displayAmount", "0"),
'direction': record.get("direction", "")
})
return True
return False
def query_coin_records(self):
"""查询金币流水记录"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
"sigCatVer": "1",
"accountType": "coin",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records[:3]:
self.coin_records.append({
'time': self._format_timestamp(record.get("createTime", 0)),
'title': record.get("title", ""),
'amount': record.get("displayAmount", "0"),
'direction': record.get("direction", "")
})
return True
return False
def _format_timestamp(self, timestamp):
"""格式化时间戳"""
if timestamp:
try:
dt = datetime.fromtimestamp(timestamp / 1000)
return dt.strftime("%Y-%m-%d %H:%M")
except:
return "未知时间"
return "未知时间"
def calculate_coin_stats(self):
"""计算今日和昨日金币收入及兑换后金额"""
today = datetime.now().date()
yesterday = today - timedelta(days=1)
self.today_coin = 0
self.yesterday_coin = 0
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
"sigCatVer": "1",
"accountType": "coin",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records:
if record.get("direction") != "IN":
continue
amount = record.get("amount", 0)
create_time = record.get("createTime", 0)
if create_time:
record_date = datetime.fromtimestamp(create_time / 1000).date()
if record_date == today:
self.today_coin += amount
elif record_date == yesterday:
self.yesterday_coin += amount
# 计算兑换后金额
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006) # 默认46对应的比率
self.today_coin_cash = round(self.today_coin * ratio, 2)
self.yesterday_coin_cash = round(self.yesterday_coin * ratio, 2)
return True
def query_all_data(self):
"""查询所有数据"""
print(f"正在查询账号[{self.index}] {self.remark}...")
# 查询提现信息(包含用户名和余额)
if not self.query_withdraw_info():
print(f"账号[{self.index}] {self.remark} 提现信息查询失败")
return False
# 查询现金流水
if not self.query_cash_records():
print(f"账号[{self.index}] {self.remark} 现金流水查询失败")
# 查询金币流水
if not self.query_coin_records():
print(f"账号[{self.index}] {self.remark} 金币流水查询失败")
# 计算金币统计
self.calculate_coin_stats()
return True
def get_display_data(self):
"""获取显示数据"""
# 现金余额从分转换为元
cash_yuan = self.cash_balance / 100 if self.cash_balance else 0
total_yuan = self.total_balance / 100 if self.total_balance else 0
return {
"index": self.index,
"user_name": self.user_name,
"remark": self.remark,
"today_coin": self.today_coin,
"yesterday_coin": self.yesterday_coin,
"today_coin_cash": self.today_coin_cash,
"yesterday_coin_cash": self.yesterday_coin_cash,
"coin_balance": self.coin_balance,
"cash_balance": round(cash_yuan, 2),
"total_balance": round(total_yuan, 2),
"coin_records": self.coin_records,
"cash_records": self.cash_records,
"ratio_param": SELECTED_PARAM
}
def load_cookies_from_env():
"""从环境变量ksck加载cookie配置格式备注#cookie#salt#ip|端口|用户名|密码|到期日期"""
cookies = []
ksck_env = os.getenv('ksck')
if not ksck_env:
print("未找到环境变量 ksck")
return cookies
lines = ksck_env.strip().split('&')
for i, line in enumerate(lines):
line = line.strip()
if not line:
continue
parts = line.split('#')
if len(parts) < 3:
print(f"{i + 1}行格式错误,跳过: {line}")
continue
remark = parts[0].strip()
cookie = parts[1].strip()
salt = parts[2].strip() # 暂时不使用
if not cookie:
print(f"{i + 1}行cookie为空跳过")
continue
# 不再检查socName直接添加
cookies.append({
"cookie": cookie,
"remark": remark
})
print(f"从环境变量 ksck 加载了 {len(cookies)} 个账号")
return cookies
def create_excel_summary(data_list, filename="快手金币数据汇总.xlsx"):
"""创建Excel汇总表格"""
wb = Workbook()
ws = wb.active
ws.title = "金币数据汇总"
# 设置表头
headers = ["序号", "用户名", "备注", "今日金币", "昨日金币", "当前金币",
f"今日{SELECTED_PARAM}后(元)", f"昨日{SELECTED_PARAM}后(元)", "当前现金(元)", "累计收益(元)",
"最近金币流水", "最近现金流水"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal="center")
cell.fill = PatternFill(start_color="E6F3FF", end_color="E6F3FF", fill_type="solid")
# 填充数据
for row, data in enumerate(data_list, 2):
ws.cell(row=row, column=1, value=data["index"]).alignment = Alignment(horizontal="center")
ws.cell(row=row, column=2, value=data["user_name"])
ws.cell(row=row, column=3, value=data["remark"])
ws.cell(row=row, column=4, value=data["today_coin"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=5, value=data["yesterday_coin"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=6, value=data["coin_balance"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=7, value=data["today_coin_cash"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=8, value=data["yesterday_coin_cash"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=9, value=data["cash_balance"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=10, value=data["total_balance"]).alignment = Alignment(horizontal="right")
# 格式化流水记录
coin_flow = "\n".join([f"{r['time']} {r['title']} +{r['amount']}" for r in data["coin_records"]])
cash_flow = "\n".join([f"{r['time']} {r['title']} {r['amount']}" for r in data["cash_records"]])
ws.cell(row=row, column=11, value=coin_flow)
ws.cell(row=row, column=12, value=cash_flow)
# 设置列宽
column_widths = {
'A': 8, # 序号
'B': 20, # 用户名
'C': 20, # 备注
'D': 12, # 今日金币
'E': 12, # 昨日金币
'F': 12, # 当前金币
'G': 18, # 今日兑换后
'H': 18, # 昨日兑换后
'I': 15, # 当前现金
'J': 15, # 累计收益
'K': 30, # 最近金币流水
'L': 30 # 最近现金流水
}
for col, width in column_widths.items():
ws.column_dimensions[col].width = width
# 设置行高
for row in range(2, len(data_list) + 2):
ws.row_dimensions[row].height = 60
# 保存文件
wb.save(filename)
print(f"\nExcel表格已生成: {filename}")
# 打印汇总统计
total_today = sum(data["today_coin"] for data in data_list)
total_yesterday = sum(data["yesterday_coin"] for data in data_list)
total_today_cash = sum(data["today_coin_cash"] for data in data_list)
total_yesterday_cash = sum(data["yesterday_coin_cash"] for data in data_list)
total_coins = sum(data["coin_balance"] for data in data_list)
total_cash = sum(data["cash_balance"] for data in data_list)
total_accumulative = sum(data["total_balance"] for data in data_list)
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006)
print(f"\n汇总统计 (使用比率参数 {SELECTED_PARAM}, 比率: {ratio}):")
print(f"今日金币总数: {total_today}")
print(f"今日金币兑换后: {total_today_cash}")
print(f"昨日金币总数: {total_yesterday}")
print(f"昨日金币兑换后: {total_yesterday_cash}")
print(f"当前金币总数: {total_coins}")
print(f"当前现金总数: {total_cash}")
print(f"累计收益总数: {total_accumulative}")
def main():
"""主函数"""
print_disclaimer()
print("开始查询快手账号数据...")
print("=" * 50)
print(f"当前使用比率参数: {SELECTED_PARAM}, 兑换比率: {RATIO_MAP.get(SELECTED_PARAM, 0.00006)}")
print("=" * 50)
# 从环境变量加载cookie配置
cookies_config = load_cookies_from_env()
if not cookies_config:
print("错误: 未找到有效的cookie配置")
print("\n请设置环境变量 ksck格式为:")
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
print("每行一个账号,用&分隔,例如:")
print("我的账号1#kuaishou.api_st=xxx; token=xxx#salt1#&我的账号2#kuaishou.api_st=yyy; token=yyy#salt2#")
return
all_data = []
success_count = 0
for i, account in enumerate(cookies_config):
if not account.get("cookie"):
print(f"账号[{i + 1}] cookie为空跳过")
continue
client = KuaishouClient(
index=i + 1,
cookie=account["cookie"],
remark=account["remark"]
)
if client.query_all_data():
data = client.get_display_data()
all_data.append(data)
success_count += 1
# 打印单个账号信息
print(f"\n账号[{i + 1}] 用户名: {data['user_name']} 备注: {account['remark']} 查询成功:")
print(f" 今日金币: {data['today_coin']}{data['today_coin_cash']}")
print(f" 昨日金币: {data['yesterday_coin']}{data['yesterday_coin_cash']}")
print(f" 当前金币: {data['coin_balance']}")
print(f" 当前现金: {data['cash_balance']}")
print(f" 累计收益: {data['total_balance']}")
if data['coin_records']:
print(" 最近金币流水:")
for record in data['coin_records']:
print(f" {record['time']} {record['title']} +{record['amount']}")
if data['cash_records']:
print(" 最近现金流水:")
for record in data['cash_records']:
print(f" {record['time']} {record['title']} {record['amount']}")
else:
print(f"\n账号[{i + 1}] {account['remark']} 查询失败")
# 添加0.5秒延迟,避免请求过于频繁
if i < len(cookies_config) - 1: # 最后一个账号不需要延迟
print("等待0.5秒后继续下一个账号...")
time.sleep(0.5)
# 生成Excel表格
if all_data:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"快手金币数据汇总_{SELECTED_PARAM}后_{timestamp}.xlsx"
create_excel_summary(all_data, filename)
print(f"\n成功查询 {success_count}/{len(cookies_config)} 个账号")
else:
print("没有成功查询到任何账号数据")
if __name__ == "__main__":
main()

File diff suppressed because one or more lines are too long