Python爬虫程序运行中假死无响应且不抛异常,如何排查与解决?
null
Python爬虫程序运行中假死无响应且不抛异常,如何排查与解决?
设置 timeout ?
遇到爬虫假死这事儿确实挺烦的,程序挂着不动也不报错。我一般按这个顺序来查:
1. 先看是不是网络请求卡住了 直接用requests的timeout参数,别让它无限等:
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retries = Retry(total=3, backoff_factor=0.5)
session.mount('http://', HTTPAdapter(max_retries=retries))
session.mount('https://', HTTPAdapter(max_retries=retries))
# 设置连接和读取超时
try:
response = session.get('http://example.com', timeout=(3.05, 27))
except requests.exceptions.Timeout:
print("请求超时了")
except requests.exceptions.RequestException as e:
print(f"请求出错: {e}")
2. 检查是不是解析耗死了 特别是用BeautifulSoup处理大文件或复杂HTML时:
from bs4 import BeautifulSoup
import lxml # 确保安装了lxml解析器
# 用lxml解析器,比html.parser快得多
soup = BeautifulSoup(html_content, 'lxml')
# 如果文档真的很大,考虑逐部分处理
# 或者用select代替find_all,效率更高
3. 线程/进程池可能卡住了 如果用concurrent.futures,记得设timeout:
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
def fetch_url(url):
# 你的爬取逻辑
pass
urls = [...] # URL列表
with ThreadPoolExecutor(max_workers=10) as executor:
future_to_url = {executor.submit(fetch_url, url): url for url in urls}
for future in as_completed(future_to_url.keys(), timeout=30):
try:
data = future.result(timeout=10) # 每个任务单独超时
except TimeoutError:
print(f"任务超时: {future_to_url[future]}")
future.cancel() # 取消卡住的任务
4. 加个全局看门狗 设个总时间限制,超时就退出:
import signal
import time
class TimeoutException(Exception):
pass
def timeout_handler(signum, frame):
raise TimeoutException("程序运行超时")
# 设置2小时超时
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(7200) # 7200秒=2小时
try:
# 你的主爬虫逻辑
main_spider()
except TimeoutException:
print("程序执行超时,自动退出")
finally:
signal.alarm(0) # 取消定时器
5. 关键位置加日志 在可能卡住的地方记录状态:
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def parse_page(html):
logger.info("开始解析页面")
# 解析逻辑...
logger.info(f"解析完成,找到{len(items)}个条目")
return items
6. 用异步试试 如果同步请求容易卡,考虑aiohttp:
import aiohttp
import asyncio
async def fetch(session, url):
try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as response:
return await response.text()
except asyncio.TimeoutError:
print(f"异步请求超时: {url}")
return None
async def main():
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks, return_exceptions=True)
快速排查步骤:
- 先加超时参数复现问题
- 在关键函数入口/出口加print或日志
- 用
top或任务管理器看CPU/内存 - 逐步缩小范围,定位具体卡住的函数
最可能的就是网络请求没设超时,或者解析大文件时内存爆了。先从这里查起。
总结:核心是给所有可能阻塞的操作加上超时控制。
多 print, 看卡在哪了。。。
你代码也不发 让我们怎么猜。。。。
接楼上,我猜是爬虫累了
栈溢出
爬虫:爬了这么久,是该歇歇了。
多线程死锁?
服务器被你爬趴下了?
阻塞了, 链接池释放了吗,设置 timeout 了吗
可能虫子被小鸟吃了
开 ssh,我去看看
爬虫:我休息一下不行?换你一直爬试试?
用 print 方法检查,那个地方卡了。每个函数下都放个 print.
1 楼说的对,很大可能没有设置 timeout。
另外可以加杀死进程的代码。在下一次启动任务时,先执行一下杀死进程。注意 2 个 crontab
爬虫:我有自己的想法了,我要看小电影,歇一会
只说自己爬虫程序卡死了,也不说自己具体使用的是什么技术。。也不贴代码,这让人怎么给你分析?
大多数原因都是阻塞在了某个链接上,如果你使用 python 的协程 处理不好的话很容易卡死的。
被一只早起的鸟,吃了
可以看一下,是不是卡在打 log 上了。我曾经碰到过,将所有 log 配置都去除,只有在抛异常的时候再打 log
当然是等它复活啊
记得 close connection


