从零构建高*能代理IP池:一个10万级免费代理采集-验证-分发的完整架构
演示站点:支付系统专用代理IP – YY/腾讯/网易/畅游专属网关 – 高匿HTTP/SOCKS5代理池 | httpip.pay66.cn
本文介绍如何用 PHP + SQLite 从零搭建一个日均稳定产出 4000+ 可用代理的免费IP池系统,涵盖全网采集、并发验证、质量分类、网关探测、API分发、SEO落地页等完整流程。
一、背景与设计目标
代理IP池是很多网络应用的基础设施。市面上的收费代理服务价格不菲,而互联网上其实散落着大量免费代理——只要有一*高效的自动化采集+验证+分发流水线,就能持续获得可用的免费代理。
设计目标:
全自动:Cron 定时调度,零人工*预
高吞吐:每小时采集→验证数万代理,可用池维持在千级规模
质量可控:不只测连通*,还要识别 WiFi 认证热点、广告注入、中间人劫持等低质量代理
多协议:HTTP / HTTPS / SOCKS4 / SOCKS5 全覆盖
可分发:提供 RESTful API,支持多格式输出,分免费/付费用户权限
二、整体架构
系统由四个核心模块组成一个闭环流水线:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 全网采集 │───▶│ 并发验证 │───▶│ 网关探测 │───▶│ API分发 │
│ (Fetcher)│ │ (Checker)│ │(GW Probe)│ │ + 前端 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │
└───────────────┴───────────────┴───────────────┘
│
SQLite(WAL)
一键获取完整项目代码
技术栈:PHP 8.1 + SQLite(WAL模式)+ pcntl_fork 多进程 + curl_multi 并发IO
三、采集模块:全网撒网 + 智能解析
3.1 双源采集策略
代理来源分为两大类:
(1)Raw List 源(*60+个)
GitHub 上的每日/每小时更新代理列表,纯 ip:port 文本格式,解析速度极快。通过 GitHub 的 raw 地址或 jsDelivr CDN 加速国内访问。
核心代码——正则提取即可:
// 从 ip:port 文本中提取代理
private function fromRawList(string $url, string $protocol): array
{
[$body] = pp_http_get($url, 15);
$out = [];
if (preg_match_all(‘/(\d{1,3}(?:\.\d{1,3}){3}):(\d{1,5})/’, $body, $m, PREG_SET_ORDER)) {
foreach ($m as $hit) {
$out[] = [‘ip’ => $hit[1], ‘port’ => (int)$hit[2], ‘protocol’ => $protocol];
}
}
return $out;
}
一键获取完整项目代码
(2)Site 源(网页表格型代理站)
网页表格型代理站(如 kuaidaili、89ip、ip3366 等)的页面结构各异、列顺序不统一。写死每个站的解析规则维护成本太高,这里采用了内容驱动解析:
// 通用内容驱动行解析:自动识别 IP/端口/协议/匿名度/地区
private function parseRow(array $tds): ?array
{
$ip = null; $port = null; $proto = ‘http’;
foreach ($tds as $c) {
$c = trim($c);
if ($ip === null && filter_var($c, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$ip = $c;
} elseif ($port === null && ctype_digit($c) && $c > 0 && $c <= 65535) {
$port = (int)$c;
} elseif (preg_match('/https/i', $c)) {
$proto = 'https';
} elseif (preg_match('/高匿|匿名|透明|elite|anonymous|transparent/i', $c, $m)) {
$anon = $this->mapAnonymity($m[0]);
}
}
return ($ip && $port) ? [‘ip’ => $ip, ‘port’ => $port, ‘protocol’ => $proto] : null;
}
一键获取完整项目代码
这种思路的核心是:不依赖列顺序,而是根据单元格内容特征来判断它是什么。比如遇到合法的 IPv4 地址就是 IP、遇到纯数字 1-65535 就是端口。对 GBK 编码的站点也自动转码:
if ($encoding && function_exis*(‘mb_convert_encoding’)) {
$html = @mb_convert_encoding($html, ‘UTF-8’, $encoding);
}
一键获取完整项目代码
3.2 并发采集 + 去重入库
Raw 源多达 60+ 个,串行采集太慢。使用 curl_multi 分批并发拉取:
public function runRawLis*Concurrent(int $concurrency = 30, int $timeout = 15): array
{
foreach (array_chunk($items, $concurrency) as $chunk) {
$mh = curl_multi_init();
foreach ($chunk as $j => $item) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $item[‘url’],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
// …
]);
curl_multi_add_handle($mh, $ch);
}
// 并行执行
do { curl_multi_exec($mh, $running); curl_multi_select($mh, 1.0); }
while ($running);
// 解析 + 入库
foreach ($chunk as $j => $item) {
$body = curl_multi_getcontent($handles[$j]);
// … 正则提取 ip:port …
}
}
}
一键获取完整项目代码
入库使用 ON CONFLICT(ip, port) DO UPDATE 实现去重 Upert,重复代理只更新 updated_at,不重置 last_check(避免已验可用的代理被重复验证)。
关键优化:单源封顶。有些大源一次*吐出 10 万+ 条记录,不加限制会导致数据库膨胀和验证预算被少数源头垄断。设置 max_per_source = 120000 可容纳绝大多数源的全量,同时防止极端情况。
3.3 源质量加权调度
不是所有源的质量都一样。系统会记录每个采集源的验证通过率,按通过率动态调整轮转频率:
// 从历史通过率推导轮转权重(1~5 档)
private function weightFor(string $name): int
{
$rate = $pass / $total; // 通过率通常 1~7%
return max(1, min(5, (int)round(1 + $rate * 40)));
}
// taskList() 中按权重展开:通过率高的源在轮转**现更多次
一键获取完整项目代码
四、验证模块:并发检测 + 多维度质量判定
这是整个系统的核心。免费代理鱼龙混杂,仅测连通*远远不够。
4.1 多进程并行架构
使用 pcntl_fork 实现多进程并行验证,每个 worker 独立 curl_multi:
父进程 fork ──▶ worker[0] curl_multi (分片 id%4=0)
├──▶ worker[1] curl_multi (分片 id%4=1)
├──▶ worker[2] curl_multi (分片 id%4=2)
└──▶ worker[3] curl_multi (分片 id%4=3)
一键获取完整项目代码
分片取数据通过 SQL 取模实现,各 worker 互不重叠:
SELECT * FROM proxy_ips
WHERE (last_check = 0 OR last_check < :threshold)
AND (id % :shards) = :shard
ORDER BY last_check ASC
LIMIT :limit
一键获取完整项目代码
验证结果按批(1000条/批)用事务批量提交,减少 SQLite 写锁竞争:
$pdo->exec(‘BEGIN IMMEDIATE’);
foreach ($chunk as $i => $row) {
Repository::updateCheck($id, $result);
}
$pdo->exec(‘COMMIT’);
一键获取完整项目代码
4.2 两阶段探针
验证阶段不仅做连通*探测,还额外发起 HTTPS 质量探针:
阶段 探针地址 检测内容
连通*探测 自托管 echo 端点 HTTP 可达 + 响应 JSON 完整* + 匿名度分析
质量探测 自托管 HTTPS 端点 隧道*净度(是否有注入/劫持/认证页)
4.3 7类质量分级
根据两阶段探针结果,将代理分为以下质量等级:
质量等级 触发条件 是否下架
clean 双探针正常 否
captive 返回 WiFi 认证/登录页面 是
mitm SSL 证书异常(中间人劫持) 是
ad_injected 响应中检测到广告脚本注入 是
tampered 响应内容被篡改(非预期JSON) 是
risk_control 返回验证码/滑块/*控拦截页 是
https_unreachable HTTPS 隧道不支持但 HTTP 正常 否(保留为HTTP可用)
判定代码示例:
// 质量探针返回 200 + 合法 JSON → *净
if ($qCode === 200 && $qBody !== ”) {
$qJson = json_decode($qBody, true);
if (is_array($qJson)) {
return [1, $anonymity, $score, ‘clean’, ”];
}
// 200 但非 JSON:检查篡改类型
if ($this->matchAny($captiveRe, $qBody)) {
return [0, $anonymity, 0, ‘captive’, ‘疑似WiFi热点代理’];
}
if ($this->matchAny($adRe, $qBody)) {
return [0, $anonymity, 0, ‘ad_injected’, ‘HTTPS响应被注入广告脚本’];
}
}
一键获取完整项目代码
4.4 软失败机制
一个关键设计:已被标记为”可用”的代理,单次复检失败不会立即剔除。只有连续失败次数达到阈值(max_fail = 8)才降级。这避免了网络抖动导致可用池大面积萎缩:
// 软失败保护
$wasAlive = ($row[‘status’] === 1);
$down = !$wasAlive || $newFail >= $maxFail;
Repository::updateCheck($id, [
‘status’ => $down ? 0 : 1, // 可用代理不轻易下架
‘fail_count’ => $newFail, // 累计失败计数
]);
一键获取完整项目代码
4.5 匿名度判定
通过自托管 echo 端点返回的请求头信息,分析代理的匿名程度:
private function judgeAnonymity($json, string $proxyIp): string
{
$headers = array_change_key_case($json[‘headers’], CASE_LOWER);
$forwardKeys = [‘x-forwarded-for’, ‘via’, ‘proxy-connection’, ‘x-real-ip’, ‘client-ip’];
$hasForward = false;
foreach ($forwardKeys as $k) {
if (isset($headers[$k])) { $hasForward = true; break; }
}
if (strpos($origin, ‘,’) !== false) return ‘transparent’; // 透明代理:**多级IP
if ($hasForward) return ‘anonymous’; // 匿名代理:透传了代理头
return ‘elite’; // 高匿代理:完全不**
}
一键获取完整项目代码
五、网关探测:专项可达*验证
采集和连通*验证回答的是”这个代理能不能上网”,但实际业务场景往往需要回答”这个代理能不能访问特定目标站点”。
5.1 架构设计
通过配置化网关列表,可任意扩展检测目标:
‘gateways’ => [
‘yy’ => [
‘label’ => ‘YY’,
‘url’ => ‘https://api-turnover.example.com/’,
‘expect_code’ => 200,
‘timeout’ => 8,
‘vendor’ => true, // 厂商网关:计入优质判定
],
‘google’ => [
‘label’ => ‘谷歌’,
‘url’ => ‘https://www.google.com/’,
‘expect_code’ => 200,
‘expect_contains’ => ‘Google’,
‘vendor’ => false, // 非厂商网关:不参与优质判定
],
// … 更多网关 …
]
一键获取完整项目代码
vendor=true 的网关参与 premium(优质代理)判定:至少通过 N 个厂商网关检测才算优质代理。
5.2 并发网关探测
对当前可用代理逐个走代理访问各网关:
public function probeGateway(array $targe*, string $url, int $expectCode, string $expectContains, int $timeout): array
{
$mh = curl_multi_init();
foreach ($targe* as $i => $row) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_PROXY => $row[‘ip’] . ‘:’ . $row[‘port’],
CURLOPT_PROXYTYPE => $this->proxyType($row[‘protocol’]),
// …
]);
curl_multi_add_handle($mh, $ch);
}
// curl_multi 并发执行
// 判定:状态码匹配 && 内容包含期望字符串 → 可达
}
一键获取完整项目代码
探测结果写回每个代理的 {gw}_ok 字段,支持多网关交叉筛选。
六、调度系统:全自动四阶段流水线
总任务由 Shell 脚本调度,宝塔面板的「计划任务」功能每 20 分钟触发一次。
6.1 四阶段流程
阶段1 清死链瘦身
├── 删除已确认失效的代理(fail_count >= max_fail)
├── 清除失效代理的网关可用标记
└── 纯净兜底(按质量等级下架低质代理)
阶段2 全网采集(预算 120s)
├── 并发拉取 60+ 个 raw_lis*(curl_multi, 30并发, 15s超时)
└── 串行采集网页表格站(预算用尽即停)
阶段3 并行验证(预算 600s)
├── pcntl_fork → 2 workers
├── 每个 worker curl_multi(100并发)
├── 分片取数据(id % 2 互不重叠)
└── 批量事务回写 + 源权重更新
阶段4 网关探测 + 生成文件
├── 对所有可用代理做厂商网关可达*检测
├── 生成静态导出文件({gw}_ok.txt)
└── 生成 SEO 落地页
一键获取完整项目代码
6.2 并发安全
# flock 文件锁:防止 cron 重叠执行
exec 9>”$LOCK”
if ! flock -n 9; then
echo “已有实例在运行,本次跳过”
exit 0
fi
# 暂停开关:后台可随时暂停调度
STOP=”$BASE/data/stop_master.flag”
check_stop() {
if [ -f “$STOP” ]; then
echo “总任务已暂停,本次跳过”
exit 0
fi
}
一键获取完整项目代码
6.3 配置摘要
参数 值 说明
VERIFY_BUDGET 600s 验证阶段时间预算
FETCH_BUDGET 120s 采集阶段时间预算
workers 2 验证并行进程数(4核4G建议2个)
concurrency 100 每worker的curl并发数
max_fail 8 连续失败阈值
recheck_after 1800s 距上次检测超过30分钟才复检
七、数据库设计
7.1 表结构
CREATE TABLE proxy_ips (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip TEXT NOT NULL,
port INTEGER NOT NULL,
protocol TEXT DEFAULT ‘http’, — http/https/socks4/socks5
anonymity TEXT DEFAULT ”, — elite/anonymous/transparent
region TEXT DEFAULT ”, — 地区(离线IP库查询)
isp TEXT DEFAULT ”, — 运营商
country TEXT DEFAULT ”, — 国家
speed INTEGER DEFAULT -1, — 响应时间(ms)
score INTEGER DEFAULT 0, — 质量评分(0-100)
status INTEGER DEFAULT 0, — 0待检/1可用/-1失效
fail_count INTEGER DEFAULT 0, — 连续失败计数
source TEXT DEFAULT ”, — 采集来源
last_check INTEGER DEFAULT 0, — 最后验证时间戳
created_at INTEGER DEFAULT 0,
updated_at INTEGER DEFAULT 0,
— 网关可用标记(自动按配置迁移加列)
yy_ok INTEGER DEFAULT 0,
tx_ok INTEGER DEFAULT 0,
wy_ok INTEGER DEFAULT 0,
cy_ok INTEGER DEFAULT 0,
— 低质量判定
quality TEXT DEFAULT ”, — clean/captive/mitm/ad_injected/tampered/risk_control/dead
quality_note TEXT DEFAULT ” — 详细原因
);
CREATE UNIQUE INDEX uniq_ipport ON proxy_ips(ip, port);
CREATE INDEX idx_status_score ON proxy_ips(status, score);
一键获取完整项目代码
7.2 关键优化
WAL 模式:SQLite 默认的 rollback journal 不支持并发读写,改为 WAL(Write-Ahead Logging)后,读和写可以同时进行。
busy_timeout = 30000ms:多进程并行验证时,写锁冲突不再立即报错,而是等待最多 30 秒。
定期 checkpoint:验证完成后执行 PRAGMA wal_checkpoint(TRUNCATE) 强制合并 WAL,确保数据全部落盘。
自动迁移:通过 PRAGMA table_info 检测现有列,按配置自动添加缺失列(如新加的网关标记列),做到零停机升级。
八、API 与分发
8.1 输出格式
API 支持四种输出格式:
格式 参数 示例输出
JSON format=json [{“ip”:”1.2.3.4″,”port”:8080,”protocol”:”http”,…}]
TXT format=txt 1.2.3.4:8080
TXTP format=txtp http://1.2.3.4:8080
CSV format=csv ip,port,protocol,…
8.2 筛选参数
API 支持丰富的筛选维度:
protocol=http / https / socks4 / socks5 — 协议筛选
anonymity=elite / anonymous / transparent — 匿名度筛选
gw=yy,tx — 按网关可用*筛选(支持多选,gw_mode=all/any)
cn=cn / foreign — 国内外筛选
country=中国 — 按国家筛选
keyword=北京 — IP/地区/运营商关键词搜索
min_speed=100&max_speed=3000 — 速度区间
sort=speed / score / random — 排序方式
8.3 用户权限分级
通过用户系统实现免费/付费分层,每人自动生成专属 API KEY:
匿名用户:单次最多返回 N 条,不累计
免费用户:每请求最多 N 条,每天累计上限
付费用户:无上限,可全量提取
限速使用文件锁方案,SQLite 零依赖:
function apiRateAllow(array $cfg, string $ip): bool
{
$file = $dir . ‘/’ . preg_replace(‘/[^A-Za-z0-9._-]/’, ‘_’, $ip) . ‘.json’;
$fp = fopen($file, ‘c+’);
flock($fp, LOCK_EX);
// 原子读写计数
$data = json_decode(stream_get_conten*($fp), true) ?: [];
if ($data[‘exp’] < time()) {
$data = ['exp' => time() + $window, ‘cnt’ => 0];
}
$data[‘cnt’]++;
$allowed = $data[‘cnt’] <= $max;
ftruncate($fp, 0); fseek($fp, 0);
fwrite($fp, json_encode($data));
flock($fp, LOCK_UN); fclose($fp);
return $allowed;
}
一键获取完整项目代码
九、离线IP地理定*
集成 ip2region 离线IP数据库,入库时自动补充代理的地区、运营商、国家信息,不依赖任何在线API:
public static function geoIp(string $ip): array
{
$info = self::$geoDb->searchInfo($ip);
$raw = self::$geoDb->search($ip);
// 库格式: 国家|省|市|运营商|国家码
$par* = explode(‘|’, $raw);
// 运营商兜底:国外ISP关键词库不覆盖,从raw倒数第二段补取
// 国家名中文化:100+国家英文名→中文名映*
return [‘region’ => $region, ‘isp’ => $isp, ‘country’ => $country];
}
一键获取完整项目代码
十、落地页SEO体系
系统自动生成了多*独立的 HTML 落地页,每页带完整的 SEO meta标签、结构化数据(JSON-LD BreadcrumbList + WebPage)、内链交叉引用:
网关落地页(如 gw/yy.html):展示某网关可用的代理列表
场景落地页(如 lp/http_elite.html):按协议+匿名度组合展示
每个落地页包含:
规范的 title / description / keywords
Open Graph 标签
canonical 链接
结构化数据(BreadcrumbList + WebPage)
实时可用代理表格
内链网络(交叉推荐其他网关/场景页)
十一、实战效果
在 4核4G 的 Linux 服务器上持续运行一个月的表现:
指标 数值
数据库规模 * 13 万条记录
稳定可用池 4000~5000 个
日均系统吞吐 验 3~5 万次
通过率 1.4%~2%(免费代理真实存活率)
协议覆盖 HTTP / HTTPS / SOCKS4 / SOCKS5
网关覆盖 YY / 腾讯 / 网易 / 畅游 / 百度 / 谷歌
数据库体积 ~22 MB
单轮总任务耗时 ~10~15 分钟
十二、总结
这个系统的核心设计思路:
采集端广撒网:60+个源、双通道(raw+site)、并发拉取,最大化新鲜代理的入口量
验证端高质量:连通*+HTTPS隧道质量双探针,7级质量分类,*准剔除低质代理
调度端全自动:flock防并发、预算控制、暂停开关、cron_state 状态追踪
分发端灵活:多格式API、多维度筛选、用户分级权限
存储端轻量化:SQLite + WAL,零外部依赖,22MB跑*
关键技术点回顾:
curl_multi 并发IO是吞吐量的核心(比串行快 10~20 倍)
pcntl_fork 多进程是扩展*的关键(2 workers 就翻倍吞吐)
WAL + busy_timeout 是多进程写入安全的基础
软失败机制是可用池稳定的保障(可用代理不因网络抖动被误杀)
内容驱动解析是降低维护成本的关键(不需要为每个站写专属爬虫)

本文仅讨论技术架构与实现思路,不含任何商业推广内容。代码中的具体URL、配置参数均仅为示例。
————————————————
评论(0)
暂无评论