2026年1月16日星期五

化龙巷自动签到脚本使用指南

本脚本用于自动化登录化龙巷论坛并完成每日签到。用户需配置服务器及青龙面板,填入账户信息后运行。脚本采用多策略定位签到入口,登录失败或签到异常时会自动截图,便于排查验证码或路径问题。仅供学习测试。

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 timefrom datetime import datetimefrom pathlib import Path
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeoutError

BASE_URL = "http://bbs.hualongxiang.com"OUT_DIR = Path("hlx_artifacts")OUT_DIR.mkdir(exist_ok=True)

def env_bool(name: str, default: bool = True) -> bool:    val = os.getenv(name, str(default)).strip().lower()    return val not in ["0""false""off""no"]

def now_str() -> str:    return datetime.now().strftime("%Y%m%d_%H%M%S")

class HualongxiangSignBot:    def __init__(self, username: str, password: str, headless: bool = True, timeout_s: int = 30):        self.username = username        self.password = password        self.headless = headless        self.timeout_ms = timeout_s * 1000
        self.pw = None        self.browser = None        self.context = None        self.page = None
    # -------------------- 核心流程 --------------------    def run(self) -> None:        try:            self.start()            self.login()            ok, msg = self.sign_in()            self.log(f"[RESULT] ok={ok} msg={msg}")        except Exception as e:            self.log(f"[FATAL] {type(e).__name__}{e}")            self.screenshot("fatal")            raise        finally:            self.close()
    # -------------------- 浏览器管理 --------------------    def start(self) -> None:        self.pw = sync_playwright().start()        self.browser = self.pw.chromium.launch(headless=self.headless)        self.context = self.browser.new_context(            viewport={"width"1280"height"800},            user_agent=(                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "                "AppleWebKit/537.36 (KHTML, like Gecko) "                "Chrome/123.0.0.0 Safari/537.36"            ),            locale="zh-CN",        )        self.page = self.context.new_page()        self.page.set_default_timeout(self.timeout_ms)        self.log("[INIT] browser started")
    def close(self) -> None:        try:            if self.context:                self.context.close()            if self.browser:                self.browser.close()            if self.pw:                self.pw.stop()        except Exception:            pass
    # -------------------- 登录 --------------------    def login(self) -> None:        """        Discuz 常见登录入口:        - /member.php?mod=logging&action=login        - /member.php?mod=logging&action=login&infloat=yes&handlekey=login        """        login_urls = [            f"{BASE_URL}/member.php?mod=logging&action=login",            f"{BASE_URL}/member.php?mod=logging&action=login&infloat=yes&handlekey=login",        ]
        for url in login_urls:            self.log(f"[LOGIN] open: {url}")            self.page.goto(url, wait_until="domcontentloaded")
            # 如果已经登录,直接返回            if self.is_logged_in():                self.log("[LOGIN] already logged in")                return
            # 尝试填写表单(兼容不同 input name)            user_selectors = [                'input[name="username"]',                'input[name="email"]',                'input[name="account"]',                'input[name="loginfield"]',                'input[placeholder*="用户名"]',                'input[placeholder*="邮箱"]',                'input[placeholder*="手机"]',            ]            pass_selectors = [                'input[name="password"]',                'input[type="password"]',            ]
            user_el = self.first_visible(user_selectors)            pwd_el = self.first_visible(pass_selectors)
            if not user_el or not pwd_el:                self.log("[LOGIN] cannot find login inputs on this page, try next url")                continue
            user_el.fill(self.username)            pwd_el.fill(self.password)
            # 常见登录按钮            btn_selectors = [                'button[name="loginsubmit"]',                'button#loginsubmit',                'input[name="loginsubmit"]',                'button:has-text("登录")',                'input[type="submit"]',            ]            btn = self.first_visible(btn_selectors)            if not btn:                self.log("[LOGIN] cannot find submit button, try press Enter")                pwd_el.press("Enter")            else:                btn.click()
            # 等待跳转/刷新            self.page.wait_for_timeout(1500)
            if self.is_logged_in():                self.log("[LOGIN] success")                return
            # 若出现验证码/风控,截图提示            self.log("[LOGIN] not logged in yet; maybe captcha/extra step")            self.screenshot("login_failed_try")
        # 所有登录入口都失败        self.screenshot("login_failed")        raise RuntimeError("登录失败:未能完成登录(可能是验证码/风控/站点结构不同)")
    def is_logged_in(self) -> bool:        html = self.page.content()        # Discuz 登录后常见:退出/设置/提醒/用户名区域        keywords = ["退出""设置""提醒""我的""欢迎您""个人中心"]        hit = sum(1 for k in keywords if k in html)        # 同时排除明显的"登录/注册"强提示        if "登录" in html and "密码" in html and hit <= 1:            return False        return hit >= 2
    # -------------------- 签到 --------------------    def sign_in(self) -> tuple[boolstr]:        """        多策略签到:        1) 直接访问常见签到插件路径(dsu_paulsign / k_misign 等)        2) 在页面中寻找"签到/打卡/签 到"等按钮并点击        """        # 常见 Discuz 签到插件入口(不同站点可能不同)        sign_urls = [            f"{BASE_URL}/plugin.php?id=dsu_paulsign:sign",            f"{BASE_URL}/plugin.php?id=k_misign:sign",            f"{BASE_URL}/plugin.php?id=dsu_paulsign:sign&operation=qiandao",            f"{BASE_URL}/plugin.php?id=dsu_paulsign:sign&infloat=1",            f"{BASE_URL}/plugin.php?id=dsu_paulsign:sign&operation=signin",        ]
        for url in sign_urls:            try:                self.log(f"[SIGN] try url: {url}")                self.page.goto(url, wait_until="domcontentloaded")                self.page.wait_for_timeout(800)
                # 已签到特征词(不同插件不同)                html = self.page.content()                if any(x in html for x in ["已经签到""今日已签""已打卡""签到过了""您今天已经签到"]):                    self.screenshot("already_signed")                    return True"今日已签到"
                # 寻找"签到"按钮并点击(表单提交)                btn = self.first_visible([                    'button:has-text("签到")',                    'a:has-text("签到")',                    'input[value*="签到"]',                    'button:has-text("打卡")',                    'a:has-text("打卡")',                    'button:has-text("签 到")',                    'a:has-text("签 到")',                ])                if btn:                    btn.click()                    self.page.wait_for_timeout(1200)
                    html2 = self.page.content()                    if any(x in html2 for x in ["签到成功""已签到""获得""奖励""积分""经验"]):                        self.screenshot("sign_success")                        return True"签到成功(已命中插件页)"
                # 某些插件需要提交 formhash                # 兜底:如果页面里有 formhash,尝试提交包含 formhash 的表单                formhash = self.extract_formhash()                if formhash:                    self.log(f"[SIGN] found formhash={formhash}, try submit")                    self.try_submit_with_formhash(formhash)                    self.page.wait_for_timeout(1200)
                    html3 = self.page.content()                    if any(x in html3 for x in ["签到成功""已签到""获得""奖励""积分""经验"]):                        self.screenshot("sign_success_formhash")                        return True"签到成功(formhash 提交)"
            except PWTimeoutError:                self.log("[SIGN] timeout, try next")                continue            except Exception as e:                self.log(f"[SIGN] error: {e}, try next")                continue
        # 2) 从首页找入口(有些站点把"签到"挂在顶部导航)        self.log("[SIGN] fallback: scan from home page")        self.page.goto(BASE_URL, wait_until="domcontentloaded")        self.page.wait_for_timeout(800)
        nav_btn = self.first_visible([            'a:has-text("签到")',            'a:has-text("打卡")',            'a:has-text("每日签到")',            'a:has-text("签 到")',            'button:has-text("签到")',        ])        if nav_btn:            nav_btn.click()            self.page.wait_for_timeout(1200)            # 再找一次签到按钮            btn2 = self.first_visible([                'button:has-text("签到")',                'a:has-text("签到")',                'input[value*="签到"]',                'button:has-text("打卡")',                'a:has-text("打卡")',            ])            if btn2:                btn2.click()                self.page.wait_for_timeout(1200)                html4 = self.page.content()                if any(x in html4 for x in ["签到成功""已签到""获得""奖励""积分""经验"]):                    self.screenshot("sign_success_fallback")                    return True"签到成功(首页入口兜底)"
        self.screenshot("sign_failed")        return False"未找到有效签到入口(可能站点没有签到/插件路径不同/需要验证码)"
    def extract_formhash(self) -> str | None:        html = self.page.content()        m = re.search(r'name="formhash"\s+value="([^"]+)"', html)        if m:            return m.group(1)        return None
    def try_submit_with_formhash(self, formhash: str) -> None:        # 最粗暴兜底:页面内直接执行 JS 提交第一个表单        # 或者点击可能的提交按钮        btn = self.first_visible([            'button[type="submit"]',            'input[type="submit"]',            'button:has-text("提交")',            'button:has-text("确定")',            'a:has-text("签到")',        ])        if btn:            btn.click()            return
        # 再兜底:直接用 JS submit        self.page.evaluate(            """() => {                const forms = document.querySelectorAll('form');                if (forms && forms.length) { forms[0].submit(); }            }"""        )
    # -------------------- 工具方法 --------------------    def first_visible(self, selectors: list[str]):        for s in selectors:            try:                el = self.page.locator(s).first                if el.count() > 0 and el.is_visible():                    return el            except Exception:                continue        return None
    def screenshot(self, tag: str) -> None:        try:            path = OUT_DIR / f"{tag}_{now_str()}.png"            self.page.screenshot(path=str(path), full_page=True)            self.log(f"[SHOT] {path}")        except Exception:            pass
    def log(self, msg: str) -> None:        print(f"{datetime.now().strftime('%H:%M:%S')} {msg}")

def main():    username = os.getenv("HLX_USERNAME""").strip()    password = os.getenv("HLX_PASSWORD""").strip()
    if not username or not password:        print("❌ 缺少环境变量:HLX_USERNAME / HLX_PASSWORD")        sys.exit(1)
    headless = env_bool("HLX_HEADLESS"True)    timeout_s = int(os.getenv("HLX_TIMEOUT""30"))
    bot = HualongxiangSignBot(username, password, headless=headless, timeout_s=timeout_s)    bot.run()

if __name__ == "__main__":    main()
解析
该脚本为化龙巷论坛自动签到脚本,主要作用包括:
  • 自动化登录化龙巷论坛账号

  • 自动尝试多个常见论坛签到入口并完成签到

  • 如果站点签到入口不固定,则回到首页扫描"签到/打卡"入口再执行

  • 全程输出日志,并在关键失败点保存截图,便于你快速定位是"验证码/路径不对/按钮文案不同"

主要方法

  • run:脚本总入口,串起"启动浏览器 → 登录 → 签到 → 输出结果 → 关闭资源"全过程。

  • start:启动 Playwright 浏览器、创建上下文与页面,并设置超时时间与 UA。

  • close:释放浏览器资源,避免青龙/cron 跑多次后残留进程。

  • login:打开常见登录页,自动识别用户名/密码输入框并提交登录;失败时截图。

  • is_logged_in:通过页面关键字粗判断是否已登录(用于避免重复登录、判断登录成功与否)。

  • sign_in:签到主流程,按"插件路径直达 → 页面点击 → formhash 提交 → 首页入口兜底"多策略完成签到。

  • extract_formhash:从 HTML 中提取 Discuz 常见的 formhash(很多操作都需要它)。

  • try_submit_with_formhash:当页面存在 formhash 但找不到明显按钮时,尝试点击提交按钮或直接 JS 提交表单。

  • first_visible:在多个 selector 里找出第一个可见元素(增强兼容性)。

  • screenshot:保存全页截图到 hlx_artifacts/,用于排查验证码/按钮变更/跳转失败等问题。

  • log:统一输出带时间戳的日志信息。


注意

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


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

没有评论:

发表评论

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

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