2026年2月5日星期四

Huilongguan Community Auto-Sign-in Script Guide

Summary: This script automates daily sign-in for Huilongguan community sites. It includes server setup links, deployment steps, and Python code for login and sign-in via keyword detection. Screenshots and retries aid troubleshooting. Use requires environment variables for credentials.

1.购买服务器

阿里云:

服务器购买地址

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

2.部署教程

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

3.代码如下

# -*- coding: utf-8 -*-
import osimport timeimport pathlibfrom datetime import datetimefrom typing import OptionalListTuple
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeoutError

BASE_URLS = [    "https://www.hlgnet.com/",    "http://bbs.hlgnet.com/",]
KEYWORDS_SIGN = ["签到""打卡""每日签到""签 到""Check in""checkin"]KEYWORDS_LOGIN = ["登录""登录/注册""登陆"]KEYWORDS_LOGOUT = ["退出""退出登录""注销"]
ART_DIR = pathlib.Path("hlgnet_artifacts")ART_DIR.mkdir(exist_ok=True)

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

def save_screenshot(page, name: str) -> str:    fp = ART_DIR / f"{datetime.now().strftime('%Y%m%d_%H%M%S')}_{name}.png"    page.screenshot(path=str(fp), full_page=True)    return str(fp)

def wait_network_idle(page, timeout_ms: int = 15000) -> None:    # Playwright 的 networkidle 对某些站点可能不稳定,因此做一个温和等待    try:        page.wait_for_load_state("domcontentloaded", timeout=timeout_ms)    except PWTimeoutError:        pass    time.sleep(1.0)

def open_site(page) -> str:    """    依次尝试打开可访问的URL,返回最终使用的URL    """    last_err = None    for url in BASE_URLS:        try:            page.goto(url, wait_until="domcontentloaded", timeout=20000)            wait_network_idle(page)            return url        except Exception as e:            last_err = e    raise RuntimeError(f"站点不可访问:{last_err}")

def is_logged_in(page) -> bool:    """    通过页面上是否出现"退出/注销"等关键词粗略判断已登录    """    text = page.inner_text("body")[:20000]    return any(k in text for k in KEYWORDS_LOGOUT)

def try_click_by_keywords(page, keywords: List[str], max_click: int = 1) -> bool:    """    在页面内搜索包含关键词的可点击元素并点击    - 优先找 a/button    - 找到后尝试滚动到可见区域点击    """    clicked = 0    for kw in keywords:        # a / button / role=button / input[type=submit] 的组合检索        candidates = [            f"a:has-text('{kw}')",            f"button:has-text('{kw}')",            f"[role='button']:has-text('{kw}')",        ]        for sel in candidates:            loc = page.locator(sel).first            try:                if loc.count() > 0:                    loc.scroll_into_view_if_needed(timeout=3000)                    loc.click(timeout=3000)                    clicked += 1                    wait_network_idle(page)                    if clicked >= max_click:                        return True            except Exception:                continue    return clicked > 0

def try_login(page, username: str, password: str) -> bool:    """    尝试登录(通用策略):    1) 点击"登录/登陆"    2) 寻找账号/密码输入框    3) 提交表单    """    # 已登录则跳过    if is_logged_in(page):        return True
    # 尝试打开登录页/弹窗    try_click_by_keywords(page, KEYWORDS_LOGIN, max_click=1)
    # 常见的输入框策略:text/email/tel + password    # 账号输入框可能是 name=username / email / phone 等    account_selectors = [        "input[name='username']",        "input[name='user']",        "input[name='account']",        "input[name='email']",        "input[name='mobile']",        "input[type='text']",        "input[type='email']",        "input[type='tel']",    ]    pass_selectors = [        "input[name='password']",        "input[name='pass']",        "input[type='password']",    ]    submit_selectors = [        "button:has-text('登录')",        "button:has-text('登陆')",        "input[type='submit']",        "button[type='submit']",    ]
    # 填账号    account_filled = False    for sel in account_selectors:        loc = page.locator(sel).first        try:            if loc.count() > 0 and loc.is_visible():                loc.click()                loc.fill(username)                account_filled = True                break        except Exception:            continue
    # 填密码    pass_filled = False    for sel in pass_selectors:        loc = page.locator(sel).first        try:            if loc.count() > 0 and loc.is_visible():                loc.click()                loc.fill(password)                pass_filled = True                break        except Exception:            continue
    if not (account_filled and pass_filled):        return False
    # 提交    submitted = False    for sel in submit_selectors:        loc = page.locator(sel).first        try:            if loc.count() > 0 and loc.is_visible():                loc.click(timeout=5000)                submitted = True                break        except Exception:            continue
    wait_network_idle(page)
    # 验证是否登录成功    return submitted and is_logged_in(page)

def do_sign(page) -> Tuple[boolstr]:    """    执行签到:    - 在当前页面尝试寻找"签到/打卡/每日签到"等入口点击    - 如果跳转到新页面,再次尝试点击"签到"按钮    """    # 第一次在首页/当前页找入口    ok = try_click_by_keywords(page, KEYWORDS_SIGN, max_click=1)    if not ok:        return False"未找到签到入口(页面未出现"签到/打卡/每日签到"等字样)"
    # 进入签到页后,还有一个"立即签到/签到领取/确认签到"    ok2 = try_click_by_keywords(page, ["立即签到""确认签到""签到领取""签到""打卡"], max_click=1)    if ok2:        return True"已点击签到按钮(请以页面实际结果为准)"
    # 如果第二步没找到,点入口即完成    return True"已点击签到入口(入口可能已完成签到或需要在新页面手动确认)"

def run(max_retry: int = 2, headless: bool = True) -> None:    user = os.getenv("HLG_USER""").strip()    pwd = os.getenv("HLG_PASS""").strip()    if not user or not pwd:        raise RuntimeError("缺少环境变量:HLG_USER / HLG_PASS(账号密码)")
    with sync_playwright() as p:        browser = p.chromium.launch(headless=headless)        context = browser.new_context(locale="zh-CN")        page = context.new_page()
        last_error: Optional[str] = None        for attempt in range(1, max_retry + 2):            try:                print(f"[{now_str()}] 第 {attempt} 次尝试:打开站点")                used_url = open_site(page)                print(f"[{now_str()}] 已打开:{used_url}")
                print(f"[{now_str()}] 尝试登录")                logged = try_login(page, user, pwd)                if not logged:                    shot = save_screenshot(page, "login_failed")                    raise RuntimeError(f"登录流程未成功(可能是站点登录结构不同/出现验证码/输入框未命中)。截图:{shot}")
                print(f"[{now_str()}] 登录状态:OK")
                print(f"[{now_str()}] 开始执行签到")                ok, msg = do_sign(page)                shot = save_screenshot(page, "after_sign")                print(f"[{now_str()}] 签到结果:{ok} - {msg}")                print(f"[{now_str()}] 截图:{shot}")                return
            except Exception as e:                last_error = str(e)                print(f"[{now_str()}] ❌ 本次失败:{last_error}")                try:                    shot = save_screenshot(page, "error")                    print(f"[{now_str()}] 错误截图:{shot}")                except Exception:                    pass                time.sleep(2)
        raise RuntimeError(f"多次重试仍失败:{last_error}")

if __name__ == "__main__":    # headless=True:无头模式(适合服务器/青龙)    # 若要调试选择器,把 headless 改为 False    run(max_retry=2, headless=True)
解析

该脚本为回龙观自动签到脚本,主要作用包括:

  1. 自动打开回龙观社区网站(优先 https,失败则尝试 bbs 子站 http)。

  2. 自动登录(使用环境变量提供的账号密码)。

  3. 自动寻找"签到/打卡/每日签到"入口并点击,尽量不依赖固定签到 URL。

  4. 保存截图与日志,便于你定位是登录页结构变化、入口文字变化、还是验证码拦截导致失败。

  5. 失败自动重试(默认最多 3 次尝试)。

主要方法

  • now_str:生成当前时间字符串,用于日志打印。

  • save_screenshot:保存当前页面截图到本地 hlgnet_artifacts/,用于排障。

  • wait_network_idle:等待页面基础加载完成并额外停顿,降低动态渲染导致的找不到元素问题。

  • open_site:按顺序尝试打开可访问的站点入口 URL,返回最终成功打开的地址。

  • is_logged_in:通过页面是否出现"退出/注销"等文本,粗略判断是否已登录。

  • try_click_by_keywords:在页面里按关键词搜索可点击元素(a/button/role=button)并点击,用于"登录/签到"这种入口不固定的场景。

  • try_login:通用登录流程:点击登录入口 → 填账号密码 → 提交 → 再用 is_logged_in 验证。

  • do_sign:执行签到流程:先点"签到入口",若进入签到页再点"立即签到/确认签到"等按钮。

  • run:脚本总入口,串联"打开站点 → 登录 → 签到 → 截图 → 重试"的完整流程。


注意

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


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

没有评论:

发表评论

OpenClaw AI开发挑战赛|春节造产品,赢取Mac Mini

VibeHacks第三期推出"Vibe Coding for OpenClaw"月度主题赛。参赛者在二月围绕火爆的OpenClaw生态开发产品,按月度活跃用户排名。奖品包括Mac Mini、现金及社群会员资格。活动倡导用实际产品与用户数据证明能力。 今年春...