一个功能完整的 Node.js 代理池实现,专注于从免费代理网站自动抓取、验证和管理代理 IP。该系统采用模块化设计,提供简单易用的 RESTful API 接口。
- 🔄 自动代理抓取 - 从 free-proxy-list.net 自动抓取免费代理 IP
- ✅ 代理验证 - 通过 httpbin.org/ip 验证代理连通性,确保代理可用
- 🗄️ 内存存储 - 高效的内存代理池,支持随机获取可用代理
- 🌐 RESTful API - 简洁的 HTTP API 接口,支持获取代理和查看状态
- ⏰ 定时刷新 - 每10分钟自动刷新代理池,保持代理的可用性
- 📝 详细日志 - 完整的操作日志,便于监控和调试
npm installnpm start服务将在 http://localhost:3000 启动,并自动开始抓取和验证代理。
# 运行所有测试
npm test
# 测试代理抓取器
npm run test-scraper
# 测试文档完整性
npm run test-docs# 基本使用示例
npm run example-basic
# 客户端使用示例(需要先启动服务)
npm run example-clientGET /proxy响应示例(成功):
{
"success": true,
"data": {
"ip": "192.168.1.1",
"port": 8080,
"protocol": "http",
"country": "US",
"anonymity": "elite"
},
"message": "成功获取代理"
}响应示例(无可用代理):
{
"success": false,
"error": "当前没有可用的代理",
"code": "NO_PROXY_AVAILABLE"
}GET /status响应示例:
{
"success": true,
"data": {
"totalProxies": 15,
"proxies": [
{
"ip": "192.168.1.1",
"port": 8080,
"protocol": "http",
"country": "US",
"addedAt": "2024-01-01T12:00:00.000Z",
"lastUsed": "2024-01-01T12:30:00.000Z"
}
]
},
"message": "成功获取状态信息"
}POST /refresh响应示例:
{
"success": true,
"data": {
"addedProxies": 12,
"totalProxies": 15,
"refreshTime": 8500
},
"message": "代理池刷新完成,添加了 12 个新代理"
}const ProxyPool = require('./proxy-pool');
const ProxyScraper = require('./proxy-scraper');
// 创建代理池
const pool = new ProxyPool({
refreshInterval: 600000, // 10分钟刷新间隔
timeout: 5000 // 请求超时
});
// 添加代理
pool.addProxy({
ip: '192.168.1.1',
port: 8080,
protocol: 'http',
country: 'US'
});
// 获取随机代理
const proxy = pool.getProxy();
if (proxy) {
console.log(`使用代理: ${proxy.ip}:${proxy.port}`);
}
// 启动定时刷新
await pool.start();const scraper = new ProxyScraper({
timeout: 10000,
userAgent: 'Mozilla/5.0...'
});
// 从 free-proxy-list.net 抓取代理
const proxies = await scraper.scrapeFromFreeProxyList();
console.log(`抓取到 ${proxies.length} 个代理`);
// 验证代理
const validProxies = await scraper.validateProxies(proxies);
console.log(`验证通过 ${validProxies.length} 个代理`);
// 添加到代理池
validProxies.forEach((proxy) => {
pool.addProxy(proxy);
});const pool = new ProxyPool({
refreshInterval: 600000, // 刷新间隔(毫秒),默认10分钟
timeout: 5000 // 请求超时(毫秒)
});const scraper = new ProxyScraper({
timeout: 10000, // 请求超时(毫秒)
userAgent: 'Mozilla/5.0...' // 自定义User-Agent
});# 启动服务
npm start
# 查看代理池状态
curl http://localhost:3000/status
# 获取一个可用代理
curl http://localhost:3000/proxy
# 手动刷新代理池
curl -X POST http://localhost:3000/refresh// 获取代理示例
async function getProxy() {
try {
const response = await fetch('http://localhost:3000/proxy');
const result = await response.json();
if (result.success) {
console.log('获取到代理:', result.data);
return result.data;
} else {
console.log('无可用代理:', result.error);
return null;
}
} catch (error) {
console.error('请求失败:', error);
return null;
}
}
// 使用代理发送请求
async function useProxy() {
const proxy = await getProxy();
if (proxy) {
// 使用获取到的代理进行后续请求
console.log(`使用代理 ${proxy.ip}:${proxy.port} 发送请求`);
}
}// 定期检查代理池状态
setInterval(async () => {
try {
const response = await fetch('http://localhost:3000/status');
const result = await response.json();
if (result.success) {
console.log(`当前代理池状态: ${result.data.totalProxies} 个代理`);
// 如果代理数量过少,触发刷新
if (result.data.totalProxies < 5) {
console.log('代理数量不足,触发刷新...');
await fetch('http://localhost:3000/refresh', { method: 'POST' });
}
}
} catch (error) {
console.error('状态检查失败:', error);
}
}, 300000); // 每5分钟检查一次免费代理服务存在以下固有问题,使用前请充分了解:
- 成功率低:通常只有 10-30% 的免费代理能正常工作
- 速度慢:响应时间通常在 2-10 秒,远慢于付费代理
- 不稳定:代理可能随时失效,需要频繁更新
- 带宽限制:大多数免费代理有严格的带宽和并发限制
- 数据泄露:免费代理可能记录或篡改传输的数据
- 恶意代理:部分代理可能用于收集用户信息或进行攻击
- IP 泄露:代理失效时可能暴露真实 IP 地址
- 仅用于测试:建议仅在开发和测试环境中使用
- 避免敏感数据:不要通过免费代理传输敏感信息
- 生产环境:生产环境建议使用付费的专业代理服务
- 定期更新:由于失效率高,需要频繁刷新代理池
- 请求频率控制 - 避免过于频繁的抓取请求,建议间隔至少 1-2 秒
- 并发限制 - 同时使用的代理数量不宜过多,避免被目标网站封禁
- User-Agent 轮换 - 建议定期更换 User-Agent 字符串
- IP 轮换 - 避免长时间使用同一个代理 IP
- 遵守法律法规 - 确保代理使用符合当地法律法规
- 尊重网站规则 - 遵守目标网站的 robots.txt 和使用条款
- 避免滥用 - 不要用于恶意攻击、数据窃取等非法活动
- 商业使用 - 商业用途请确保获得适当的授权
症状:无法从 free-proxy-list.net 获取代理列表
可能原因:
- 网络连接问题
- 目标网站被防火墙阻止
- 网站结构发生变化
- 请求被反爬虫系统拦截
解决方案:
# 检查网络连接
curl -I https://free-proxy-list.net/
# 检查 DNS 解析
nslookup free-proxy-list.net
# 尝试使用不同的 User-Agent
# 修改 proxy-scraper.js 中的 userAgent 配置症状:抓取到代理但验证通过率很低(< 10%)
可能原因:
- 免费代理质量本身较差
- 验证超时时间设置过短
- httpbin.org 服务不稳定
解决方案:
// 调整验证超时时间
const scraper = new ProxyScraper({
timeout: 15000 // 增加到 15 秒
});
// 或者更换验证服务
// 在 validateProxy 方法中使用其他验证 URL症状:运行 npm start 时出现错误
可能原因:
- 端口被占用
- 依赖包未正确安装
- Node.js 版本不兼容
解决方案:
# 检查端口占用
lsof -i :3000
# 重新安装依赖
rm -rf node_modules package-lock.json
npm install
# 检查 Node.js 版本(建议 14.0+)
node --version症状:长时间运行后内存占用持续增长
可能原因:
- 代理池未正确清理
- 定时器未正确释放
- 内存泄漏
解决方案:
// 定期清理代理池
setInterval(() => {
if (pool.proxies.length > 100) {
pool.clear();
}
}, 3600000); // 每小时检查一次
// 确保正确停止服务
process.on('SIGINT', () => {
pool.stop(); // 停止定时器
process.exit(0);
});// 在环境变量中设置调试级别
process.env.DEBUG = 'proxy-pool:*';
// 或者修改代码增加更多日志输出
console.log('调试信息:', debugInfo);# 定期检查代理池状态
watch -n 30 'curl -s http://localhost:3000/status | jq'
# 监控系统资源使用
top -p $(pgrep -f "node.*proxy")// 手动测试特定代理
const scraper = new ProxyScraper();
const isValid = await scraper.validateProxy({
ip: '192.168.1.1',
port: 8080,
protocol: 'http'
});
console.log('代理是否可用:', isValid);- 批量验证优化:减少并发验证数量,避免过载
- 缓存机制:对验证结果进行短期缓存
- 智能刷新:根据代理池状态动态调整刷新频率
- 资源监控:定期监控内存和 CPU 使用情况
MIT License