拿到一批IP,先别急着往程序里塞
先说个真事。上个月帮朋友跑一个数据采集脚本,两百多条IP直接灌进去,半小时卡死三回,排查半天才发现,里面三分之一是连不通的死IP,每次请求都要干等超时才肯罢休。从那以后我养成了习惯:IP到手先体检,体检合格再进业务。
检测这件事说穿了就四个维度,每个维度都有一条能落地的及格线:
| 检测维度 | 看什么 | 我的及格线 |
|---|---|---|
| 连通性 | 超时时间内能否返回正常状态码 | 5秒内有响应 |
| 延迟 | 从发出请求到收到回复的耗时 | 1秒以内,超2秒慎用 |
| 匿名度 | 请求头里有没有带出真实信息 | 高匿优先 |
| 稳定性 | 同一条IP连测10次能成功几次 | 成功8次以上 |
这四项里,连通性和延迟用几行代码就能测出来;匿名度和稳定性多写十几行也不复杂。下面从最简单的开始,一步步搭出一个能跑的检测脚本。
单条IP怎么测:requests 加一个 proxies 参数
Python 里最省事的方案就是 requests。它原生支持代理,请求时多传一个 proxies 参数,流量就会从指定的IP走。检测逻辑很朴素:请求一个稳定的回显接口,能在超时时间内拿到正常响应,这条IP就算活着。
import time
import requests
def check_one(ip, port, timeout=5):
"""检测单条代理IP,返回 (是否可用, 延迟秒数)"""
proxies = {
"http": f"http://{ip}:{port}",
"https": f"http://{ip}:{port}",
}
start = time.time()
try:
resp = requests.get("http://httpbin.org/ip",
proxies=proxies, timeout=timeout)
cost = round(time.time() - start, 2)
if resp.status_code == 200 and "origin" in resp.json():
return True, cost
except Exception:
pass
return False, None
ok, cost = check_one("123.45.67.89", 8080)
print(f"是否可用: {ok},延迟: {cost}秒")
三个细节值得留意:
一是 timeout 必须设。不设的话,一条半死不活的IP能把整个程序挂住,你见过的"跑着跑着卡死"多半就是这个原因。5秒是个稳妥的起点,追求速度可以收紧到3秒。
二是顺手记耗时。同样能通,800毫秒和4秒的体验差着一个天上一个地下,用 time 包一下就能拿到,后面排序全靠它。
三是核对回显内容。接口返回的 origin 字段就是这条链路的出口地址,拿它和你手里的IP对一下,对不上说明线路有问题,直接淘汰。
一次测几百条:开多线程跑并发
单条测通了,接下来才是正题——手上几百上千条,串着一条条测,等到天黑也跑不完。检测是典型的"等网络"型任务,CPU 大部分时间在闲着,多线程正合适,Python 标准库里的 ThreadPoolExecutor 几行就能用上。
import csv
import time
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
def check_one(ip, port, timeout=5):
proxies = {"http": f"http://{ip}:{port}",
"https": f"http://{ip}:{port}"}
start = time.time()
try:
resp = requests.get("http://httpbin.org/ip",
proxies=proxies, timeout=timeout)
if resp.status_code == 200:
return True, round(time.time() - start, 2)
except Exception:
pass
return False, None
def batch_check(proxy_list, workers=30):
results = []
with ThreadPoolExecutor(max_workers=workers) as pool:
tasks = {pool.submit(check_one, ip, port): (ip, port)
for ip, port in proxy_list}
for task in as_completed(tasks):
ip, port = tasks[task]
ok, cost = task.result()
results.append({"ip": ip, "port": port,
"可用": ok, "延迟": cost})
return results
# 从 proxies.txt 读取,每行一条 ip:端口
proxy_list = []
with open("proxies.txt", encoding="utf-8") as f:
for line in f:
line = line.strip()
if ":" in line:
ip, port = line.rsplit(":", 1)
proxy_list.append((ip, int(port)))
results = batch_check(proxy_list, workers=30)
results.sort(key=lambda x: (not x["可用"], x["延迟"] or 99))
with open("result.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["ip", "port", "可用", "延迟"])
writer.writeheader()
writer.writerows(results)
alive = sum(1 for r in results if r["可用"])
print(f"共 {len(results)} 条,可用 {alive} 条,"
f"可用率 {alive / len(results):.0%}")
跑完打开 result.csv,就是一张现成的体检报告:可用的排前面,按延迟从快到慢排好序,业务那边从表头往下取就行。
并发数别一上来就拉满。30 个线程是稳妥的起点,普通家用宽带完全扛得住;先跑一轮看看超时比例,异常偏多就把并发降到 15 再观察,分清是本机带宽撑不住,还是IP本身质量差。
能连上不等于能用:匿名度也查一遍
有些IP能通、延迟也漂亮,用起来却出问题——因为它在请求头里把你的真实地址带出去了。代理按隐藏程度分三档:透明代理直接暴露你的真实地址,等于白用;普通匿名让对方知道你在用代理,但看不到真实地址;高匿则两边都看不出来。检测办法是请求一个回显接口,看返回的 headers:
def check_anonymity(ip, port):
proxies = {"http": f"http://{ip}:{port}"}
try:
resp = requests.get("http://httpbin.org/get",
proxies=proxies, timeout=5)
headers = resp.json().get("headers", {})
if "X-Forwarded-For" in headers or "Via" in headers:
return "普通匿名"
return "高匿名"
except Exception:
return "连接失败"
实际用的时候,建议把这一步并进上一节的并发脚本,每条IP测完顺手打上匿名等级的标签,筛可用池时直接按"高匿"过滤,省得事后返工。
检测完的IP怎么管:搭一个自己的可用池
脚本有了,最后聊聊怎么让检测结果持续产生价值,几个实操建议:
定时复检。IP 是有寿命的,动态IP尤其如此,几小时前测通的现在可能已经下线。写个定时任务,每隔一两个小时把池子整体过一遍,及时清掉失效的。
按延迟排队。把检测结果里的延迟当排序依据,快的排前面,业务取IP时优先拿头部,慢的留作备用。
失败别急着判死刑。偶发超时可能只是网络抖动,连续失败两次再剔除,能避免误杀一批其实还不错的IP。
用前现测。如果你用的IP时效本来就短——比如神龙IP的动态高级套餐,时效最短2小时、最长360小时,背后是日更200万+的IP资源——那正确的姿势是取出来先过一遍检测脚本再进业务,随取随测,不囤积。顺带一提,这类30ms级响应的线路质量普遍扎实,脚本里的超时可以放心收紧到3秒,整轮跑得更快。
常见问题
Q: 检测通过的IP,过几个小时还能用吗?
不一定。动态IP本身有时效,几小时前测通的现在可能已经下线。稳妥的做法是业务取用前再跑一次单条检测,也就几百毫秒的事。
Q: 并发数开多大合适?
从 20 到 30 起步。检测本身很轻,主要吃网络,普通宽带开到 50 也没问题;如果超时明显变多,先降并发再排查别的,别急着怀疑IP质量。
Q: 为什么有的IP能连上,返回的内容却不对?
常见两种情况:一是这条IP的实际出口地区和标注的不一致,回显接口里能看到真实出口,对一下就露馅;二是目标站返回了验证页或空内容。所以除了看状态码,最好再校验返回内容里的关键字段。
Q: 检测用的目标网址怎么选?
优先选和业务目标一致的站点,测出来的延迟才有参考价值。没有的话,用稳定的回显接口(比如 httpbin.org)看连通性,再抽样几条去测真实目标,两头对照着用。




