如果您向同一个网站发送数百个请求,单个代理 IP 很快就会被标记。轮换代理将您的流量分散到多个 IP 上,使目标网站看到的是许多不同的访问者。在 Axios Node.js 项目中构建代理池需要一个池类和一些死代理处理机制。
以下是一个用于追踪失效代理的简易轮询池:
class ProxyPool {
constructor(proxies) {
this.proxies = proxies.map(p => ({ ...p, alive: true }));
this.index = 0;
}
next() {
const alive = this.proxies.filter(p => p.alive);
if (!alive.length) throw new Error('All proxies dead');
const proxy = alive[this.index % alive.length];
this.index++;
return { host: proxy.host, port: proxy.port, auth: proxy.auth };
}
markDead(host, port) {
const p = this.proxies.find(
px => px.host === host && px.port === port
);
if (p) p.alive = false;
}
}
在 Axios 中使用该池如下所示:
const pool = new ProxyPool([
{ host: '1.2.3.4', port: 8080, auth: { username: 'u1', password: 'p1' } },
{ host: '5.6.7.8', port: 8080, auth: { username: 'u2', password: 'p2' } },
{ host: '9.10.11.12', port: 3128 }
]);
async function fetchWithRotation(url) {
const proxy = pool.next();
try {
const res = await axios.get(url, { proxy, timeout: 10000 });
return res.data;
} catch (err) {
pool.markDead(proxy.host, proxy.port);
return fetchWithRotation(url); // retry with next proxy
}
}
设置 timeout (单位为毫秒)至关重要。部分代理会无限期卡死而非返回错误,若未设置超时,脚本将陷入停滞。对于大多数爬取任务,10 秒是一个合理的起始值。若想进一步了解如何避免爬取过程中被封锁,建议查阅防止 IP 被封的技巧。