2025年12月30日星期二

成都吃喝任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/55RK8C若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

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=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

# -*- coding: utf-8 -*-"""52ch.net 自动签到脚本(Discuz + dsu_paulsign)- 自动登录- 自动获取 formhash- 自动执行签到
使用方式(Linux/Mac):export CH52_USERNAME="你的用户名"export CH52_PASSWORD="你的密码"python3 sign_52ch.py
Windows PowerShell:setx CH52_USERNAME "你的用户名"setx CH52_PASSWORD "你的密码"python sign_52ch.py"""
import osimport reimport sysimport timeimport randomfrom dataclasses import dataclass
import requests

BASE = "https://www.52ch.net"LOGIN_PAGE = f"{BASE}/member.php?mod=logging&action=login&mobile=no"# Discuz 常见登录提交地址(会带 loginhash)LOGIN_SUBMIT_TEMPLATE = f"{BASE}/member.php?mod=logging&action=login&loginsubmit=yes&inajax=1&loginhash={{loginhash}}"# 签到页(你在网页里能打开的那个)SIGN_PAGE = f"{BASE}/dsu_paulsign-sign.html"# dsu_paulsign 常见签到提交接口(Discuz 默认插件风格)SIGN_SUBMIT = f"{BASE}/plugin.php?id=dsu_paulsign:sign&operation=qiandao&inajax=1"

@dataclassclass SignResult:    ok: bool    msg: str    raw: str = ""

class Discuz52chSigner:    def __init__(self, username: str, password: str, timeout: int = 20):        self.username = username        self.password = password        self.timeout = timeout        self.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/122.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",        })
    # -------------------- 工具方法 --------------------    def _get(self, url: str) -> str:        r = self.s.get(url, timeout=self.timeout, allow_redirects=True)        r.raise_for_status()        return r.text
    def _post(self, url: str, data: dict, headers: dict | None = None) -> str:        h = {}        if headers:            h.update(headers)        r = self.s.post(url, data=data, headers=h, timeout=self.timeout, allow_redirects=True)        r.raise_for_status()        return r.text
    @staticmethod    def _extract_formhash(html: str) -> str | None:        # Discuz 常见:name="formhash" value="xxxx"        m = re.search(r'name="formhash"\s+value="([^"]+)"', html)        return m.group(1if m else None
    @staticmethod    def _extract_loginhash(html: str) -> str | None:        # 登录 form action 里通常会带 loginhash=xxxx        m = re.search(r'loginhash=([A-Za-z0-9]+)', html)        return m.group(1if m else None
    @staticmethod    def _is_logged_in(html: str) -> bool:        # Discuz 登录后页面通常会出现 "退出/退出登录/我的/设置"等        return ("退出" in html) or ("logout" in html) or ('id="um"' in html) or ('id="loginstatus"' in html)
    # -------------------- 核心流程 --------------------    def login(self) -> SignResult:        html = self._get(LOGIN_PAGE)        formhash = self._extract_formhash(html)        loginhash = self._extract_loginhash(html)
        if not formhash or not loginhash:            return SignResult(False"登录页解析失败:未拿到 formhash/loginhash,可能页面结构变化或被风控。", html[:5000])
        submit_url = LOGIN_SUBMIT_TEMPLATE.format(loginhash=loginhash)
        payload = {            "formhash": formhash,            "referer": BASE + "/",            "loginfield""username",   # 常见字段:username / email / auto            "username"self.username,            "password"self.password,            "questionid""0",            "answer""",        }
        # Discuz 登录一般要求带这个头        headers = {            "Content-Type""application/x-www-form-urlencoded",            "Origin": BASE,            "Referer": LOGIN_PAGE,        }
        resp_text = self._post(submit_url, payload, headers=headers)
        # 登录返回通常是 JS/HTML,包含 "succeed" 或者 "欢迎您回来"        # 也可能返回错误:密码错误、需要验证码、账号异常等        if ("succeed" in resp_text) or ("欢迎您回来" in resp_text) or ("登录成功" in resp_text):            # 再访问首页确认 cookie 生效            home = self._get(BASE + "/")            if self._is_logged_in(home):                return SignResult(True"登录成功")            return SignResult(False"登录请求看似成功,但未检测到登录态(可能需要二次验证/风控)。", resp_text[:5000])
        # 常见失败提示        if ("验证码" in resp_text) or ("安全验证" in resp_text) or ("请先完成验证" in resp_text):            return SignResult(False"登录失败:站点触发验证码/安全验证,requests 方案无法直接处理。", resp_text[:5000])
        if ("密码错误" in resp_text) or ("登录失败" in resp_text) or ("用户名" in resp_text):            return SignResult(False"登录失败:账号或密码错误/账号异常(请检查输入)。", resp_text[:5000])
        return SignResult(False"登录失败:未知响应(建议把 raw 打印出来排查)。", resp_text[:5000])
    def get_sign_page_formhash(self) -> SignResult:        html = self._get(SIGN_PAGE)
        # 未登录会提示"您需要先登录才能继续本操作"        if ("需要先登录" in html) or ("登录才能继续" in html):            return SignResult(False"未登录:访问签到页被要求先登录。", html[:2000])
        formhash = self._extract_formhash(html)        if not formhash:            # dsu_paulsign 有时 formhash 在 JS 里            m = re.search(r"formhash=([a-zA-Z0-9]+)", html)            formhash = m.group(1if m else None
        if not formhash:            return SignResult(False"签到页解析失败:未拿到 formhash(可能插件页面结构变化)。", html[:5000])
        # 已签到常见提示(不同站点 wording 不一样)        if ("今日已签" in html) or ("已经签到" in html) or ("已签到" in html):            return SignResult(Truef"检测到页面提示:可能已签到(formhash={formhash})", formhash)
        return SignResult(True"获取签到页 formhash 成功", formhash)
    def do_sign(self, formhash: str, mood: str = "kx", say: str = "") -> SignResult:        """        dsu_paulsign 常见参数:        - formhash: 必填        - qdxq: 心情(如 kx=开心,ym=郁闷 等,站点可自定义)        - qdmode: 签到模式(一般 1)        - todaysay: 签到内容        - fastreply: 是否快速回复(一般 0)        """        payload = {            "formhash": formhash,            "qdxq": mood,            "qdmode""1",            "todaysay": say,            "fastreply""0",        }
        headers = {            "Content-Type""application/x-www-form-urlencoded",            "Origin": BASE,            "Referer": SIGN_PAGE,            "X-Requested-With""XMLHttpRequest",        }
        resp_text = self._post(SIGN_SUBMIT, payload, headers=headers)
        # dsu_paulsign 通常返回:恭喜你签到成功 / 今日已签到 / 权限不足 等        if ("签到成功" in resp_text) or ("恭喜" in resp_text):            return SignResult(True"签到成功", resp_text)        if ("已经签到" in resp_text) or ("今日已签到" in resp_text):            return SignResult(True"今日已签到", resp_text)        if ("权限" in resp_text) or ("禁止" in resp_text):            return SignResult(False"签到失败:可能没有权限/需要满足等级/绑定手机等。", resp_text)        if ("验证码" in resp_text) or ("安全验证" in resp_text):            return SignResult(False"签到失败:触发验证码/安全验证。", resp_text)
        return SignResult(False"签到失败:未知响应(可查看 raw)。", resp_text[:5000])
    def run(self) -> int:        # 1) 登录        r = self.login()        print(f"[LOGIN] {r.msg}")        if not r.ok:            return 1
        # 2) 访问签到页拿 formhash        r2 = self.get_sign_page_formhash()        print(f"[SIGN_PAGE] {r2.msg}")        if not r2.ok:            return 2
        # 3) 执行签到        formhash = r2.raw if r2.raw else ""        mood_pool = ["kx""ng""ym""wl""fd"]  # 心情参数站点可能不同,不行就固定用 kx        mood = random.choice(mood_pool)        say = "每日签到打卡~"
        time.sleep(random.uniform(1.02.0))        r3 = self.do_sign(formhash=formhash, mood=mood, say=say)        print(f"[SIGN] {r3.msg}")
        # 你需要的话可以把 r3.raw 输出到文件排查        # print(r3.raw)
        return 0 if r3.ok else 3

def main():    username = os.getenv("CH52_USERNAME""").strip()    password = os.getenv("CH52_PASSWORD""").strip()
    if not username or not password:        print("❌ 缺少环境变量:CH52_USERNAME / CH52_PASSWORD")        sys.exit(1)
    signer = Discuz52chSigner(username=username, password=password)    code = signer.run()    sys.exit(code)

if __name__ == "__main__":    main()
解析

该脚本为成都吃喝论坛自动签到脚本,主要作用包括:

  1. 建立会话(Session):用 requests.Session() 维持 Cookie,让"登录 → 访问签到页 → 提交签到"处于同一登录态。

  2. 登录 Discuz:从登录页解析出 formhashloginhash,再 POST 到登录提交接口。

  3. 进入签到插件页:访问 dsu_paulsign-sign.html,解析签到所需的 formhash

  4. 提交签到请求:向 plugin.php?id=dsu_paulsign:sign&operation=qiandao&inajax=1 发 POST,完成签到。

  5. 输出结果:成功/已签到/失败原因(验证码、权限、账号密码问题等)。

主要方法

login()

  • 作用:完成论坛登录。

  • 关键点

    • 先 GET 登录页,解析 formhash(防 CSRF)和 loginhash(Discuz 登录提交 URL 的动态参数)。

    • 再 POST 登录表单,拿到登录 Cookie。

    • 最后访问首页二次校验是否真的登录成功。

get_sign_page_formhash()

  • 作用:访问签到页并拿到签到用的 formhash

  • 为什么要单独拿dsu_paulsign 签到提交也需要 formhash,而且可能和登录页不一样,最稳妥是签到页再取一次。

  • 附带逻辑:如果页面出现"需要先登录",说明登录态丢失或登录没成功。

do_sign(formhash, mood, say)

  • 作用:真正执行签到动作。

  • 参数含义(常见 dsu_paulsign)

    • formhash:CSRF token(必填)

    • qdxq:签到心情(站点可能自定义,不行就固定 kx

    • qdmode:签到模式(多数站点为 1)

    • todaysay:签到留言

    • fastreply:快速回复开关(一般 0)

  • 返回处理:识别"签到成功 / 今日已签到 / 权限不足 / 验证码"等关键词。

run()

  • 作用:把整个流程串起来,按顺序执行:登录 → 取签到 formhash → 签到提交。

  • 附加:加入随机等待、随机心情,减少"像机器人"。



注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>

没有评论:

发表评论

自动化工具进阶:解决Cookie问题

点击上方蓝字关注我吧博主算是半个程序员,很喜欢研究一些技术方面的问题,最近不是在抽空学习返利网嘛,我也对返利网 点击上方 蓝字 关注我吧 博主算是半个程序员,很喜欢研究一些技术方面的问题,最近不是在抽空学习返利网嘛,我也对返利网的offer链接进行了研究。发现很多是只有登录后...