2026年1月24日星期六

Hometown Pass Auto Check-In Script Guide and Code

Summary: Provides server purchase links (Alibaba, Tencent, Huawei Clouds), a deployment tutorial link, and Python script code for automating daily check-ins on ms.ccoo.cn. The script features auto-login, sign-in button detection, and cookie persistence.

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 reimport sysimport timefrom pathlib import Pathfrom typing import OptionalList
from playwright.sync_api import sync_playwright, TimeoutError as PWTimeoutError
BASE_URL = os.getenv("CCOO_BASE_URL""http://www.ms.ccoo.cn/").rstrip("/") + "/"STATE_FILE = Path("storage_state.json")
USER = os.getenv("CCOO_USER""").strip()PASS = os.getenv("CCOO_PASS""").strip()
# 你可以把这里改成更明确的入口(如果你知道网站签到入口)CANDIDATE_PATHS = [    "",  # 首页    "user/""member/""my/""mine/""ucenter/""account/",    "signin/""sign/""checkin/""task/""mission/""qiandao/",]
# 常见"签到/打卡/领取"按钮文案关键字BUTTON_TEXT_KEYWORDS = [    "签到""打卡""今日签到""立即签到""一键签到",    "领取""领积分""领红包""任务""去签到",]

def log(msg: str):    print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}{msg}", flush=True)

def open_candidate_pages(page) -> None:    """依次打开签到入口的页面,提高命中率"""    for p in CANDIDATE_PATHS:        url = BASE_URL + p        try:            log(f"打开页面: {url}")            page.goto(url, wait_until="domcontentloaded", timeout=25000)            page.wait_for_timeout(800)        except PWTimeoutError:            log(f"打开超时,跳过: {url}")            continue

def is_logged_in(page) -> bool:    """    基于页面特征判断是否已登录(通用 heuristics)    命中任意一种即认为登录态存在:    - 页面出现"退出/注销/个人中心/我的"等    - 页面包含明显的用户头像/昵称区域(常见 class)    """    html = page.content()    if any(k in html for k in ["退出""注销""个人中心""我的资料""我的订单""我的主页"]):        return True    # 常见用户区域class/id特征(可按实际站点补充)    for sel in [        "text=退出""text=注销""text=个人中心""text=我的",        "[class*='avatar']""[class*='user']""[id*='user']""[id*='avatar']",    ]:        try:            if page.locator(sel).first.is_visible(timeout=800):                return True        except Exception:            pass    return False

def try_login(page) -> bool:    """    通用登录流程:    1) 打开首页    2) 尝试点击"登录/账号登录/密码登录"    3) 尝试在页面上找到账号/密码输入框并填写    4) 点击"登录/提交"    """    if not USER or not PASS:        log("❌ 未设置环境变量 CCOO_USER / CCOO_PASS,无法自动登录")        return False
    page.goto(BASE_URL, wait_until="domcontentloaded", timeout=25000)    page.wait_for_timeout(1000)
    # 先尝试点"登录"入口    login_entry_selectors = [        "text=登录""text=立即登录""text=账号登录""text=密码登录",        "a:has-text('登录')""button:has-text('登录')",    ]    for sel in login_entry_selectors:        try:            loc = page.locator(sel).first            if loc.is_visible(timeout=800):                loc.click(timeout=1500)                page.wait_for_timeout(800)                break        except Exception:            pass
    # 寻找账号/密码输入框(常见 placeholder / name / type)    user_selectors = [        "input[placeholder*='手机']",        "input[placeholder*='账号']",        "input[placeholder*='用户名']",        "input[placeholder*='邮箱']",        "input[type='text']",        "input[name*='user']",        "input[name*='mobile']",        "input[name*='email']",        "input[id*='user']",        "input[id*='mobile']",    ]    pass_selectors = [        "input[type='password']",        "input[placeholder*='密码']",        "input[name*='pass']",        "input[id*='pass']",    ]
    user_box = None    pwd_box = None
    for sel in user_selectors:        try:            loc = page.locator(sel).first            if loc.is_visible(timeout=800):                user_box = loc                break        except Exception:            pass
    for sel in pass_selectors:        try:            loc = page.locator(sel).first            if loc.is_visible(timeout=800):                pwd_box = loc                break        except Exception:            pass
    if not user_box or not pwd_box:        log("❌ 未能自动定位账号/密码输入框(需要你根据实际页面补 1-2 个选择器)")        return False
    user_box.fill(USER, timeout=3000)    pwd_box.fill(PASS, timeout=3000)
    # 点击登录按钮    submit_selectors = [        "button:has-text('登录')",        "button:has-text('提交')",        "button:has-text('确定')",        "input[type='submit']",        "text=登录",    ]    clicked = False    for sel in submit_selectors:        try:            loc = page.locator(sel).first            if loc.is_visible(timeout=800):                loc.click(timeout=2000)                clicked = True                break        except Exception:            pass
    if not clicked:        log("❌ 未找到可点击的登录按钮(需要你补充登录按钮选择器)")        return False
    # 等待跳转/登录态生效    page.wait_for_timeout(2500)    # 有些站点登录后会跳回首页或个人中心,这里再打开一遍首页确认    page.goto(BASE_URL, wait_until="domcontentloaded", timeout=25000)    page.wait_for_timeout(1000)
    ok = is_logged_in(page)    log("✅ 登录成功" if ok else "❌ 登录可能失败(未检测到登录态)")    return ok

def find_sign_buttons(page) -> List:    """    多策略找"签到/打卡/领取"按钮:    - 按文本关键词找 button/a/div/span    - 按常见 class/id(qiandao/sign/checkin/task)    """    candidates = []
    # 1) 文本关键字    for kw in BUTTON_TEXT_KEYWORDS:        for sel in [            f"button:has-text('{kw}')",            f"a:has-text('{kw}')",            f"div:has-text('{kw}')",            f"span:has-text('{kw}')",        ]:            try:                locs = page.locator(sel)                count = min(locs.count(), 5)                for i in range(count):                    one = locs.nth(i)                    if one.is_visible(timeout=300):                        candidates.append(one)            except Exception:                pass
    # 2) 常见标识    for sel in [        "[class*='qiandao']",        "[class*='sign']",        "[class*='checkin']",        "[id*='qiandao']",        "[id*='sign']",        "[id*='checkin']",        "a[href*='qiandao']",        "a[href*='sign']",        "a[href*='checkin']",        "a[href*='task']",    ]:        try:            locs = page.locator(sel)            count = min(locs.count(), 5)            for i in range(count):                one = locs.nth(i)                if one.is_visible(timeout=300):                    candidates.append(one)        except Exception:            pass
    # 去重(按 element handle)    uniq = []    seen = set()    for c in candidates:        try:            h = c.element_handle()            if not h:                continue            key = h._impl_obj._guid if hasattr(h, "_impl_obj"else str(h)            if key not in seen:                seen.add(key)                uniq.append(c)        except Exception:            pass    return uniq

def do_sign(page) -> bool:    """执行签到:打开候选页面 → 找按钮 → 逐个尝试点击"""    open_candidate_pages(page)
    btns = find_sign_buttons(page)    if not btns:        log("❌ 未找到任何疑似签到/打卡按钮(建议你指定一个明确的签到入口路径或选择器)")        return False
    log(f"发现 {len(btns)} 个疑似按钮,开始尝试点击…")    for idx, b in enumerate(btns, 1):        try:            text = (b.inner_text(timeout=800or "").strip().replace("\n"" ")        except Exception:            text = ""
        try:            log(f"尝试点击第 {idx} 个按钮: {text[:30]}")            b.click(timeout=2000)            page.wait_for_timeout(1500)
            # 点击后一般会出现"已签到/成功/领取成功"等提示            html = page.content()            if any(k in html for k in ["已签到""签到成功""打卡成功""领取成功""成功"]):                log("✅ 检测到成功提示,签到可能已完成")                return True
            # 也可能直接跳转到结果页            if re.search(r"(sign|qiandao|checkin|task|mission)", page.url, re.I):                log(f"ℹ️ 页面已跳转到: {page.url}")                # 继续用提示判断                html2 = page.content()                if any(k in html2 for k in ["已签到""签到成功""打卡成功""领取成功""成功"]):                    log("✅ 检测到成功提示,签到可能已完成")                    return True
        except Exception as e:            log(f"点击失败,继续下一个: {e}")
    log("❌ 已尝试所有候选按钮,仍未判断为签到成功")    return False

def main():    log("开始执行 ms.ccoo.cn 自动签到(通用探测版)")
    with sync_playwright() as p:        browser = p.chromium.launch(headless=True)        context = browser.new_context(storage_state=str(STATE_FILE) if STATE_FILE.exists() else None)        page = context.new_page()
        # 1) 先检查登录态        page.goto(BASE_URL, wait_until="domcontentloaded", timeout=25000)        page.wait_for_timeout(1000)
        if not is_logged_in(page):            log("未检测到登录态,开始自动登录…")            if not try_login(page):                log("❌ 登录失败,终止")                browser.close()                sys.exit(1)        else:            log("✅ 检测到已登录态(将直接签到)")
        # 2) 执行签到        ok = do_sign(page)
        # 3) 保存登录态,便于下次免登        context.storage_state(path=str(STATE_FILE))        log(f"✅ 已保存登录态到 {STATE_FILE.resolve()}")
        browser.close()
        if ok:            log("🎉 脚本执行结束:签到流程已完成(或检测到成功提示)")            sys.exit(0)        else:            log("⚠️ 脚本执行结束:未能确认签到成功(需要补充入口或选择器)")            sys.exit(2)

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

该脚本为家乡通自动签到脚本,主要作用包括:

  • 自动复用 Cookie:优先读取 storage_state.json,能免登录直接跑签到。

  • 自动登录:未登录时,尝试点击"登录",自动填入账号密码并提交。

  • 自动探测签到入口:遍历一批常见"个人中心/任务/签到"路径。

  • 自动找"签到/打卡/领取"按钮:通过"文本关键字 + 常见class/id/href"多策略定位并点击。

  • 保存登录态:执行结束后保存最新 Cookie,下次更稳定。

主要方法

  • log → 统一输出带时间戳的日志,便于排障。

  • open_candidate_pages → 依次打开常见个人中心/任务/签到路径,提高命中率。

  • is_logged_in → 用页面关键字/元素特征判断是否处于登录状态。

  • try_login → 自动完成"找登录入口 → 填账号密码 → 提交 → 验证登录态"的流程。

  • find_sign_buttons → 多策略搜集疑似"签到/打卡/领取"按钮(文本匹配 + 标识匹配)。

  • do_sign → 执行签到核心流程:打开候选页 → 找按钮 → 逐个点击 → 判断成功提示。

  • main → 脚本入口:加载/复用登录态 → 必要时登录 → 执行签到 → 保存登录态并退出。


注意

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


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

没有评论:

发表评论

Hometown Pass Auto Check-In Script Guide and Code

Summary: Provides server purchase links (Alibaba, Tencent, Huawei Clouds), a deployment tutorial link, and Python script code for automating...