Python爬虫程序在Spyder中每爬取约600个网页后卡死,如何排查问题?
null
Python爬虫程序在Spyder中每爬取约600个网页后卡死,如何排查问题?
2 回复
这个问题很典型,通常和资源管理或网络行为有关。别慌,咱们一步步来。
首先,最可能的原因是连接没关闭或者内存泄漏。爬虫卡死,多半是资源耗尽了。我给你写个诊断和修复的模板,你对照着改。
import requests
import time
from contextlib import closing
import gc
def robust_crawler(url_list, delay=1, max_retries=3):
"""
一个健壮的爬虫函数,重点处理连接和内存。
"""
session = requests.Session()
# 设置一个合理的超时,防止永远等待
session.request = lambda method, url, **kwargs: requests.Session.request(
session, method, url, timeout=(10, 30), **kwargs
)
for i, url in enumerate(url_list):
print(f"Processing {i+1}/{len(url_list)}: {url}")
html = None
for attempt in range(max_retries):
try:
# 关键:使用 with closing 确保连接体被释放
with closing(session.get(url, stream=True)) as response:
# 使用stream模式,避免大响应体一次性读入内存
response.raise_for_status()
html = response.content # 或 .text
# 这里处理你的html数据,比如解析、保存
# process_html(html)
# 成功抓取后跳出重试循环
break
except requests.exceptions.RequestException as e:
print(f" Attempt {attempt+1} failed for {url}: {e}")
if attempt < max_retries - 1:
time.sleep(delay * 2 ** attempt) # 指数退避
else:
print(f" Failed after {max_retries} attempts.")
html = None
except Exception as e:
print(f" Unexpected error: {e}")
html = None
break # 非网络错误,直接跳出
# 每处理N个请求后,主动清理一次,并暂停。这是关键!
if (i + 1) % 100 == 0: # 你可以调整这个数字,比如200
print(f" --- 已处理 {i+1} 个,主动清理内存并休息 ---")
# 1. 关闭session的适配器连接池(可选但有效)
session.close()
# 2. 强制垃圾回收
gc.collect()
# 3. 短暂休息,模拟人工操作,也释放系统资源
time.sleep(5)
# 4. 重新创建session(如果上面关闭了)
session = requests.Session()
session.request = lambda method, url, **kwargs: requests.Session.request(
session, method, url, timeout=(10, 30), **kwargs
)
# 每个请求之间的基础间隔
time.sleep(delay)
# 最终关闭
session.close()
print("所有任务完成。")
# 使用示例
if __name__ == '__main__':
# 假设你的url列表
my_urls = [f"http://example.com/page/{i}" for i in range(1000)]
robust_crawler(my_urls, delay=0.5)
核心排查点:
- 连接池耗尽:Spyder(或任何IDE)里长时间运行脚本,
requests的默认连接池可能被占满。上面的代码通过定期session.close()和重建来清空。 - 内存泄漏:如果解析库(如
BeautifulSoup)或你的代码持续创建未被释放的对象,内存会慢慢涨上去。gc.collect()和定期重启“处理循环”能缓解。 - 网络不稳定/服务器限制:加入了重试机制和指数退避,避免因偶发失败卡住。
- Spyder 自身限制:在IDE里跑长进程有时不如命令行稳定。你可以在代码里把关键日志(如处理到第几个URL)打印出来,这样即使卡住,也能看到最后卡在哪里。
给你的直接建议:
先别管你原来的代码,用上面这个模板替换你的抓取循环,重点看 每处理N个请求后 那段逻辑。把 process_html(html) 换成你自己的处理函数。如果问题解决,那基本就是资源管理的问题;如果还卡,可能是你处理HTML的那部分代码有性能瓶颈。
一句话总结:用 with closing 管理连接,并定期休息、清理内存和重建会话。
多 print 一些信息, 看停留在什么地方了。。。

