1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/55RK8C若失效,可用地址
阿里云:
服务器购买地址
https://t.aliyun.com/U/55RK8C若失效,可用地址
https://www.aliyun.com/daily-act/ecs/activity_selection?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=2019052.部署教程
3.代码如下
#!/usr/bin/env python3# -*- coding: utf-8 -*-import osimport reimport timeimport randomimport requestsfrom dataclasses import dataclassfrom typing import Optional, TupleSIGN_PAGE = "https://bbs.360.cn/dsu_paulsign-sign.html"SIGN_API = "https://bbs.360.cn/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=1&inajax=1"class CheckinResult:ok: boolstatus: strdetail: strclass BBS360Checkin:"""360社区签到客户端:- 负责:加载签到页 -> 提取 formhash -> 提交签到"""def __init__(self, cookie: str, timeout: int = 20):self.cookie = cookie.strip()self.timeout = timeoutself.session = requests.Session()self.session.headers.update({"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0 Safari/537.36"),"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language": "zh-CN,zh;q=0.9","Connection": "keep-alive","Cookie": self.cookie,"Referer": "https://bbs.360.cn/",})# ---------- 主要方法 1:拉取签到页并提取 formhash ----------def fetch_formhash(self) -> Tuple[Optional[str], str]:"""访问签到页,提取 Discuz 用于防 CSRF 的 formhash。返回:(formhash, raw_html_snippet)"""resp = self.session.get(SIGN_PAGE, timeout=self.timeout, allow_redirects=True)text = resp.text or ""# 未登录/未绑定手机号时页面会提示 "您需要先登录才能继续本操作"if "您需要先登录才能继续本操作" in text or "请使用手机微信扫码安全登录" in text:return None, "未登录或账号未满足发帖/互动条件(可能需要绑定手机号)"# Discuz 常见 formhash 形态:formhash=xxxxxxxx 或 name="formhash" value="xxxx"m = re.search(r'formhash=([0-9a-zA-Z]{6,})', text)if not m:m = re.search(r'name="formhash"\s+value="([0-9a-zA-Z]{6,})"', text)if not m:return None, "已登录但未解析到 formhash(页面结构可能变更)"return m.group(1), "OK"# ---------- 主要方法 2:提交签到 ----------def submit_checkin(self, formhash: str) -> CheckinResult:"""提交签到请求(dsu_paulsign)典型字段:- formhash: 必须- qdxq: 心情(插件常见:kx/ym/tp/ng/wl 等,不同站点可能不同)- qdmode: 签到模式(一般 1)- todaysay: 签到内容- fastreply: 是否快速回复(一般 0)"""moods = ["kx", "ym", "tp", "ng", "wl"] # 常见心情值,若站点自定义也通常能兼容payload = {"formhash": formhash,"qdxq": random.choice(moods),"qdmode": "1","todaysay": random.choice(["打卡签到,愿一切顺利!","新的一天,继续加油~","保持热爱,奔赴山海。","今日签到,万事胜意。","坚持自律,慢慢变强。",]),"fastreply": "0",}# dsu_paulsign 的 inajax 提交,通常返回一段包含中文提示的文本/脚本片段resp = self.session.post(SIGN_API, data=payload, timeout=self.timeout)raw = resp.text or ""# 站点常见返回关键字(不同 Discuz 皮肤/插件版本会略不同)if ("签到成功" in raw) or ("恭喜" in raw and "签到" in raw):return CheckinResult(True, "success", self._extract_message(raw) or "签到成功")if ("已经签到" in raw) or ("已签到" in raw) or ("请勿重复签到" in raw):return CheckinResult(True, "already", self._extract_message(raw) or "今日已签到")if ("formhash" in raw and "错误" in raw) or ("请求无效" in raw):return CheckinResult(False, "bad_formhash", self._extract_message(raw) or "formhash无效/过期")if resp.status_code != 200:return CheckinResult(False, "http_error", f"HTTP {resp.status_code}")return CheckinResult(False, "unknown", self._extract_message(raw) or raw[:200])# ---------- 工具:从返回内容里尽量提取提示语 ----------@staticmethoddef _extract_message(text: str) -> str:# 1) 常见 Discuz AJAX:showmessage('xxx')m = re.search(r"showmessage\('([^']+)'\)", text)if m:return m.group(1)# 2) 退而求其次:抓取"签到"附近的中文片段m = re.search(r"([^\n\r]{0,20}(签到|已签到|重复签到)[^\n\r]{0,40})", text)if m:return m.group(1)return ""# ---------- 运行入口 ----------def run(self) -> CheckinResult:formhash, info = self.fetch_formhash()if not formhash:return CheckinResult(False, "no_login_or_parse_failed", info)# 避免太快(有些站点对频率敏感)time.sleep(random.uniform(1.0, 2.5))return self.submit_checkin(formhash)def main():cookie = os.getenv("BBS360_COOKIE", "").strip()if not cookie:print("❌ 未设置环境变量 BBS360_COOKIE")print("💡 先浏览器登录 bbs.360.cn,然后复制 Cookie 到环境变量:")print(" export BBS360_COOKIE='粘贴Cookie整段'")returnclient = BBS360Checkin(cookie=cookie, timeout=20)result = client.run()if result.ok:print(f"✅ 签到完成:{result.status} | {result.detail}")else:print(f"❌ 签到失败:{result.status} | {result.detail}")if __name__ == "__main__":main()
解析
该脚本为自动完成 360 社区每日签到脚本。整体流程是:
访问签到页
dsu_paulsign-sign.html,从页面里解析出formhash(Discuz 的防 CSRF 参数)。 360社区调用签到接口(
dsu_paulsign插件的签到提交接口),带上formhash + 心情 + 签到内容提交签到。 360社区解析返回内容,判断是"签到成功 / 今日已签到 / Cookie失效或异常"。
主要方法
① fetch_formhash()
作用:打开签到页面并提取
formhash。为什么必须要它:Discuz 的很多操作(签到/发帖/回帖)都会要求
formhash,否则会被判定为"请求无效/非法请求"。失败常见原因:
Cookie 没带上或已失效 → 页面提示"需要先登录"
账号未绑定手机号/无互动权限 → 仍可能提示无法继续
页面结构变动 → 正则没匹配到
formhash
② submit_checkin(formhash)
作用:向签到接口发起 POST 请求,提交签到数据(心情
qdxq、内容todaysay等)。内部做了什么:
随机一个心情值(降低行为特征一致性)
组装 payload 并提交
根据返回内容关键字判断:成功/已签到/异常
③ _extract_message(text)
作用:从接口返回的文本里尽可能提取"人能看懂的提示语"(比如"签到成功""今日已签到"等)。
意义:不同站点/皮肤返回结构不一样,直接打印原文很难读,这个方法用于提炼关键信息。
④ run()
作用:把"获取 formhash → 提交签到"串起来,作为对外的单一入口。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
没有评论:
发表评论