CaptchaAI xử lý tính đồng thời cao, nhưng bạn có thể muốn giới hạn chính mình. Lý do: kiểm soát chi phí, tránh các lỗi tăng đột biến ngoài ý muốn, chia sẻ tài nguyên công bằng giữa các nhóm hoặc giới hạn tỷ lệ phù hợp do trang web mục tiêu đặt ra. Hướng dẫn này triển khai ba mẫu giới hạn tốc độ phía máy khách choCaptchaAI.
Tại sao lại giới hạn tỷ lệ phía khách hàng
| Kịch bản | Không giới hạn | Có giới hạn |
|---|---|---|
| Lỗi gây ra vòng lặp giải quyết vô hạn | Đốt cháy qua sự cân bằng | Dừng ở giới hạn được định cấu hình |
| Nhiều nhóm chia sẻ một khóa API | Chi tiêu không đồng bộ | Phân công công bằng cho mỗi đội |
| Trang web mục tiêu bị cấm ở mức > 100 req/min | Tài khoản bị chặn | Ở dưới ngưỡng |
| Ngân sách là $50/month | Có thể vượt quá trong một buổi chiều | Giới hạn cứng được thực thi |
Mẫu 1: Nhóm mã thông báo
Nhóm mã thông báo cho phép bùng nổ trong khi thực thi tốc độ trung bình. Token bổ sung theo tỷ lệ cố định; mỗi yêu cầu tiêu thụ một mã thông báo.
Nhóm mã thông báo Python
# token_bucket_solver.py
import os
import time
import threading
import requests
API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
class TokenBucket:
"""Token bucket rate limiter."""
def __init__(self, rate, capacity):
"""
rate: tokens added per second
capacity: max tokens (burst size)
"""
self.rate = rate
self.capacity = capacity
self.tokens = capacity
self.last_refill = time.monotonic()
self.lock = threading.Lock()
def acquire(self, timeout=30):
"""Wait for a token. Returns True if acquired, False on timeout."""
deadline = time.monotonic() + timeout
while True:
with self.lock:
self._refill()
if self.tokens >= 1:
self.tokens -= 1
return True
if time.monotonic() >= deadline:
return False
time.sleep(0.1)
def _refill(self):
now = time.monotonic()
elapsed = now - self.last_refill
self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
self.last_refill = now
# Allow 10 solves/minute with burst of 5
limiter = TokenBucket(rate=10/60, capacity=5)
def solve_rate_limited(sitekey, pageurl):
"""Solve with rate limiting."""
if not limiter.acquire(timeout=60):
raise Exception("Rate limit: could not acquire token within 60s")
session = requests.Session()
resp = session.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": "1",
})
result = resp.json()
if result.get("status") != 1:
raise Exception(f"Submit failed: {result.get('request')}")
task_id = result["request"]
time.sleep(15)
for _ in range(25):
poll = session.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1",
})
poll_result = poll.json()
if poll_result.get("status") == 1:
return poll_result["request"]
if poll_result.get("request") != "CAPCHA_NOT_READY":
raise Exception(f"Error: {poll_result.get('request')}")
time.sleep(5)
raise Exception("Timeout")
Mẫu 2: Quầy cửa sổ trượt
Theo dõi số lượng yêu cầu trong một khoảng thời gian cố định. Đơn giản hơn nhóm mã thông báo nhưng không có khả năng kiểm soát cụm.
Cửa sổ trượt JavaScript
// sliding_window_solver.js
const axios = require('axios');
const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
class SlidingWindowLimiter {
constructor(maxRequests, windowMs) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.timestamps = [];
}
async acquire(timeoutMs = 60000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
// Remove expired timestamps
const cutoff = Date.now() - this.windowMs;
this.timestamps = this.timestamps.filter(t => t > cutoff);
if (this.timestamps.length < this.maxRequests) {
this.timestamps.push(Date.now());
return true;
}
// Wait until the oldest request exits the window
const waitMs = Math.min(
this.timestamps[0] + this.windowMs - Date.now() + 10,
deadline - Date.now()
);
if (waitMs > 0) await new Promise(r => setTimeout(r, waitMs));
}
return false;
}
}
// Allow 20 solves per 5 minutes
const limiter = new SlidingWindowLimiter(20, 5 * 60 * 1000);
async function solveRateLimited(sitekey, pageurl) {
const acquired = await limiter.acquire(60000);
if (!acquired) throw new Error('Rate limit exceeded');
const submit = await axios.get('https://ocr.captchaai.com/in.php', {
params: {
key: API_KEY, method: 'userrecaptcha',
googlekey: sitekey, pageurl, json: '1',
},
});
if (submit.data.status !== 1) throw new Error(submit.data.request);
await new Promise(r => setTimeout(r, 15000));
for (let i = 0; i < 25; i++) {
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
});
if (poll.data.status === 1) return poll.data.request;
if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
await new Promise(r => setTimeout(r, 5000));
}
throw new Error('Timeout');
}
Mẫu 3: Giới hạn dựa trên ngân sách
Đặt ngân sách chi phí hàng ngày và dừng khi đạt đến:
# budget_limiter.py
import os
import time
from datetime import date
class BudgetLimiter:
"""Limit daily CAPTCHA spending."""
def __init__(self, daily_budget, cost_per_solve=0.003):
self.daily_budget = daily_budget
self.cost_per_solve = cost_per_solve
self.daily_spend = 0.0
self.current_date = date.today()
def can_solve(self):
"""Check if budget allows another solve."""
if date.today() != self.current_date:
self.daily_spend = 0.0
self.current_date = date.today()
return self.daily_spend + self.cost_per_solve <= self.daily_budget
def record_solve(self):
"""Record a successful solve against the budget."""
self.daily_spend += self.cost_per_solve
@property
def remaining_budget(self):
return max(0, self.daily_budget - self.daily_spend)
@property
def remaining_solves(self):
return int(self.remaining_budget / self.cost_per_solve)
# $5/day budget
budget = BudgetLimiter(daily_budget=5.00, cost_per_solve=0.003)
def solve_with_budget(sitekey, pageurl):
if not budget.can_solve():
raise Exception(
f"Daily budget exhausted. Remaining: ${budget.remaining_budget:.2f}"
)
# ... solve logic ...
token = "..." # actual solve
budget.record_solve()
return token
Chọn một mẫu
| mẫu | Tốt nhất cho | Độ phức tạp |
|---|---|---|
| Nhóm mã thông báo | Kiểm soát tốc độ mượt mà với khả năng cho phép bùng nổ | Trung bình |
| Cửa sổ trượt | Số lượng yêu cầu đơn giản trên mỗi khoảng thời gian | Thấp |
| Giới hạn ngân sách | Kiểm soát chi phí mỗi ngày/week/month | Thấp |
| Kết hợp (tỷ lệ + ngân sách) | Hệ thống sản xuất | Trung bình |
Khắc phục sự cố
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| Tất cả các yêu cầu được xếp hàng đợi, không có yêu cầu nào được thực thi | Giá quá thấp so với nhu cầu | Tăng tỷ lệ hoặc kích thước cửa sổ |
| Giới hạn ngân sách được đặt lại vào giữa ngày | Đồng hồ hệ thống thay đổi hoặc khởi động lại | Kiên trì chi tiêu hàng ngày cho tập tin hoặc cơ sở dữ liệu |
| Thùng mã thông báo cạn kiệt đột ngột | Công suất quá nhỏ cho quy trình làm việc | Tăng thông số công suất |
| Bộ giới hạn tốc độ chặn các yêu cầu bỏ phiếu | Giới hạn cũng được áp dụng cho các cuộc thăm dò ý kiến | Chỉ giới hạn gửi yêu cầu, không thăm dò ý kiến |
Câu hỏi thường gặp
Tôi có nên xếp hạng giới hạn yêu cầu gửi hoặc yêu cầu thăm dò ý kiến không?
Chỉ giới hạn tỷ lệ yêu cầu gửi (in.php). Việc bỏ phiếu (res.php) sẽ diễn ra tự do vì nó không tạo ra nhiệm vụ mới hoặc tốn tiền.
Làm cách nào để chia sẻ giới hạn tỷ lệ cho nhiều nhân viên?
Sử dụng giới hạn tốc độ được Redis hỗ trợ. Các thư viện như redis-rate-limiter (Python) hoặc rate-limiter-flexible (Node.js) hỗ trợ giới hạn tốc độ phân tán bằng các hoạt động nguyên tử.
CaptchaAI có thể cho tôi biết tỷ lệ sử dụng hiện tại của tôi không?
Sử dụng điểm cuối số dư để theo dõi chi tiêu. Để sử dụng chi tiết, hãy triển khai bộ đếm của riêng bạn như trong hướng dẫn này.
bài viết liên quan
Các bước tiếp theo
Kiểm soát tỷ lệ và ngân sách giải CAPTCHA của bạn —lấy khóa API CaptchaAI của bạn.
Hướng dẫn liên quan: