为何部分URL无法爬取?循环执行陷入无限等待
问题原因与解决办法
核心原因
- 服务器反爬阻塞请求:这类新闻网站有严格反爬机制,仅带User-Agent的请求容易被识别为爬虫,服务器会故意不返回响应,导致
urlopen无限等待,看起来像程序卡住。 - 默认解析器效率极低:Python内置的
html.parser处理结构复杂、体积庞大的新闻页面时,解析速度极慢,会让你误以为程序无限运行。 - 未设置请求超时:
urlopen默认无超时限制,一旦服务器不响应,请求会一直挂起,不会抛出任何错误,直接卡住循环。 - 异常捕获范围错误:原代码的try-except仅包裹了
bs.find_all,但urlopen、html.read()这些IO操作也可能触发异常,却没被捕获,一旦出错就会直接中断循环。
修复方案
1. 给请求添加超时限制
修改urlopen调用,加入超时参数避免无限等待:
html = urlopen(request_site, timeout=10) # 10秒超时,可按需调整
2. 更换高效解析器
先安装lxml解析器(速度远快于内置的html.parser):
pip install lxml
再修改BeautifulSoup初始化代码:
bs = BeautifulSoup(html.read(), 'lxml')
3. 完善请求头,模拟真实浏览器
补充更多请求头字段,降低被识别为爬虫的概率:
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Referer": "https://www.google.com/" } request_site = Request(url, headers=headers)
4. 调整异常捕获范围
把所有可能出错的IO操作和解析操作都放进try块,确保异常能被捕获:
for url in initial["url"]: Article = "" try: request_site = Request(url, headers=headers) html = urlopen(request_site, timeout=10) bs = BeautifulSoup(html.read(), 'lxml') text_list = bs.find_all(['h1','p']) for text in text_list: Article += "\n\n" + text.get_text() except HTTPError as e: Article = str(e) except URLError as u: Article = str(u) except AttributeError as a: Article = str(a) except Exception as e: # 捕获其他未知异常 Article = f"未知错误: {str(e)}" # 用pd.concat替代append,效率更高 Instance_DF = pd.DataFrame({"URL":[url],"Text":[Article]}) Articles = pd.concat([Articles, Instance_DF], ignore_index=True)
5. 改用requests库(更便捷)
requests库比urllib更易用,自动处理会话和Cookie,设置超时和请求头更方便:
import requests # 先安装依赖:pip install requests for url in initial["url"]: Article = "" try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() # 主动触发HTTP错误 bs = BeautifulSoup(response.text, 'lxml') text_list = bs.find_all(['h1','p']) for text in text_list: Article += "\n\n" + text.get_text() except requests.exceptions.RequestException as e: Article = str(e) except Exception as e: Article = f"未知错误: {str(e)}" Instance_DF = pd.DataFrame({"URL":[url],"Text":[Article]}) Articles = pd.concat([Articles, Instance_DF], ignore_index=True)
内容的提问来源于stack exchange,提问作者am3333
相关产品推荐
相关产品推荐

