2026年1月16日星期五

标题**:麻辣社区自动化签到脚本指南

**摘要**:提供服务器购买、青龙面板部署及自动签到脚本。脚本通过Playwright登录并同步Cookie,支持Discuz常见签到入口,输出结构化结果。需配置环境变量运行。

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 -*-
import osimport reimport sysimport timeimport jsonimport tracebackfrom urllib.parse import urljoin, urlparse
import requestsfrom bs4 import BeautifulSoupfrom playwright.sync_api import sync_playwright

BASE_URL = "https://www.mala.cn/"UA = (    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "    "(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")

class MalaSignBot:    def __init__(self, username: str, password: str, headless: bool = True):        self.username = username        self.password = password        self.headless = headless
        self.session = requests.Session()        self.session.headers.update({"User-Agent": UA})
    # =========================    # 1) Playwright 登录拿 cookie    # =========================    def login_and_export_cookies(self) -> None:        """        用浏览器登录后,把 cookie 同步到 requests.Session        """        with sync_playwright() as p:            browser = p.chromium.launch(headless=self.headless)            context = browser.new_context(user_agent=UA)            page = context.new_page()
            page.goto(BASE_URL, wait_until="domcontentloaded", timeout=60_000)
            # 尝试找 Discuz 登录入口(常见:member.php?mod=logging...)            login_url = self._discover_login_url(page.url, page.content())            if not login_url:                # 兜底:直接拼常见登录入口                login_url = urljoin(BASE_URL, "member.php?mod=logging&action=login")            page.goto(login_url, wait_until="domcontentloaded", timeout=60_000)
            # 常见 Discuz 登录表单字段            # username: name="username" 或 "loginfield" + "username"            # password: name="password"            # 如果站点改了字段名,你就需要在这里按页面结构改一下 selector            try:                # 有些站点输入框可能不是标准 name,这里做一组兜底                user_sel_candidates = [                    'input[name="username"]',                    'input[id*="username"]',                    'input[placeholder*="用户名"]',                    'input[placeholder*="账号"]',                    'input[type="text"]',                ]                pass_sel_candidates = [                    'input[name="password"]',                    'input[id*="password"]',                    'input[placeholder*="密码"]',                    'input[type="password"]',                ]
                user_box = None                for sel in user_sel_candidates:                    loc = page.locator(sel)                    if loc.count() > 0:                        user_box = loc.first                        break                if not user_box:                    raise RuntimeError("未找到用户名输入框(请打开非 headless 模式观察页面后调整 selector)")
                pass_box = None                for sel in pass_sel_candidates:                    loc = page.locator(sel)                    if loc.count() > 0:                        pass_box = loc.first                        break                if not pass_box:                    raise RuntimeError("未找到密码输入框(请打开非 headless 模式观察页面后调整 selector)")
                user_box.fill(self.username)                pass_box.fill(self.password)
                # 提交按钮:常见 class/id/name 关键字 submit/login                submit_candidates = [                    'button[type="submit"]',                    'input[type="submit"]',                    'button:has-text("登录")',                    'input[value*="登录"]',                ]                clicked = False                for sel in submit_candidates:                    loc = page.locator(sel)                    if loc.count() > 0:                        loc.first.click()                        clicked = True                        break                if not clicked:                    # 兜底:按回车提交                    pass_box.press("Enter")
                # 等待跳转/登录态出现(比如"退出/设置/消息/个人中心"等)                page.wait_for_timeout(3000)
            except Exception as e:                browser.close()                raise RuntimeError(f"登录步骤失败:{e}")
            # 取 cookie 同步到 requests            cookies = context.cookies()            browser.close()
        # 把 playwright cookies 写入 requests session        for ck in cookies:            domain = ck.get("domain""")            name = ck.get("name")            value = ck.get("value")            if not name:                continue            # requests 的 cookie domain 写法略不同,这里尽量兼容            self.session.cookies.set(name, value, domain=domain.lstrip("."), path=ck.get("path""/"))
    def _discover_login_url(self, current_url: str, html_text: str) -> str | None:        """        从首页/当前页面源码里,尝试找登录入口链接        """        soup = BeautifulSoup(html_text, "lxml")        for a in soup.select("a[href]"):            href = a.get("href""")            if "member.php" in href and "mod=logging" in href and "action=login" in href:                return urljoin(current_url, href)        return None
    # =========================    # 2) 探测 formhash    # =========================    def get_formhash(self) -> str | None:        """        Discuz 常用的 CSRF 字段:formhash        """        resp = self.session.get(BASE_URL, timeout=30)        resp.raise_for_status()        m = re.search(r'name="formhash"\s+value="([^"]+)"', resp.text)        if m:            return m.group(1)
        # 兜底:从 JS 变量里找        m2 = re.search(r'formhash\s*=\s*"([^"]+)"', resp.text)        if m2:            return m2.group(1)        return None
    # =========================    # 3) 执行签到(多路径候选 + 自动提交)    # =========================    def try_signin(self) -> dict:        """        尝试多种 Discuz/插件签到入口:        - plugin.php?id=dsu_paulsign:sign        - plugin.php?id=dsu_paulsign        - 其他常见签到插件入口(需要你根据实际页面补充)        """        formhash = self.get_formhash()
        # 候选签到入口(你可以把日志里探测到的真实入口补进来)        candidates = [            # 最常见:dsu_paulsign            "plugin.php?id=dsu_paulsign:sign",            "plugin.php?id=dsu_paulsign",
            # 其他可能的签到入口(不同站点会有差异)            "plugin.php?id=dc_signin",            "plugin.php?id=dd_sign",            "k_misign-sign.html",            "home.php?mod=spacecp&ac=credit&op=base",        ]
        # 1) 先 GET 入口页,看看是否存在签到表单(formhash/按钮/提示)        for path in candidates:            url = urljoin(BASE_URL, path)            try:                r = self.session.get(url, timeout=30)                if r.status_code >= 400:                    continue
                # 如果页面里出现"请先登录",说明登录没成功                if "登录" in r.text and ("请先登录" in r.text or "您需要先登录" in r.text):                    return {"ok"False"stage""signin""message""登录态无效:访问签到页提示未登录""url": url}
                # 如果是 dsu_paulsign,通常有 formhash 和提交 action                if "dsu_paulsign" in r.text or "paulsign" in r.text or "签到" in r.text:                    # 2) 尝试从签到页抽 form action / formhash                    action_url = self._extract_form_action(url, r.text) or url                    fh = self._extract_formhash_from_html(r.text) or formhash
                    # 如果仍拿不到 formhash,基本无法提交                    if not fh:                        continue
                    # 3) 组装常见签到 payload(dsu_paulsign 常用字段)                    payload = {                        "formhash": fh,                        "qdxq""kx",          # 心情:kx/ym/wl/ng/fd(不同站点可不同,但一般不严格校验)                        "qdmode""1",        # 签到模式                        "todaysay""每日签到"# 签到说说                        "fastreply""0",                        "submit""true",                    }
                    # 4) POST 提交                    pr = self.session.post(action_url, data=payload, timeout=30)
                    # 5) 解析结果:常见返回关键字                    text = pr.text                    if any(k in text for k in ["签到成功""恭喜""已签到""已经签到""success"]):                        return {"ok"True"stage""signin""message""签到成功/已签到""url": action_url}
                    # 有些站点会跳转到提示页:再看 Location                    if pr.status_code in (301302303307308):                        return {"ok"True"stage""signin""message""签到请求已提交(发生跳转)""url": action_url}
                    # 如果失败,把部分信息带回(方便你定位实际字段/入口)                    return {                        "ok"False,                        "stage""signin",                        "message""签到提交可能失败(未命中成功关键字),建议开启 headless=false 观察实际签到入口与字段",                        "url": action_url,                        "debug_snippet": text[:500],                    }
            except Exception:                continue
        return {            "ok"False,            "stage""discover",            "message""未在候选路径中找到可用签到入口。建议:先手动登录并签到一次,然后把签到页面 URL 发我,我帮你把入口/字段定死。",        }
    def _extract_form_action(self, page_url: str, html_text: str) -> str | None:        """        从 HTML 表单中提取 action(用于 POST)        """        soup = BeautifulSoup(html_text, "lxml")        form = soup.select_one("form[action]")        if not form:            return None        action = form.get("action""").strip()        if not action:            return None        return urljoin(page_url, action)
    def _extract_formhash_from_html(self, html_text: str) -> str | None:        m = re.search(r'name="formhash"\s+value="([^"]+)"', html_text)        return m.group(1if m else None

def main():    username = os.getenv("MALA_USERNAME""").strip()    password = os.getenv("MALA_PASSWORD""").strip()    headless_env = os.getenv("MALA_HEADLESS""true").strip().lower()    headless = headless_env not in ("false""0""off""no")
    if not username or not password:        print("❌ 缺少账号密码环境变量:MALA_USERNAME / MALA_PASSWORD")        sys.exit(1)
    bot = MalaSignBot(username=username, password=password, headless=headless)
    try:        print("1) 开始登录并同步 Cookie ...")        bot.login_and_export_cookies()        print("✅ 登录成功,Cookie 已同步")
        print("2) 开始尝试签到 ...")        result = bot.try_signin()        print("=== 签到结果 ===")        print(json.dumps(result, ensure_ascii=False, indent=2))
        sys.exit(0 if result.get("ok"else 2)
    except Exception as e:        print("❌ 脚本执行异常:"str(e))        print(traceback.format_exc())        sys.exit(3)

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

该脚本为麻辣社区自动签到脚本,主要功能包括:

  • 自动打开 mala.cn,完成账号登录

  • 登录成功后把浏览器 Cookie 同步到 requests 会话

  • 自动探测 Discuz 常见 formhash(CSRF token)

  • 依次尝试多个常见签到入口(如 dsu_paulsign 插件入口),并自动提交签到表单

  • 输出结构化结果(成功/失败原因、使用的 URL、失败时截断的响应片段)

主要方法

  • login_and_export_cookies → 使用 Playwright 完成网页登录,并将登录后的 Cookie 同步到 requests.Session,为后续 HTTP 方式签到做准备。

  • _discover_login_url → 从首页 HTML 中尝试自动发现登录入口(常见 member.php?mod=logging&action=login)。

  • get_formhash → 获取 Discuz 常见 CSRF 参数 formhash(从首页或脚本变量中提取)。

  • try_signin → 核心签到流程:遍历候选签到入口,GET 判断是否为签到页,抽取表单 action/formhash,POST 提交签到并判定结果。

  • _extract_form_action → 从签到页 HTML 中提取 <form action="..."> 作为 POST 提交地址。

  • _extract_formhash_from_html → 从签到页 HTML 中提取隐藏字段 formhash

  • main → 读取环境变量、初始化机器人、执行登录与签到、输出结果并设置退出码。


注意

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


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

没有评论:

发表评论

标题**:技术宅零成本营销:50个免费工具月入9万

**内容概括**:一位厌恶传统营销的印度程序员,通过开发近50个AI免费工具(如PDF转换器、聊天机器人),吸引月5万自然搜索流量,零成本将用户转化为付费客户,实现SaaS产品月入9万元。其核心策略是以代码自动化获客,用"免费工具引流+精准转化路径"替代广告投...