Scrapy请求失败、代理报错及多进程优化技术咨询
解决代理IP爬取错误 & 多进程优化方案
一、先搞定那些302/403/500报错
这些错误本质上要么是代理IP本身失效/不被目标网站认可,要么是你的请求模拟得不够像真实用户。咱们一步步来修复:
1. 先筛掉无效代理IP
你现在是随机选池里的IP,但免费代理大多是短命鬼,很多已经不能用了。建议在选代理前先做有效性检测:
import requests def is_proxy_valid(ip): try: # 用httpbin检测代理是否能正常转发请求 resp = requests.get( "https://httpbin.org/ip", proxies={"http": f"http://{ip}", "https": f"http://{ip}"}, timeout=5 ) return resp.status_code == 200 except: return False # 提前过滤出可用IP再随机选择 valid_proxies = [item for item in ippool if is_proxy_valid(item['ip'])] if valid_proxies: selected_proxy = random.choice(valid_proxies) request.meta['proxy'] = f"http://{selected_proxy['ip']}" else: # 没有可用代理时的降级方案,比如用本地IP继续爬 pass
2. 处理302重定向问题
你设置了dont_redirect=True,但有些网站的302是正常跳转(比如地域跳转、登录跳转),强制关闭反而会触发403。可以改成允许重定向,但要保证重定向请求也用代理:
request.meta['dont_redirect'] = False request.meta['allow_redirects'] = True # 确保重定向后的请求也走当前代理 request.meta['proxy'] = f"http://{selected_proxy['ip']}"
另外,如果是地域导致的302,记得筛选和目标网站匹配地域的代理IP。
3. 破解403 Forbidden
403基本是网站把你当成爬虫了,除了换有效代理,还要优化请求头模拟真实用户:
- 换掉Scrapy默认的User-Agent:
request.headers['User-Agent'] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
- 补充Referer、Accept-Language等常见请求头,让请求更逼真;
- 给请求加一点延迟,别太激进,在
settings.py里配置:
DOWNLOAD_DELAY = 1.5 # 每个请求间隔1.5秒
4. 解决500内部服务器错误
500大概率是代理IP本身挂了,或者被目标网站拉黑了。可以在响应处理里自动剔除失效代理:
def process_response(self, request, response, spider): # 遇到500/403/302这类错误,把对应代理从池里移除 if response.status in [500, 403, 302]: if 'proxy' in request.meta: bad_ip = request.meta['proxy'].split('//')[1] global ippool ippool = [item for item in ippool if item['ip'] != bad_ip] # 重新发送当前请求 return request.copy() return response
如果还是频繁500,建议换付费代理,稳定性比免费的好太多。
二、添加多进程提升爬取速度
Scrapy本身是异步框架,但如果你的爬虫有大量阻塞操作(比如代理检测、复杂数据处理),可以结合多进程优化。这里给你两种实用方案:
1. 先调优Scrapy内置并发(最简单)
先把Scrapy本身的并发参数拉满,这是最省心的优化:
在settings.py里修改:
# 全局并发请求数 CONCURRENT_REQUESTS = 32 # 每个域名的并发数 CONCURRENT_REQUESTS_PER_DOMAIN = 8 # 每个代理IP的并发数(避免单个IP被封) CONCURRENT_REQUESTS_PER_IP = 4 # 启用自动限速,根据网站响应动态调整请求速度 AUTOTHROTTLE_ENABLED = True AUTOTHROTTLE_START_DELAY = 1 AUTOTHROTTLE_MAX_DELAY = 10
2. 用multiprocessing启动多爬虫进程
如果单爬虫实例不够,可以启动多个进程跑同一个爬虫:
from multiprocessing import Process from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings def run_spider(spider_name): process = CrawlerProcess(get_project_settings()) process.crawl(spider_name) process.start() if __name__ == "__main__": # 启动3个进程同时跑你的爬虫 processes = [] for _ in range(3): p = Process(target=run_spider, args=('你的爬虫名称',)) p.start() processes.append(p) # 等待所有进程完成 for p in processes: p.join()
⚠️ 注意:每个进程的爬虫是独立的,不要共享全局变量;如果有数据库写入操作,记得加锁避免冲突。
3. 进阶:用scrapy-redis做分布式爬取
如果需要更大规模的并发,推荐用scrapy-redis实现分布式——多个机器/进程共享任务队列,充分利用多节点资源。不过这个需要配置Redis,适合中大型爬取任务。
内容的提问来源于stack exchange,提问作者yixuan
相关产品推荐
相关产品推荐

