爬虫 IP 被封怎么办?5 个实用方法彻底解决采集难题(2026 最新)
发布时间:2026-03-19 阅读:720
爬虫采集时 IP 总被封?本文介绍 5 个实用方法,帮你彻底解决 IP 被封问题,包括代理 IP 选择、请求频率控制、User-Agent 轮换等核心技巧,2026 年最新实测有效。

一、IP 被封的常见原因
你在爬取网站数据时,是否经常遇到这些问题:
- 代码明明没问题,请求几次后就被网站拉黑
- 返回 403 Forbidden 错误,再也访问不了目标网站
- IP 地址被加入黑名单,换个时间还是不行
- 辛苦采集的数据付诸东流,项目进度严重受阻
IP 被封的根本原因: 网站的反爬虫机制检测到了异常访问行为。
1.1 网站如何识别爬虫?
| 检测维度 | 识别特征 | 触发后果 |
|---|---|---|
| 请求频率 | 短时间内大量请求 | IP 临时封禁 |
| User-Agent | 固定或缺失 | 标记为可疑 |
| IP 行为 | 同一 IP 访问过多页面 | 加入黑名单 |
| 访问模式 | 规律性请求(如每秒 1 次) | 识别为机器人 |
| Cookie 行为 | 不接受或固定 Cookie | 限制访问 |
1.2 IP 被封的常见错误代码
403 Forbidden # 禁止访问(最常见)
429 Too Many Requests # 请求过多
503 Service Unavailable # 服务不可用
Connection Reset # 连接被重置
Timeout # 请求超时
二、方法一:使用高质量住宅代理 IP(最推荐)⭐
原理: 代理 IP 可以隐藏你的真实 IP,每次请求使用不同的 IP 地址,让网站无法追踪你的真实身份。
2.1 为什么选择住宅代理 IP?
| IP 类型 | 特点 | 被封风险 | 适用场景 |
|---|---|---|---|
| 住宅代理 IP | 来自真实家庭宽带 | ⭐ 低 | 爬虫、电商、社媒 |
| 机房代理 IP | 来自数据中心 | ⭐⭐⭐ 高 | 一般用途 |
| 免费代理 IP | 公开共享 | ⭐⭐⭐⭐⭐ 极高 | 不推荐用于生产 |
住宅代理 IP 的优势:
- ✅ IP 来自真实 ISP(电信、联通、移动),网站难以识别
- ✅ IP 池庞大,可频繁切换
- ✅ 覆盖全国 300+ 城市,可指定地区
- ✅ 成功率高,适合大规模采集
2.2 Python 爬虫代理 IP 配置示例
import requests
import time
import random
# 代理 IP 配置(以悟空代理为例)
proxy_pool = [
'http://ip1:port',
'http://ip2:port',
'http://ip3:port',
# 更多 IP...
]
def get_random_proxy():
"""随机获取一个代理 IP"""
return {'http': random.choice(proxy_pool),
'https': random.choice(proxy_pool)}
def crawl_with_proxy(url, max_retries=3):
"""使用代理 IP 爬取网页"""
for i in range(max_retries):
try:
proxy = get_random_proxy()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, proxies=proxy, headers=headers, timeout=10)
if response.status_code == 200:
print(f"✓ 请求成功,使用 IP: {proxy['http']}")
return response.text
else:
print(f"✗ 请求失败,状态码:{response.status_code}")
except Exception as e:
print(f"✗ 请求异常:{str(e)}")
time.sleep(2) # 失败后等待 2 秒重试
return None
# 使用示例
url = 'https://example.com/data'
html = crawl_with_proxy(url)
2.3 代理 IP 使用技巧
技巧 1:IP 轮换策略
# 每请求 5-10 次更换一个 IP
REQUESTS_PER_IP = random.randint(5, 10)
for i in range(100):
if i % REQUESTS_PER_IP == 0:
current_proxy = get_random_proxy()
# 使用 current_proxy 发送请求
技巧 2:失败自动切换
# 检测到 IP 失效时自动切换
def check_proxy_health(proxy):
try:
response = requests.get('https://www.baidu.com',
proxies=proxy, timeout=5)
return response.status_code == 200
except:
return False
三、方法二:设置合理的请求频率
原理: 模拟真实用户的访问速度,避免短时间内发送大量请求。
3.1 推荐请求频率
| 网站类型 | 建议间隔 | 说明 |
|---|---|---|
| 小型网站 | 3-5 秒/次 | 服务器承载能力弱 |
| 中型网站 | 1-3 秒/次 | 一般电商、论坛 |
| 大型网站 | 0.5-1 秒/次 | 百度、淘宝等 |
| API 接口 | 按官方限制 | 通常有明确说明 |
3.2 随机延迟代码示例
import time
import random
def random_delay(min_seconds=1, max_seconds=3):
"""随机延迟,模拟真实用户行为"""
delay = random.uniform(min_seconds, max_seconds)
time.sleep(delay)
print(f"等待 {delay:.2f} 秒...")
# 使用示例
for url in url_list:
response = requests.get(url)
# 处理数据...
random_delay(1, 3) # 每次请求后随机等待 1-3 秒
3.3 避免规律性请求
❌ 错误做法:
# 固定间隔,容易被识别
for url in url_list:
requests.get(url)
time.sleep(2) # 固定 2 秒,太规律了
✅ 正确做法:
# 随机间隔 + 随机顺序
random.shuffle(url_list) # 打乱请求顺序
for url in url_list:
requests.get(url)
time.sleep(random.uniform(1, 5)) # 1-5 秒随机
四、方法三:轮换 User-Agent 和请求头
原理: 每次请求使用不同的浏览器标识,避免被识别为同一客户端。
4.1 User-Agent 池
import random
USER_AGENTS = [
# Chrome
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# Firefox
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
# Safari
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15',
# Edge
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
]
def get_random_headers():
"""获取随机请求头"""
return {
'User-Agent': random.choice(USER_AGENTS),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
# 使用示例
headers = get_random_headers()
response = requests.get(url, headers=headers)
4.2 进阶:模拟真实浏览器指纹
# 添加更多真实浏览器特征
headers = {
'User-Agent': random.choice(USER_AGENTS),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
}
五、方法四:处理 Cookie 和 Session
原理: 维护合理的 Cookie 行为,模拟真实用户的会话状态。
5.1 使用 Session 保持会话
import requests
# 创建 Session 对象
session = requests.Session()
# 首次访问,获取 Cookie
session.get('https://example.com')
# 后续请求会自动携带 Cookie
for url in url_list:
response = session.get(url)
# 处理数据...
5.2 Cookie 轮换策略
# 多个账号/会话轮换
cookies_list = [
{'sessionid': 'abc123'},
{'sessionid': 'def456'},
{'sessionid': 'ghi789'},
]
def get_random_cookies():
return random.choice(cookies_list)
# 使用示例
for url in url_list:
response = requests.get(url, cookies=get_random_cookies())
六、方法五:使用隧道代理自动换 IP
原理: 隧道代理可以在云端自动切换 IP,无需手动管理 IP 池,调用更简单。
6.1 隧道代理 vs 普通代理
| 特性 | 隧道代理 | 普通代理 |
|---|---|---|
| IP 切换 | 自动(每次请求) | 手动管理 |
| 代码复杂度 | 低 | 高 |
| IP 质量 | 高(云端筛选) | 参差不齐 |
| 适用场景 | 大规模采集 | 小规模测试 |
6.2 隧道代理配置示例
import requests
# 隧道代理配置(只需一个入口地址)
tunnel_proxy = {
'http': 'http://tunnel.wukongdaili.com:端口',
'https': 'http://tunnel.wukongdaili.com:端口'
}
# 添加认证信息(如有)
auth = ('用户名', '密码')
# 每次请求自动使用不同 IP
for url in url_list:
response = requests.get(
url,
proxies=tunnel_proxy,
auth=auth,
headers=get_random_headers()
)
# 处理数据...
time.sleep(random.uniform(1, 3))
6.3 隧道代理优势
- ✅ 自动换 IP - 每次请求自动使用不同 IP,无需手动管理
- ✅ 高成功率 - 云端 IP 池实时更新,自动过滤失效 IP
- ✅ 简单易用 - 一个入口地址,代码改动最小
- ✅ 成本可控 - 按请求量或时长计费,灵活选择
七、综合方案:5 种方法组合使用
最佳实践: 同时使用多种方法,最大化降低被封风险。
7.1 完整爬虫代码示例
import requests
import time
import random
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
class AntiBlockSpider:
"""防封爬虫类"""
def __init__(self, proxy_list=None):
self.proxy_list = proxy_list or []
self.session = self._create_session()
def _create_session(self):
"""创建带重试机制的 Session"""
session = requests.Session()
# 配置重试策略
retry = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session
def get_random_proxy(self):
"""获取随机代理"""
if not self.proxy_list:
return None
return {'http': random.choice(self.proxy_list),
'https': random.choice(self.proxy_list)}
def get_random_headers(self):
"""获取随机请求头"""
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
]
return {
'User-Agent': random.choice(USER_AGENTS),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
}
def crawl(self, url, max_retries=3):
"""爬取网页(防封版)"""
for i in range(max_retries):
try:
# 方法 1:使用代理 IP
proxy = self.get_random_proxy()
# 方法 2:随机请求头
headers = self.get_random_headers()
# 发送请求
response = self.session.get(
url,
proxies=proxy,
headers=headers,
timeout=10
)
if response.status_code == 200:
print(f"✓ 成功:{url}")
return response.text
elif response.status_code == 403:
print(f"✗ 被封禁,切换 IP 重试...")
else:
print(f"✗ 状态码:{response.status_code}")
except Exception as e:
print(f"✗ 异常:{str(e)}")
# 方法 3:失败后等待
time.sleep(random.uniform(2, 5))
return None
def crawl_batch(self, url_list):
"""批量爬取"""
results = []
# 方法 4:打乱请求顺序
random.shuffle(url_list)
for i, url in enumerate(url_list):
html = self.crawl(url)
if html:
results.append({'url': url, 'html': html})
# 方法 5:控制请求频率
if i < len(url_list) - 1:
delay = random.uniform(1, 3)
print(f"等待 {delay:.2f} 秒...")
time.sleep(delay)
return results
# 使用示例
if __name__ == '__main__':
# 配置代理 IP 池
proxy_list = [
'http://ip1:port',
'http://ip2:port',
'http://ip3:port',
]
spider = AntiBlockSpider(proxy_list=proxy_list)
urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
]
results = spider.crawl_batch(urls)
print(f"成功采集 {len(results)} 个页面")
八、常见问题解答
Q1: 代理 IP 多少钱?贵吗?
答: 代理 IP 价格因类型和数量而异:
- 短效代理:约 0.002-0.01 元/IP
- 隧道代理:约 39-199 元/月
- 独享 IP:约 49-99 元/月/IP
对于小规模采集,月消费通常在 100-500 元;大规模采集可根据用量选择套餐。
Q2: 免费代理 IP 能用吗?
答: 不推荐用于生产环境。免费代理 IP 的问题:
- ❌ 稳定性差,随时失效
- ❌ 速度慢,影响采集效率
- ❌ 安全性低,可能泄露数据
- ❌ 容易被网站识别并封禁
Q3: 代理 IP 成功率多少算正常?
答: 高质量代理 IP 的成功率:
- ✅ 优秀:95% 以上
- ✅ 良好:90%-95%
- ⚠️ 一般:80%-90%
- ❌ 较差:80% 以下(建议更换服务商)
Q4: 如何测试代理 IP 质量?
def test_proxy(proxy, test_url='https://www.baidu.com'):
"""测试代理 IP 质量"""
import time
start = time.time()
try:
response = requests.get(test_url, proxies=proxy, timeout=10)
latency = (time.time() - start) * 1000
return {
'proxy': proxy,
'status': '可用' if response.status_code == 200 else '不可用',
'latency': f'{latency:.0f}ms',
'status_code': response.status_code
}
except Exception as e:
return {
'proxy': proxy,
'status': '异常',
'error': str(e)
}
# 批量测试
proxy_list = ['http://ip1:port', 'http://ip2:port']
for proxy in proxy_list:
result = test_proxy(proxy)
print(result)
Q5: 被封 IP 后多久能解封?
答: 视网站政策而定:
- 临时封禁:几分钟到几小时
- 短期封禁:24-72 小时
- 永久封禁:需要更换 IP 或联系网站解封
建议: 使用代理 IP 避免被封,比解封更省时省力。
九、总结
爬虫 IP 被封的 5 个解决方法:
| 方法 | 效果 | 实施难度 | 推荐指数 |
|---|---|---|---|
| 1. 使用住宅代理 IP | ⭐⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐⭐ |
| 2. 设置合理请求频率 | ⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐⭐ |
| 3. 轮换 User-Agent | ⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐ |
| 4. 处理 Cookie/Session | ⭐⭐⭐ | 中等 | ⭐⭐⭐ |
| 5. 使用隧道代理 | ⭐⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐⭐ |
最佳实践: 5 种方法组合使用,最大化降低被封风险。
悟空代理 提供 1000 万 + 纯净住宅 IP,覆盖全国 300+ 城市,支持短效代理、隧道代理、独享 IP 等多种产品。
新用户福利: 注册即送免费试用,立即体验高质量代理服务。
👉 立即试用 | 📞 咨询客服
本文由悟空代理原创,转载请注明出处。
想了解更多爬虫代理 IP 使用技巧?关注我们,后续教程持续更新。
悟空代理 - 千万住宅 IP 资源赋能大数据
