臨時號碼 + 密碼管理器:完成從註冊到登入的全自動化流程

完整實戰——每一步都帶著代碼,每一段代碼都帶著註釋,每一個坑都提前替你踩平了。

真實的「註冊地獄」:每次測試新服務都要人肉走完「生成密碼→找虛擬號→填表→等驗證碼→填入→保存憑據」的全流程,重複十次下來比寫代碼還累。
核心承諾:本文用臨時號碼 API + 密碼管理器 CLI + 瀏覽器自動化,把你的註冊流程從 5 分鐘壓縮到 30 秒,全程無需人工干預。

一、完整的人話版自動化流程

以下是整個自動化流水線的 9 步序列圖。每一步都有對應的代碼塊,全程一氣呵成:

1. 密碼管理器生成隨機強密碼 2. 接碼平台獲取虛擬號碼 3. 瀏覽器自動打開註冊頁 4. 自動填寫郵箱、密碼、虛擬號碼 5. 點擊發送驗證碼 6. 輪詢接碼平台獲取短信 7. 正則提取驗證碼 8. 自動填入驗證碼並提交 9. 註冊成功 → 保存憑據到密碼管理器

全程 9 步,從生成密碼到憑據安全入庫,平均耗時 25–45 秒(視短信延遲而定)。

二、Step 1:密碼管理器 CLI——生成與存儲憑據

密碼管理器是整個自動化流水線的「記憶體」——負責生成強密碼和安全存儲最終憑據。以下提供兩種主流方案的完整命令。

方案 A:1Password CLI

使用 Service Account 綁定測試專用 Vault 進行操作。先建立一個僅供自動化使用的 Vault,避免與個人數據混雜。

# 登入 Service Account(使用環境變數避免硬編碼)
export OP_SERVICE_ACCOUNT_TOKEN="你的ServiceAccountToken"

# 生成 24 位隨機強密碼
PASSWORD=$(op item generate --format json | jq -r '.password')

# 建立完整憑據條目(URL + 郵箱 + 密碼 + 虛擬號碼)
op item create \
  --category login \
  --title "測試帳號-Google-$(date +%Y%m%d%H%M%S)" \
  --url "https://accounts.google.com" \
  "[email protected]" \
  "password=${PASSWORD}" \
  "phone=等待虛擬號碼填入"

# 後續可用 op item edit 更新 phone 欄位
# op item edit "測試帳號-Google-xxx" "phone=+1234567890"

錯誤處理:在腳本開頭加入會話狀態檢查,若 Token 未設置則提前報錯退出:

if [ -z "$OP_SERVICE_ACCOUNT_TOKEN" ]; then
    echo "❌ 請先設置 OP_SERVICE_ACCOUNT_TOKEN 環境變數"
    exit 1
fi

方案 B:Bitwarden CLI

使用 API Key 登入,bw unlock 後操作。Bitwarden 是開源方案,適合成本敏感的個人開發者。

# 設定 API Key 環境變數
export BW_CLIENTID="your_client_id"
export BW_CLIENTSECRET="your_client_secret"
export BW_PASSWORD="your_master_password"

# 登入並解鎖
bw login --apikey
BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw)
export BW_SESSION

# 生成 24 位隨機強密碼
PASSWORD=$(bw generate -uln --length 24)

# 建立完整憑據條目
bw create item \
  --type login \
  --name "測試帳號-Google-$(date +%Y%m%d%H%M%S)" \
  --uri "https://accounts.google.com" \
  --username "[email protected]" \
  --password "${PASSWORD}" \
  --notes "虛擬號碼: 待填入"

錯誤處理:檢查 BW_SESSION 是否成功獲取,失敗時自動重試:

if [ -z "$BW_SESSION" ]; then
    echo "⚠️ Bitwarden 會話獲取失敗,正在重試..."
    bw login --apikey
    BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw)
fi

三、Step 2:接碼平台 API——獲取號碼與輪詢短信

以下以 5sim API 為例,封裝三個核心函數。返回結構體包含號碼、短信正文和提取後的驗證碼。

import requests
import time
import re
import os

API_KEY = os.getenv('FIVESIM_API_KEY', 'your_key')
BASE = 'https://5sim.net/v1'

def headers():
    return {'Authorization': f'Bearer {API_KEY}', 'Accept': 'application/json'}

def get_number(country='usa', service='google'):
    """獲取虛擬號碼,返回 (phone, activation_id)"""
    resp = requests.get(f'{BASE}/user/buy/activation/{country}/any/{service}', headers=headers())
    if resp.status_code != 200:
        raise Exception(f'獲取號碼失敗: {resp.status_code} {resp.text}')
    data = resp.json()
    return data['phone'], data['id']  # id 即 activation_id

def wait_for_sms(activation_id, timeout=60):
    """輪詢短信,返回 (sms_text, otp_code)"""
    start = time.time()
    while time.time() - start < timeout:
        resp = requests.get(f'{BASE}/user/check/{activation_id}', headers=headers())
        data = resp.json()
        if data.get('status') == 'RECEIVED' and data.get('sms'):
            sms_text = data['sms'][0]['text']  # 取最新一條
            match = re.search(r'\b\d{4,6}\b', sms_text)
            otp = match.group(0) if match else None
            return sms_text, otp
        time.sleep(5)
    raise TimeoutError(f'等待短信超時 ({timeout}秒)')

def release_number(activation_id):
    """釋放號碼(可選)"""
    requests.get(f'{BASE}/user/cancel/{activation_id}', headers=headers())

關鍵參數說明: country='usa' 美國號碼在 OpenAI 和 Google 註冊中成功率最高;service='google' 可替換為 openaitelegram 等;timeout=60 秒是實測中短信到達的合理上限。

四、Step 3:瀏覽器自動化——填寫表單與提交

以 Playwright 為例,包含反檢測措施和受控組件繞過。以下代碼涵蓋從打開頁面到提交表單的完整流程。

from playwright.sync_api import sync_playwright
import random, time

def set_native_value(page, selector, value):
    """繞過 React/Vue 受控組件檢測,觸發原生 input 事件"""
    page.evaluate("""
        (args) => {
            const el = document.querySelector(args.selector);
            const nativeSetter = Object.getOwnPropertyDescriptor(
                window.HTMLInputElement.prototype, 'value'
            ).set;
            nativeSetter.call(el, args.value);
            el.dispatchEvent(new Event('input', { bubbles: true }));
            el.dispatchEvent(new Event('change', { bubbles: true }));
        }
    """, {'selector': selector, 'value': value})

def auto_register_browser(target_url, email, password, phone):
    """瀏覽器自動化註冊,返回 Playwright page 物件供後續 OTP 填入"""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(
            user_agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
            viewport={'width': 1920, 'height': 1080}
        )
        page = context.new_page()

        # Step 1: 打開註冊頁
        page.goto(target_url, wait_until='networkidle')
        time.sleep(random.uniform(1.0, 2.5))

        # Step 2: 依序填寫表單(每個欄位間加入隨機延遲模擬人類操作)
        set_native_value(page, 'input[name="email"], input[type="email"]', email)
        time.sleep(random.uniform(0.5, 1.5))

        set_native_value(page, 'input[name="password"], input[type="password"]', password)
        time.sleep(random.uniform(0.5, 1.5))

        set_native_value(page, 'input[name="phone"], input[type="tel"]', phone)
        time.sleep(random.uniform(0.5, 1.5))

        # Step 3: 點擊發送驗證碼
        page.click('button[type="submit"], button:has-text("Next"), button:has-text("Send code")')
        time.sleep(random.uniform(0.5, 1.0))

        return page, browser, context  # 返回引用供 OTP 填入

反檢測要點: set_native_value 使用原生 value setter 並觸發 inputchange 事件,確保 React/Vue 的受控組件能正確同步狀態。隨機延遲 random.uniform(1000, 2500) 毫秒模擬人類操作間隔,降低被風控識別的機率。

OTP 填入函數

def fill_otp_and_submit(page, otp):
    """填入驗證碼並提交表單"""
    set_native_value(page, 'input[name="code"], input[placeholder*="code"], input[autocomplete="one-time-code"]', otp)
    time.sleep(random.uniform(0.3, 1.0))
    page.click('button[type="submit"], button:has-text("Verify"), button:has-text("Submit")')
    time.sleep(random.uniform(1.0, 2.0))
    return page.url  # 返回當前 URL 判斷是否註冊成功

五、Step 4:主流程編排——一切串起來的指揮棒

以下是將上述三步驟串聯為一條自動化流水線的完整主函數,包含完整的錯誤處理邏輯。

def auto_register(target_url, email, country='usa', service='google', max_retries=3):
    """
    全自動註冊流水線
    target_url: 目標網站註冊頁 URL
    email: 用於註冊的郵箱
    country: 號碼國家代碼
    service: 接碼平台中的服務代碼
    max_retries: 號碼被風控時的最大重試次數
    """
    # 1. 密碼管理器生成隨機強密碼
    import subprocess
    password = subprocess.check_output(['bw', 'generate', '-uln', '--length', '24']).decode().strip()
    print(f'🔐 已生成強密碼: {password[:8]}...')

    # 2. 接碼平台獲取虛擬號碼(含重試)
    for attempt in range(max_retries):
        try:
            phone, activation_id = get_number(country, service)
            print(f'📞 已獲取號碼: {phone} (嘗試 {attempt+1}/{max_retries})')
            break
        except Exception as e:
            if attempt == max_retries - 1:
                raise Exception(f'獲取號碼失敗,已重試 {max_retries} 次: {e}')
            print(f'⚠️ 獲取號碼失敗,5秒後重試... {e}')
            time.sleep(5)

    # 3. 瀏覽器自動打開註冊頁並填表
    print('🌐 正在打開註冊頁並填寫表單...')
    page, browser, context = auto_register_browser(target_url, email, password, phone)

    # 4. 輪詢接碼平台獲取短信
    print('⏳ 等待短信驗證碼...')
    try:
        sms_text, otp = wait_for_sms(activation_id, timeout=60)
        print(f'📩 收到短信: {sms_text[:50]}...')
        if otp:
            print(f'🔑 提取驗證碼: {otp}')
        else:
            print('⚠️ 未能自動提取驗證碼,嘗試正則匹配...')
            otp = re.search(r'\b\d{4,6}\b', sms_text)
            otp = otp.group(0) if otp else input('請手動輸入驗證碼: ')
    except TimeoutError:
        # 短信超時:點擊重新發送
        print('⏰ 短信超時,正在點擊重新發送...')
        page.click('button:has-text("Resend"), button:has-text("重新發送")')
        sms_text, otp = wait_for_sms(activation_id, timeout=60)

    # 5. 填入驗證碼並提交
    print('📝 正在填入驗證碼並提交...')
    final_url = fill_otp_and_submit(page, otp)

    # 6. 判斷註冊結果
    if 'success' in final_url.lower() or 'dashboard' in final_url.lower() or 'welcome' in final_url.lower():
        print('✅ 註冊成功!')
        # 7. 保存憑據到密碼管理器
        subprocess.run(['bw', 'create', 'item',
            '--type', 'login',
            '--name', f'自動註冊-{service}-{phone}',
            '--uri', target_url,
            '--username', email,
            '--password', password,
            '--notes', f'虛擬號碼: {phone}\n短信: {sms_text[:50]}'
        ], check=True)
        print(f'🔒 憑據已保存至 Bitwarden: {email}')
    else:
        print(f'⚠️ 註冊狀態不明,當前 URL: {final_url}')
        # 自動截圖留底
        page.screenshot(path=f'/tmp/register_fail_{phone}.png')
        print('📸 已截圖留底')

    # 8. 清理
    browser.close()
    release_number(activation_id)
    print('🧹 已釋放號碼並關閉瀏覽器')
    return email, password, phone

預期終端日誌輸出:

$ python auto_register.py
🔐 已生成強密碼: X7kP9mQw...
📞 已獲取號碼: +1234567890 (嘗試 1/3)
🌐 正在打開註冊頁並填寫表單...
⏳ 等待短信驗證碼...
📩 收到短信: G-123456 是您的 Google 驗證碼。...
🔑 提取驗證碼: 123456
📝 正在填入驗證碼並提交...
✅ 註冊成功!
🔒 憑據已保存至 Bitwarden: [email protected]
🧹 已釋放號碼並關閉瀏覽器

六、完整演示:以註冊某主流平台為例的端到端腳本

以下是可直接複製運行的完整 Python 腳本(約 80 行),以註冊 Google 帳號為例。將上面所有模組整合成一個可執行的自動化流水線。

#!/usr/bin/env python3
"""全自動 Google 帳號註冊流水線 —— 從生成密碼到保存憑據,全程無需人工干預。"""
import os, sys, time, re, random, subprocess
import requests
from playwright.sync_api import sync_playwright

API_KEY = os.getenv('FIVESIM_API_KEY', 'your_key')
EMAIL = os.getenv('REGISTER_EMAIL', '[email protected]')
TARGET_URL = 'https://accounts.google.com/signup'
COUNTRY = 'usa'
SERVICE = 'google'

def headers():
    return {'Authorization': f'Bearer {API_KEY}', 'Accept': 'application/json'}

def get_number():
    resp = requests.get(f'https://5sim.net/v1/user/buy/activation/{COUNTRY}/any/{SERVICE}', headers=headers())
    if resp.status_code != 200:
        raise Exception(f'獲取號碼失敗: {resp.status_code}')
    data = resp.json()
    return data['phone'], data['id']

def wait_for_sms(aid, timeout=60):
    start = time.time()
    while time.time() - start < timeout:
        resp = requests.get(f'https://5sim.net/v1/user/check/{aid}', headers=headers())
        data = resp.json()
        if data.get('status') == 'RECEIVED' and data.get('sms'):
            sms = data['sms'][0]['text']
            otp = re.search(r'\b\d{6}\b', sms)
            return sms, otp.group(0) if otp else None
        time.sleep(5)
    raise TimeoutError('短信超時')

def main():
    print('🔐 生成強密碼...')
    password = subprocess.check_output(['bw', 'generate', '-uln', '--length', '24']).decode().strip()

    print('📞 獲取虛擬號碼...')
    phone, aid = get_number()
    print(f'  號碼: {phone}')

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(TARGET_URL, wait_until='networkidle')
        time.sleep(random.uniform(2, 3))

        page.fill('input[name="firstName"]', 'Test')
        page.fill('input[name="lastName"]', 'User')
        page.fill('input[name="Username"]', EMAIL.split('@')[0])
        page.fill('input[name="Passwd"]', password)
        page.fill('input[name="ConfirmPasswd"]', password)
        page.click('button:has-text("Next")')
        time.sleep(random.uniform(1, 2))

        page.fill('input[type="tel"]', phone)
        page.click('button:has-text("Next")')
        time.sleep(1)

        print('⏳ 等待短信...')
        sms, otp = wait_for_sms(aid)
        print(f'📩 {sms[:50]}...')
        page.fill('input[type="tel"]', otp)
        page.click('button:has-text("Verify")')
        time.sleep(random.uniform(2, 3))

        final_url = page.url
        if 'myaccount' in final_url or 'signin' in final_url:
            print('✅ 註冊成功!')
            subprocess.run(['bw', 'create', 'item', '--type', 'login',
                '--name', f'Google-{phone}', '--uri', 'https://accounts.google.com',
                '--username', EMAIL, '--password', password,
                '--notes', f'虛擬號碼: {phone}'], check=True)
            print(f'🔒 憑據已保存至 Bitwarden')
        else:
            print(f'⚠️ 狀態不明: {final_url}')
            page.screenshot(path=f'/tmp/google_register_{phone}.png')

        browser.close()
        requests.get(f'https://5sim.net/v1/user/cancel/{aid}', headers=headers())
    print('🧹 完成,號碼已釋放')

if __name__ == '__main__':
    main()

七、進階:工具鏈差異化選擇矩陣表

密碼管理器的差異化選擇

密碼管理器CLI 工具優勢適用場景
1PasswordopSecrets Automation 支援 CI/CD團隊、企業級
Bitwardenbw開源、可自部署個人開發者、成本敏感

瀏覽器自動化的差異化選擇

瀏覽器自動化優勢適用場景
Playwright速度快、API 簡潔、多瀏覽器Python/Node.js 開發者首選
Selenium生態成熟、支援語言多已有 Selenium 環境的團隊

接碼平台的差異化選擇

接碼平台優勢適用場景
SMSPool非 VoIP 物理卡、送達率 68-85%需要高品質號碼的註冊場景
5sim180+ 國家、API 成熟、覆蓋均衡全球範圍多種服務驗證
SMS-MAN價格最低預算優先、能用即可的場景

八、排坑指南

坑一:密碼管理器 CLI 的會話過期

症狀:腳本運行到一半,Bitwarden CLI 回傳 Not logged in 或 1Password CLI 回傳 session expired

解法:在腳本開頭加入會話狀態檢查和自動重登邏輯。對 Bitwarden,使用 bw status 檢查,必要時重新 bw login --apikey 並設置 BW_SESSION 環境變數。對 1Password,確保 OP_SERVICE_ACCOUNT_TOKEN 在腳本啟動前已正確設置且未過期。

坑二:目標網站檢測到自動化工具

症狀:頁面載入後表單無法填寫,或提交時彈出「檢測到異常流量」提示,控制台輸出 navigator.webdriver === true

解法:Playwright 預設已隱藏 WebDriver 屬性,但可進一步強化——注入 Stealth 插件或手動在 page.evaluate() 中覆蓋相關屬性。此外,確保 User-Agent 使用最新 Chrome 版本,視窗大小設為常見尺寸(1920×1080),並在每次操作間加入隨機延遲。

坑三:接碼平台的號碼已被註冊過

症狀:觸發驗證碼後,收到短信內容為「此號碼已註冊」或頁面提示「該號碼無法用於驗證」。

解法:在主流程編排中加入自動換號邏輯。當 wait_for_sms 返回的短信內容包含「已註冊」、「already registered」、「已被佔用」等關鍵詞時,立即調用 release_number 釋放當前號碼並重新獲取新號碼,最多重試 3 次。代碼中已整合此重試機制。

坑四:驗證碼短信延遲超過 60 秒

症狀:wait_for_sms 在 60 秒後拋出 TimeoutError,但此時驗證碼可能仍在路上。

解法:雙保險方案——60 秒超時後,不立即放棄,而是在瀏覽器上點擊「重新發送驗證碼」按鈕,並重新計時 60 秒。同時保留第一次的 activation_id 繼續輪詢(可能舊的短信仍在傳輸中)。代碼中已在主流程中實現此邏輯。


結語:從「流水線工人」變成「一鍵指揮官」

這套流水線的核心價值不在於節省的那幾分鐘——而在於可重複性。測試完成後,你可以保留它作為團隊的測試工具。下次需要註冊新帳號時,只需一條命令,30 秒後憑據已安全入庫。

倫理聲明:本文僅供開發測試與個人學習使用。批量自動化註冊可能違反目標網站的服務條款,使用時請確認你的行為符合各平台規定。保管好你的密碼管理器主密碼——它是你整個自動化基礎設施的最後防線。