Xây dựng proxy pool tự động xoay IP với Redis và RoProxy cho scraping quy mô lớn
16 tháng 8, 2026
Tổng quan
Khi scraping quy mô lớn, một địa chỉ IP đơn lẻ nhanh chóng bị chặn do rate limit hoặc cơ chế anti‑bot. Proxy pool tự động xoay IP giải quyết vấn đề này bằng cách duy trì một tập hợp proxy sống, kiểm tra độ trễ liên tục và cấp proxy phù hợp cho mỗi request.
Kiến trúc tổng quan
- RoProxy API – cung cấp residential, mobile, ISP proxy với endpoint lấy danh sách và tham số sticky.
- Redis – lưu trữ proxy dưới dạng sorted set
proxy_poolvới score là độ trễ (ms). - Health‑check worker – chạy định kỳ, test mỗi proxy qua URL
http://httpbin.org/ip, cập nhật score hoặc xóa proxy chết. - Proxy client wrapper – hàm
get_proxy()trả về proxy có score thấp nhất (nhanh nhất) hoặc round‑robin. - Scraper – Python
aiohttphoặc Node.jsaxiosgọi wrapper trước mỗi request.
Bước 1: Lấy danh sách proxy từ RoProxy
curl -s 'https://api.roproxy.com/v1/proxies?type=residential&count=200' -H 'Authorization: Bearer YOUR_API_KEY' > proxies.json
File proxies.json chứa mảng đối tượng {ip, port, username, password, country}.
Bước 2: Nạp proxy vào Redis
import redis, json
r = redis.Redis(decode_responses=True)
with open('proxies.json') as f:
data = json.load(f)
for p in data:
proxy = '{}:{}@{}:{}'.format(p['username'], p['password'], p['ip'], p['port'])
# score ban đầu 0, sẽ được cập nhật sau health‑check
r.zadd('proxy_pool', {proxy: 0})
Bước 3: Worker kiểm tra sức khỏe (health‑check)
import asyncio, aiohttp, redis, time
r = redis.Redis(decode_responses=True)
TEST_URL = 'http://httpbin.org/ip'
async def check_proxy(proxy):
url = f'http://{proxy}'
start = time.perf_counter()
try:
async with aiohttp.ClientSession() as sess:
async with sess.get(TEST_URL, proxy=url, timeout=5) as resp:
if resp.status == 200:
latency = int((time.perf_counter() - start) * 1000)
r.zadd('proxy_pool', {proxy: latency})
return
except Exception:
pass
# proxy thất bại -> xóa
r.zrem('proxy_pool', proxy)
async def run_checks():
proxies = r.zrange('proxy_pool', 0, -1)
tasks = [check_proxy(p) for p in proxies]
await asyncio.gather(*tasks)
# Chạy mỗi 5 phút
while True:
asyncio.run(run_checks())
await asyncio.sleep(300)
Bước 4: Wrapper lấy proxy tối ưu
def get_proxy():
# Lấy 10 proxy nhanh nhất
top = r.zrange('proxy_pool', 0, 9, withscores=True)
if not top:
raise RuntimeError('Không có proxy khả dụng')
# Chọn ngẫu nhiên trong top 10 để phân tán tải
import random
proxy, _ = random.choice(top)
return proxy
Bước 5: Tích hợp vào scraper
Python (aiohttp)
async def fetch(session, url):
proxy = get_proxy()
async with session.get(url, proxy=f'http://{proxy}') as resp:
return await resp.text()
async def main():
async with aiohttp.ClientSession() as sess:
html = await fetch(sess, 'https://example.com')
print(html[:200])
Node.js (axios)
const axios = require('axios');
const redis = require('redis');
const client = redis.createClient();
await client.connect();
async function getProxy() {
const top = await client.zRange('proxy_pool', 0, 9, { WITHSCORES: true });
if (!top.length) throw new Error('Không có proxy');
const idx = Math.floor(Math.random() * top.length / 2) * 2;
return top[idx]; // proxy string
}
async function fetch(url) {
const proxy = await getProxy();
const res = await axios.get(url, {
proxy: { host: proxy.split('@')[1].split(':')[0], port: Number(proxy.split('@')[1].split(':')[1]), auth: { username: proxy.split('@')[0].split(':')[0], password: proxy.split('@')[0].split(':')[1] } }
});
return res.data;
}
Bước 6: Sticky session khi cần giữ IP
Một số tác vụ (đăng nhập, giỏ hàng) yêu cầu IP cố định trong vài phút. RoProxy hỗ trợ tham số session_id. Chỉ cần thêm header X-RoProxy-Session: <id> khi gọi API lấy proxy, hoặc sử dụng endpoint /v1/proxies?sticky=true&session_id=abc123. Wrapper có thể nhận tham số sticky=True và lưu session ID trong Redis với TTL 10 phút.
Mẹo tối ưu và troubleshooting
- Giới hạn kết nối: đặt
max_connectionstrongaiohttp.TCPConnectorđể tránh quá tải proxy. - Retry logic: dùng
tenacity(Python) hoặcaxios-retry(Node) với back‑off exponent. - Geo‑targeting: lưu thêm field
countrytrong Redis hashproxy_meta:{proxy}để lọc theo khu vực. - Monitoring: xuất metric
proxy_pool_size,avg_latencyra Prometheus/Grafana. - Xử lý lỗi 403/429: khi nhận mã này, gọi
r.zincrby('proxy_pool', 5000, proxy)để tăng latency ảo, buộc worker kiểm tra lại sớm.
Kết luận
Với một proxy pool tự động xoay IP được xây dựng trên Redis và RoProxy, bạn có thể mở rộng scraping từ vài trăm request/ngày lên hàng triệu mà không lo bị chặn. Quy trình health‑check liên tục đảm bảo chỉ proxy khỏe được sử dụng, wrapper đơn giản giúp tích hợp vào bất kỳ stack nào (Python, Node, Go). Hãy thử triển khai ngay hôm nay và quan sát độ thành công request tăng vọt.