下午六点,程序员小李盯着屏幕,眉头都皱成疙瘩了。
他写了个爬虫爬电商数据,前两百条顺得一批,可到了第三百条,直接疯狂报 403 Forbidden。

隔壁老员工路过瞟了一眼:“你IP被封了,换个代理继续跑就行。”
小李翻出收藏夹里那几个免费代理网站,一个个试——连不上的、慢到怀疑人生的、好不容易连上又秒封的。
折腾半小时,数据没抓几条,代码改了七八版。
说实话,这几乎是每个写爬虫的人,都踩过的坑。
代理IP这东西,说简单也简单,说复杂能把人绕晕。
今天我就把整套逻辑,掰开揉碎了讲明白。
代理IP在爬虫里的作用,说白了就是个“替身”。
你的真实IP,就像你出门带的身份证。
你去访问一个网站,人家会记下你的号。
去一两次没事,一天跑个上万次,人家立马反应过来:这肯定是机器。直接拉黑。
代理IP,就是帮你换张“临时身份证”再进门。
你的请求先发到代理服务器,再由它转给目标网站。
对方看到的IP是代理的,你的真实IP藏得严严实实。
就算被封,封的也是代理,换一个继续,根本伤不到你自己。
整个流程就两件事:
第一,怎么拿到靠谱的代理;
第二,怎么在代码里用起来。
先说说怎么搞代理。
市面上的代理分三六九等。
免费的网上一搜一大把,随便写个小脚本就能爬下来。
def fetch_free_proxies(url):
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
proxies = []
for row in soup.select("table tr")[1:]:
columns = row.find_all("td")
ip = columns[0].text.strip()
port = columns[1].text.strip()
proxies.append(f"{ip}:{port}")
return proxies
代码一跑,能抓一堆IP。
但问题也很明显:质量完全没保证——可能下一秒就失效,可能慢得要死,甚至还有可能是别人故意放的“钓鱼代理”。
想省心,就得用付费的。
数据中心代理速度快、便宜,但容易被识别;
住宅代理用的是真实用户IP,伪装效果拉满,价格贵点也正常。
代理拿到手,千万别直接扔代码里用,一定要先验货。
方法很简单:用这个代理去请求一个能显示IP的网站(比如 httpbin.org/ip),看看返回的IP是不是代理本身。
def test_proxy(proxy):
proxies = {"http": f"http://{proxy}", "https": f"https://{proxy}"}
try:
response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=5)
if response.status_code == 200:
print(f"代理 {proxy} 可用")
return True
except:
pass
return False能连通只是第一步。
你还要看速度快不快、是不是高匿(不暴露你用了代理)、有没有被目标网站拉黑。
一套测下来,十个里能用一两个都算不错了。
代理验完,就该在爬虫里用了。
最简单的方法:随机切换。
维护一个代理列表,每次请求随便挑一个。
proxy_pool = [
{"http": "http://123.45.67.89:8080"},
{"https": "http://112.89.33.21:3128"}
]
for _ in range(10):
proxy = random.choice(proxy_pool)
try:
response = requests.get(url, proxies=proxy, timeout=5)
# 处理数据
except:
continue优点是简单粗暴,缺点也明显:抽到失效代理直接报错。
稍微改进一下,就是智能轮询容错。
class ProxyRotator:
def __init__(self, proxies):
self.proxies = cycle(proxies)
def get_page(self, url):
for _ in range(len(self.proxies)):
current_proxy = next(self.proxies)
try:
resp = requests.get(url, proxies=current_proxy, timeout=8)
return resp.text
except:
continue
raise Exception("所有代理都挂了")这个版本会一个个轮着试,直到找到能用的为止,比纯随机稳得多。
更高级的玩法,是代理池 + 中间件。
自己搭一个代理池服务,自动爬免费IP、自动验证、自动去重、存数据库,再提供接口给爬虫调用。
配合 Scrapy 这类框架,配好中间件,你的爬虫主代码里,甚至不用写一句代理逻辑。
# settings.py配置
DOWNLOADER_MIDDLEWARES = {
'scrapy_proxy_pool.middlewares.ProxyPoolMiddleware': 100,
}
PROXY_POOL_URL = 'http://your-proxy-pool:5010' # 自建代理池API这种方案适合大规模采集,能自动管理成千上万的IP。
有了代理还不够,访问策略也很重要。
光换IP不行,你得让请求看起来像真人。
User-Agent 要经常换,别从头到尾一个标识。
访问频率也要控制,一秒钟刷几十次,再好的代理也得被封。
加点随机延迟,模仿正常人的浏览节奏。
更聪明的做法是动态调整速度:
成功率高就稍微快一点,遇到封禁就放慢节奏。
def adjust_delay(self, success):
if success:
self.current_delay = max(self.min_delay, self.current_delay * 0.9) # 成功就加快
else:
self.current_delay = min(self.max_delay, self.current_delay * 1.5) # 失败就减慢最后说几个最容易踩的坑。
代理连不上最常见:IP端口写错、代理挂了、网络不通。
排查也简单:先测本地网,再单独用请求工具测代理。
超时也很烦人。
有些代理本身就慢,等半天没反应。
调大 timeout 是治标,换优质低负载代理才是治本。
需要账号密码的代理,格式别写错:
http://username:password@ip:port把整套流程串起来,就是一个完整闭环:
采集代理源 → 验证可用性 → 放进代理池 → 爬虫请求时自动取用
→ 成功继续,失败标记剔除 → 定期补充新IP、清理失效IP
听起来有点麻烦,但只要跑通一次,后面一劳永逸。
你的爬虫就像随时能换身份,对方很难再把你识别出来。
小李听完这套思路,回去自己搭了个简易代理池。
第二天一看,爬虫安安稳稳跑了一整夜,抓了十几万条数据,一条封禁都没有。
他这才明白:
代理IP这东西,把流程理顺,比临时瞎找免费代理靠谱一百倍。
