Summary: This script automates login and daily check-in for JingCity Forum using Discuz. It handles formhash extraction, session management, and error logging. Setup requires server deployment (Alibaba/Tencent/Huawei Cloud) and configuring credentials. Use for learning only.
阿里云:
服务器购买地址
https://t.aliyun.com/U/siC86h若失效,可用地址
https://www.aliyun.com/benefit?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.代码如下
import reimport timeimport randomimport requestsclass JingCitySigner:BASE = "https://www.jingcity.com/bbs"def __init__(self, username: str, password: str, tid: int = 80316, timeout: int = 20):self.username = usernameself.password = passwordself.tid = tid # 默认:新人签到帖 thread-80316self.timeout = timeoutself.s = requests.Session()self.s.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ""(KHTML, like Gecko) Chrome/120.0 Safari/537.36","Referer": f"{self.BASE}/",})# ---------- 基础工具 ----------def _get(self, url: str, **kwargs) -> requests.Response:return self.s.get(url, timeout=self.timeout, allow_redirects=True, **kwargs)def _post(self, url: str, data: dict, **kwargs) -> requests.Response:return self.s.post(url, data=data, timeout=self.timeout, allow_redirects=True, **kwargs)@staticmethoddef _pick(html: str, patterns: list[str], default: str = "") -> str:for p in patterns:m = re.search(p, html, re.I | re.S)if m:return m.group(1)return defaultdef _sleep_jitter(self, a=0.8, b=1.8):time.sleep(random.uniform(a, b))# ---------- 核心流程 ----------def login(self) -> bool:"""1) 打开登录页,提取 loginhash / formhash2) 提交账号密码登录3) 通过 cookie/页面关键字判断是否登录成功"""login_page = self._get(f"{self.BASE}/member.php?mod=logging&action=login")html = login_page.textloginhash = self._pick(html, [r'loginhash=([a-zA-Z0-9]+)',r'name="loginhash"\s+value="([^"]+)"'])formhash = self._pick(html, [r'name="formhash"\s+value="([^"]+)"',r'formhash=([a-zA-Z0-9]+)'])if not formhash:# 兜底:从首页提取idx = self._get(f"{self.BASE}/").textformhash = self._pick(idx, [r'name="formhash"\s+value="([^"]+)"', r'formhash=([a-zA-Z0-9]+)'])if not formhash:print("[login] 未能获取 formhash,可能页面结构/反爬有变。")return Falseself._sleep_jitter()post_url = f"{self.BASE}/member.php?mod=logging&action=login&loginsubmit=yes"if loginhash:post_url += f"&loginhash={loginhash}"payload = {"formhash": formhash,"referer": f"{self.BASE}/","username": self.username,"password": self.password,"questionid": "0","answer": "","cookietime": "2592000", # 30天}resp = self._post(post_url, data=payload)txt = resp.text# 登录成功常见标志:cookie 里出现 discuz_uid / auth;或页面里出现"欢迎您回来/退出"等ck = self.s.cookies.get_dict()if any(k.lower() in ("discuz_uid", "uid", "auth") for k in ck.keys()):print("[login] cookie 显示已登录。")return Trueif ("退出" in txt) or ("欢迎您回来" in txt) or ("您已登录" in txt):print("[login] 页面文本显示已登录。")return True# 常见失败原因:验证码/安全验证/密码错误if ("验证码" in txt) or ("安全验证" in txt) or ("security" in txt.lower()):print("[login] 可能触发验证码/安全验证,需改用浏览器自动化或手动登录后导入 cookie。")else:print("[login] 登录失败:可能账号密码错误或站点策略变更。")return Falsedef reply_checkin(self, message: str) -> bool:"""去指定 tid 的"回复页"抓 formhash/posttime,再提交回帖"""# 先打开帖子页(拿 formhash)thread_url = f"{self.BASE}/thread-{self.tid}-1-1.html"thread_html = self._get(thread_url).text# 从帖子页/回复页提取 formhashformhash = self._pick(thread_html, [r'name="formhash"\s+value="([^"]+)"', r'formhash=([a-zA-Z0-9]+)'])if not formhash:# 进一步打开"回复表单页"reply_page = self._get(f"{self.BASE}/forum.php?mod=post&action=reply&tid={self.tid}")reply_html = reply_page.textformhash = self._pick(reply_html, [r'name="formhash"\s+value="([^"]+)"', r'formhash=([a-zA-Z0-9]+)'])if not formhash:print("[reply] 未能获取 formhash,可能未登录或帖子不可回复。")return Falseself._sleep_jitter()# Discuz 回帖提交地址post_url = f"{self.BASE}/forum.php?mod=post&action=reply&tid={self.tid}&replysubmit=yes&inajax=1"payload = {"formhash": formhash,"message": message,"subject": "",}resp = self._post(post_url, data=payload)txt = resp.text# 成功/失败的模糊判断if ("回复发布成功" in txt) or ("post_newreply_succeed" in txt) or ("succeedhandle" in txt):print("[reply] 签到回帖成功。")return Trueif ("您需要先登录" in txt) or ("notlogin" in txt.lower()):print("[reply] 回帖失败:未登录或登录已失效。")return Falseif ("抱歉" in txt) or ("权限" in txt) or ("灌水" in txt) or ("发布间隔" in txt):print("[reply] 回帖被拒:可能无权限/发帖间隔限制/防灌水策略。返回内容片段:")print(txt[:200])return Falseprint("[reply] 回帖结果未知,返回内容片段:")print(txt[:200])return Falsedef run(self) -> None:"""入口:登录 -> 生成签到内容 -> 回帖"""if not self.login():return# 你也可以改成更固定/更随机的签到文本msg = f"签到打卡~{time.strftime('%Y-%m-%d %H:%M:%S')}"self.reply_checkin(msg)if __name__ == "__main__":# TODO:填你的账号密码USERNAME = "你的用户名"PASSWORD = "你的密码"# 默认签到帖:新人签到 thread-80316(可改成你常用的签到帖 tid)signer = JingCitySigner(USERNAME, PASSWORD, tid=80316)signer.run()
该脚本为京城论坛自动签到脚本,主要作用包括:
自动登录京城论坛:模拟浏览器访问登录页,拿到 Discuz 必需的
formhash等参数,然后提交账号密码完成登录。自动"签到":对指定的
tid(签到帖)自动发布一条回复,实现"每日打卡"。容错与提示:当出现"验证码/安全验证/权限不足/发帖间隔"等情况时,输出明确日志,方便你改策略(如改用 Selenium/Playwright 或导入 cookie)。
主要方法
login()负责获取
formhash/loginhash并提交登录请求;通过 cookie 或返回页面关键字判断是否登录成功;
若触发验证码/安全验证,会提示"需要浏览器自动化或 cookie 方案"。
reply_checkin(message)打开帖子/回复页提取回帖所需的
formhash;向 Discuz 的回帖提交接口发送表单数据(包含 message);
根据返回内容判断是否成功、是否被限流/无权限/未登录。
run()串联主流程:登录成功后生成签到文案并回帖;
你要做定时任务(cron/Windows 计划任务)时,只需要定时执行这个入口即可。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
没有评论:
发表评论