告别机械重复:使用 Node.js + Playwright 构建 24 小时全自动测试网领水脚本

木西 发布于 2026-07-08 阅读 23

拒绝机械劳动是我们的本能。我利用前端领域的核心技术栈,打造了一套 **“24 小时全自动定时领水脚本

引言:为什么我要写这个脚本?

作为一名 Web3 开发者或“撸毛”玩家,日常任务清单里一定少不了这一项:去测试网水龙头(Faucet)领测试币

Sepolia ETH、各种 Layer2 的测试代币……虽然它们是“免费”的,但没有这些 gas,无论是智能合约部署还是交互测试都将寸步难行。然而,长期的手动操作痛点令人抓狂:

  • 机械的低效重复:每天固定动作——翻开书签、输入地址、点击确认。
  • 脆弱的节奏感:水龙头通常有 24 小时冷却限制,一旦因工作繁忙或时差漏掉,后续的开发/交互进度直接“断层”。
  • 进阶的防爬壁垒:为了对抗恶意刷取,官方水龙头(如 Google Cloud、ZAN)纷纷引入了账号登录、人机验证等复杂机制,导致传统的单纯 API 请求(axios/fetch)几乎全部失效。

身为前端工程师,拒绝机械劳动是我们的本能。我利用前端领域的核心技术栈,打造了一套 **“24 小时全自动定时领

技术选型:为何前端是自动化的最佳入口?

相比于传统的 Python(Selenium/Pyppeteer),前端社区的自动化生态在处理现代 Web 交互时展现出降维打击的优势:

  • Playwright:目前最前沿的自动化测试框架,天然支持 TypeScript/ESM,拥有极强的网络拦截能力,并能完美处理 Shadow DOM,模拟真人操作如丝般顺滑。
  • 持久化上下文(Persistent Context) :这是自动化脚本的“灵魂”,能够保存 Session 与 Cookie,让我们得以绕过人机验证的重灾区。

## 核心实现:两步调通自动化 Agent

为了规避自动化行为触发 Google 的高强度人机检测,我采取了 “先手动登录存凭证,后全自动运行” 的策略。

第一步:创建专用浏览器配置文件 (login.js)

该脚本负责创建一个带有本地持久化存储的浏览器环境。你只需手动操作一次登录,后续脚本便能“记住”你的登录状态。只需执行一次

import { chromium } from 'playwright';
import path from 'path';

const userDataDir = path.resolve('./browser_profile');

async function startLoginWindow() {
    console.log('正在为你打开专用的【登录配置浏览器】...');
    const context = await chromium.launchPersistentContext(userDataDir, {
        headless: false, 
        viewport: { width: 1280, height: 800 },
        args: ['--disable-blink-features=AutomationControlled']
    });
    
    const page = await context.newPage();
    
    // 依次打开两个网站的标签页
    await page.goto('https://google.com');
    const page2 = await context.newPage();
    await page2.goto('https://zan.top');

    console.log('\n==================================================');
    console.log('👉 请在弹出的浏览器中完成以下操作:');
    console.log('1. 在第一个标签页登录你的 Google 账号,并完成一次领水');
    console.log('2. 在第二个标签页登录你的 ZAN 账号,并完成一次领水');
    console.log('⚠️ 注意:完成登录和领水后,直接把这个命令行的【终端关闭】或【按 Ctrl+C】即可!');
    console.log('==================================================\n');
}

startLoginWindow();

第二步:核心定时自动化 Agent (faucet-agent.js)

利用 node-schedule 设定每天固定时间(例如早上 9:00)自动触发。脚本会自动识别动态变化的 Angular Material 标签组件,完成精准输入与点击。

import { chromium } from 'playwright';
import schedule from 'node-schedule';
import path from 'path';

// 配置你的钱包地址
const WALLET_ADDRESS = '0xYourActualWalletAddressHere'; 

// 关键:指定一个本地文件夹用来存放浏览器的登录状态(Cookies、LocalStorage等)
// 这样你手动登录一次 Google 和 ZAN 之后,脚本以后运行时就是登录状态
const userDataDir = path.resolve('./browser_profile');

async function claimTokens() {
    console.log(`[${new Date().toLocaleString()}] 启动 Faucet 自动化 Agent...`);
    
    // 启动带“记忆”的浏览器(为了调试,headless 设为 false 展现界面)
    const context = await chromium.launchPersistentContext(userDataDir, {
        headless: false, 
        viewport: { width: 1280, height: 800 },
        args: ['--disable-blink-features=AutomationControlled'] // 移除自动化特征,防爬
    });
    
    const page = await context.newPage();

    try {
        // ==========================================
        // 任务一:Google Cloud Faucet
        // ==========================================
        console.log('正在访问 Google Cloud Faucet...');
        await page.goto('https://cloud.google.com/application/web3/faucet/ethereum/sepolia', { waitUntil: 'networkidle', timeout: 60000 });
        
        // 检查是否需要登录(如果没登录,脚本暂停并提示你)
        if (await page.getByText('Sign in', { exact: false }).isVisible()) {
            console.log('⚠️ 检查到 Google 账号未登录,请在弹出的浏览器中手动登录!');
            await page.waitForTimeout(30000); // 留出30秒给你手动操作
        }

        // 输入钱包地址(Google Cloud 使用标准的 input 框或带有特定 placeholder 的元素)
        // 提示:大模型 Agent 此时可以通过文本匹配精准定位
        // const googleInput = page.locator('input[type="text"], input[placeholder*="address"]');
         const googleInput = page.locator('input[id*="mat-input-"]').first();
        await googleInput.waitFor({ state: 'visible', timeout: 10000 });
        await googleInput.fill(WALLET_ADDRESS);

        // 点击领取按钮(通常带有 "Get" 或 "Receive" 文本)
        const googleSubmitBtn = page.locator('button:has-text(" Get 0.05 Sepolia ETH "), button:has-text("Receive")').first();
        await googleSubmitBtn.click();
        console.log('✅ Google Cloud 领水请求已提交,等待5秒...');
        await page.waitForTimeout(5000);

        // ==========================================
        // 任务二:ZAN Faucet
        // ==========================================
        console.log('正在访问 ZAN Faucet...');
        await page.goto('https://zan.top/faucet', { waitUntil: 'networkidle', timeout: 60000 });

        if (await page.getByText('Login', { exact: false }).isVisible()) {
            console.log('⚠️ 检查到 ZAN 账号未登录,请在弹出的浏览器中手动登录!');
            await page.waitForTimeout(30000); 
        }

        // ZAN 页面可能需要先选中 Sepolia 网络
        const sepoliaTab = page.locator('text=Sepolia').first();
        if (await sepoliaTab.isVisible()) {
            await sepoliaTab.click();
        }

        // 输入钱包地址并点击
        const zanInput = page.locator('input[id*="address"]').first();
        await zanInput.waitFor({ state: 'visible', timeout: 10000 });
        await zanInput.fill(WALLET_ADDRESS);

        // ZAN 的提交按钮通常叫 "Claim" 或 "Submit"
        const zanSubmitBtn = page.locator('button:has-text("Claim"), button:has-text("Submit")').first();
        await zanSubmitBtn.click();
        console.log('✅ ZAN Faucet 领水请求已提交。');
        
        await page.waitForTimeout(5000);

    } catch (error) {
        console.error('❌ 自动化执行中发生错误:', error);
    } finally {
        await context.close();
        console.log('浏览器上下文已关闭,本次任务结束。');
    }
}

// ==========================================
// 自动化定时触发逻辑
// ==========================================
// 设定每天早上 9:00:00 自动执行(因为水龙头通常每24小时只能领一次)
const cronRule = '0 0 9 * * *'; 
schedule.scheduleJob(cronRule, () => {
    claimTokens();
});

console.log('🚀 Faucet 定时 Agent 已启动,将在每日 09:00 自动运行...');

// 首次部署本地调试时,可以直接取消注释下一行立即跑一次:
// claimTokens();

避坑指南:给开发者的进阶技巧

在构建自动化 Agent 时,我总结了几项关键的抗检测与稳定性技巧:

  1. Stealth 防爬对抗:许多网站会检测 navigator.webdriver。通过添加参数 --disable-blink-features=AutomationControlled,可以抹去自动化工具的“指纹”。
  2. 动态组件选择策略:现代 Web 框架(Angular/React)生成的 ID 往往包含随机数(如 mat-input-1234)。永远不要使用死板的 ID 选择器,应优先使用 CSS 正则匹配(如 input[id*="mat-input-"])或 语义化选择器(如 button:has-text("Claim"))。
  3. 从“自动化”到“智能体” :目前的逻辑是基于预设选择器的,若网页结构变动,脚本会失效。进阶方案是接入大模型的 Vision(视觉能力) :当 catch 到元素找不到的错误时,将屏幕截图发给 AI,由 AI 分析并吐出新的 CSS 选择器,真正实现“自我修复”。

结语

通过这个轻量级 Agent,我将原本每天 5 分钟的重复劳动,转化为了电脑后台的自动化生产力。这不仅是一个节省时间的工具,更是我们作为前端开发者,在 Web3 生态中利用技术掌控效率的缩影。

相关文章

0 条评论