2026年1月17日星期六

红豆社区自动签到脚本使用指南

此脚本实现红豆社区自动签到,支持登录态复用、失败重试及截图日志。需配置服务器环境与账号信息,仅限学习研究。

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/kcPAeY

若失效,可用地址

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 timeimport pathlibimport tracebackfrom dataclasses import dataclassfrom typing import Optional
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeoutError

# ----------------------------# 可配置项# ----------------------------BASE_URL = "https://hongdou.gxnews.com.cn/"SIGNIN_URL_CANDIDATES = [    # 在F12里找到真实签到入口后替换/新增    "https://hongdou.gxnews.com.cn/",    # "https://hongdou.gxnews.com.cn/plugin.php?id=dsu_paulsign:sign",  # 常见论坛签到插件形式(示例)    # "https://hongdou.gxnews.com.cn/home.php?mod=task",               # 任务中心(示例)]
# 把"可能的入口"与"关键按钮/输入框"选择器集中在这里,后续只改这里即可SELECTORS = {    # --- 登录入口(示例,需要你按实际页面改) ---    "login_entry": "text=登录",  # 首页"登录"按钮/链接    "username_input": "input[name='username']",  # 用户名输入框    "password_input": "input[name='password']",  # 密码输入框    "submit_login": "button[type='submit'], input[type='submit']",  # 登录提交按钮
    # --- 登录态判断(示例,需要你按实际页面改) ---    "user_avatar_or_profile": "a:has-text('退出'), a:has-text('我的'), img.avatar",  # 登录后可见的元素之一
    # --- 签到入口/按钮(示例,需要你按实际页面改) ---    "signin_entry": "text=签到",           # 页面上的"签到"入口    "signin_button": "text=立即签到",      # 真正的"立即签到"按钮    "already_signed_hint": "text=已签到",  # 已签到提示}
DEFAULT_TIMEOUT_MS = 20_000RETRY_TIMES = 3

@dataclassclass RunConfig:    username: str    password: str    headless: bool = True    data_dir: str = "./user_data"    screenshot_dir: str = "./screenshots"

class HongDouSignInBot:    def __init__(self, cfg: RunConfig):        self.cfg = cfg        self.screenshot_path = pathlib.Path(cfg.screenshot_dir)        self.screenshot_path.mkdir(parents=True, exist_ok=True)
        self.data_dir = pathlib.Path(cfg.data_dir)        self.data_dir.mkdir(parents=True, exist_ok=True)
    # ----------------------------    # 工具方法    # ----------------------------    def _log(self, msg: str):        now = time.strftime("%Y-%m-%d %H:%M:%S")        print(f"[{now}] {msg}")
    def _shot(self, page, name: str):        ts = time.strftime("%Y%m%d_%H%M%S")        p = self.screenshot_path / f"{ts}_{name}.png"        try:            page.screenshot(path=str(p), full_page=True)            self._log(f"📸 截图保存: {p}")        except Exception as e:            self._log(f"⚠️ 截图失败: {e}")
    def _goto(self, page, url: str):        self._log(f"🌐 打开页面: {url}")        page.goto(url, wait_until="domcontentloaded", timeout=DEFAULT_TIMEOUT_MS)
    def _click_if_exists(self, page, selector: str, desc: str, timeout_ms: int = 3000) -> bool:        try:            el = page.locator(selector).first            el.wait_for(state="visible", timeout=timeout_ms)            el.click(timeout=timeout_ms)            self._log(f"✅ 点击: {desc}")            return True        except PWTimeoutError:            return False        except Exception as e:            self._log(f"⚠️ 点击失败({desc}): {e}")            return False
    def _fill_if_exists(self, page, selector: str, value: str, desc: str, timeout_ms: int = 3000) -> bool:        try:            el = page.locator(selector).first            el.wait_for(state="visible", timeout=timeout_ms)            el.fill(value, timeout=timeout_ms)            self._log(f"✅ 填写: {desc}")            return True        except PWTimeoutError:            return False        except Exception as e:            self._log(f"⚠️ 填写失败({desc}): {e}")            return False
    # ----------------------------    # 核心流程方法    # ----------------------------    def ensure_logged_in(self, page) -> bool:        """        尝试复用登录态;如果未登录则执行账号密码登录        """        self._log("🔐 检查登录状态...")
        # 若页面已出现"退出/头像/个人中心"等,视为已登录        if page.locator(SELECTORS["user_avatar_or_profile"]).count() > 0:            self._log("✅ 已检测到登录态(无需重复登录)")            return True
        self._log("ℹ️ 未检测到登录态,开始登录流程...")
        # 点击登录入口        clicked = self._click_if_exists(page, SELECTORS["login_entry"], "登录入口")        if not clicked:            self._log("⚠️ 未找到登录入口按钮/链接,请更新 SELECTORS['login_entry']")            return False
        # 填写账号密码        if not self._fill_if_exists(page, SELECTORS["username_input"], self.cfg.username, "用户名/账号"):            self._log("⚠️ 未找到用户名输入框,请更新 SELECTORS['username_input']")            return False
        if not self._fill_if_exists(page, SELECTORS["password_input"], self.cfg.password, "密码"):            self._log("⚠️ 未找到密码输入框,请更新 SELECTORS['password_input']")            return False
        # 点击提交        if not self._click_if_exists(page, SELECTORS["submit_login"], "登录提交"):            self._log("⚠️ 未找到登录提交按钮,请更新 SELECTORS['submit_login']")            return False
        # 等待登录完成        try:            page.wait_for_timeout(1500)            page.wait_for_load_state("domcontentloaded", timeout=DEFAULT_TIMEOUT_MS)        except Exception:            pass
        if page.locator(SELECTORS["user_avatar_or_profile"]).count() > 0:            self._log("✅ 登录成功")            return True
        self._log("❌ 登录可能失败:未检测到登录后标志元素。可能原因:验证码/选择器不匹配/账号密码错误")        self._shot(page, "login_failed")        return False
    def open_signin_page(self, page) -> bool:        """        打开签到入口:先尝试从首页点击"签到",不行再尝试候选URL        """        self._log("🧭 尝试进入签到页面...")
        # 先尝试在当前页点击"签到"入口        if self._click_if_exists(page, SELECTORS["signin_entry"], "签到入口", timeout_ms=4000):            try:                page.wait_for_load_state("domcontentloaded", timeout=DEFAULT_TIMEOUT_MS)            except Exception:                pass            return True
        # 再尝试候选URL        for url in SIGNIN_URL_CANDIDATES:            try:                self._goto(page, url)                # 如果页面里能找到"签到按钮/已签到提示",就认为进入了签到相关页面                if (                    page.locator(SELECTORS["signin_button"]).count() > 0                    or page.locator(SELECTORS["already_signed_hint"]).count() > 0                    or page.locator(SELECTORS["signin_entry"]).count() > 0                ):                    self._log(f"✅ 命中签到相关页面: {url}")                    return True            except Exception as e:                self._log(f"⚠️ 打开候选签到URL失败: {url} err={e}")
        self._log("❌ 未能进入签到页面:请确认真实签到入口URL或更新 SELECTORS['signin_entry']")        self._shot(page, "signin_entry_not_found")        return False
    def do_signin(self, page) -> str:        """        执行签到:识别"已签到" -> 直接返回;否则点击"立即签到"        """        self._log("🧾 开始执行签到...")
        # 已签到判断        if page.locator(SELECTORS["already_signed_hint"]).count() > 0:            self._log("✅ 检测到已签到提示:今日无需重复签到")            self._shot(page, "already_signed")            return "今日已签到"
        # 点击签到按钮        if self._click_if_exists(page, SELECTORS["signin_button"], "立即签到", timeout_ms=6000):            page.wait_for_timeout(1500)
            # 再次确认是否出现已签到提示            if page.locator(SELECTORS["already_signed_hint"]).count() > 0:                self._log("🎉 签到成功(出现已签到提示)")                self._shot(page, "signed_success")                return "签到成功"
            # 即使没匹配到提示,也截个图给你排查            self._shot(page, "signed_clicked")            self._log("✅ 已点击签到按钮,但未识别到明确结果提示(可能提示文案/选择器不同)")            return "已点击签到按钮(结果待确认)"
        self._log("❌ 未找到签到按钮:请更新 SELECTORS['signin_button']")        self._shot(page, "signin_button_not_found")        return "签到失败:未找到签到按钮"
    def run(self) -> str:        """        总入口:启动浏览器 -> 打开首页 -> 确保登录 -> 进入签到页 -> 签到 -> 返回结果        """        for attempt in range(1, RETRY_TIMES + 1):            self._log(f"🚀 运行开始:第 {attempt}/{RETRY_TIMES} 次尝试")            try:                with sync_playwright() as p:                    context = p.chromium.launch_persistent_context(                        user_data_dir=str(self.data_dir),                        headless=self.cfg.headless,                        viewport={"width": 1280, "height": 800},                        args=["--disable-blink-features=AutomationControlled"],                    )                    page = context.new_page()                    page.set_default_timeout(DEFAULT_TIMEOUT_MS)
                    self._goto(page, BASE_URL)
                    # 1) 登录                    if not self.ensure_logged_in(page):                        context.close()                        return "登录失败(可能选择器不匹配/验证码/账号错误)"
                    # 2) 进入签到页                    if not self.open_signin_page(page):                        context.close()                        return "进入签到页失败(需要补充签到入口URL或更新选择器)"
                    # 3) 执行签到                    result = self.do_signin(page)
                    context.close()                    return result
            except Exception as e:                self._log(f"❌ 本次尝试失败: {e}")                self._log(traceback.format_exc())                if attempt < RETRY_TIMES:                    self._log("⏳ 稍后重试...")                    time.sleep(2)
        return "连续多次失败:请检查网络/选择器/登录是否需要验证码"

def load_config() -> RunConfig:    username = os.getenv("HONGDOU_USERNAME", "").strip()    password = os.getenv("HONGDOU_PASSWORD", "").strip()    if not username or not password:        raise RuntimeError("缺少环境变量:HONGDOU_USERNAME / HONGDOU_PASSWORD")
    headless = os.getenv("HEADLESS", "true").strip().lower() not in ("false", "0", "off")    data_dir = os.getenv("DATA_DIR", "./user_data").strip()
    return RunConfig(        username=username,        password=password,        headless=headless,        data_dir=data_dir,        screenshot_dir="./screenshots",    )

def main():    cfg = load_config()    bot = HongDouSignInBot(cfg)    result = bot.run()    print("\n====== 最终结果 ======")    print(result)

if __name__ == "__main__":    main()

解析

该脚本为红豆社区自动签到脚本,主要功能包括:
  • 自动打开红豆社区,检测是否已登录(复用 user_data 保存的登录态)。

  • 如未登录,则自动执行账号密码登录

  • 进入签到页面/签到入口",点击立即签到完成签到。

  • 支持失败重试、截图留证、日志输出,便于在青龙/服务器环境排查问题。

  • 关键选择器集中在 SELECTORS,站点结构变动时只改一处即可。

主要方法

  • HongDouSignInBot.run → 脚本总入口:启动浏览器、打开网站、登录、进入签到页、执行签到并返回结果。

  • HongDouSignInBot.ensure_logged_in → 检查是否已有登录态;没有则执行账号密码登录并判断登录是否成功。

  • HongDouSignInBot.open_signin_page → 尝试从页面点击"签到入口";若失败则尝试一组候选签到 URL,直到命中签到相关页面。

  • HongDouSignInBot.do_signin → 判断是否已签到;未签到则点击"立即签到",并尝试识别签到结果。

  • HongDouSignInBot._goto → 打开指定 URL 并等待页面基础加载完成。

  • HongDouSignInBot._click_if_exists → 尝试点击某个元素(带超时/异常处理),用于增强脚本健壮性。

  • HongDouSignInBot._fill_if_exists → 尝试在输入框填值(带超时/异常处理)。

  • HongDouSignInBot._shot → 保存当前页面截图,便于排查选择器不匹配、验证码等问题。

  • load_config → 从环境变量读取账号密码与运行参数,构造运行配置。


注意

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


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

没有评论:

发表评论

红豆社区自动签到脚本使用指南

此脚本实现红豆社区自动签到,支持登录态复用、失败重试及截图日志。需配置服务器环境与账号信息,仅限学习研究。 1.购买服务器 阿里云: 服务器购买地址 https://t.aliyun.com/U/kcPAeY 若失效,可用地址 https ://www.aliyun.com/...