Flask RSS新闻API随机返回500 Internal Server Error问题求助
错误产生原因
你遇到的http.client.IncompleteRead错误属于网络请求类异常,产生的核心原因是:
- feedparser向第三方新闻站点请求RSS内容时,站点返回的HTTP响应头中
Content-Length字段声明的内容大小,和实际传输的内容大小不符 - 多数情况是第三方RSS源服务器不稳定、网络抖动、连接被提前中断导致,因为你每次随机选源,所以故障只会随机出现,不是你的业务代码逻辑有问题
- 你当前的代码没有对这类网络异常做捕获处理,异常直接向上抛出到Flask框架,就会返回500错误
修复方案
1. 新增异常捕获+重试机制,避免异常直接抛出
首先将7个分类重复的逻辑封装为公共函数,同时添加异常捕获、重试逻辑,重试失败后可以自动切换其他源,或者返回友好错误:
import feedparser from flask import Flask from flask_restful import Resource, Api import random import source import requests from http.client import IncompleteRead import time app = Flask(__name__) api = Api(app) # 公共新闻获取函数,避免重复代码 def fetch_news(source_list, max_retry=2): # 最多尝试max_retry+1次 for _ in range(max_retry + 1): try: rss_source = random.choice(list(source_list)) feed = feedparser.parse(rss_source) # 校验解析结果是否有效 if not feed.entries: continue entry = random.choice(feed.entries) return { 'title': entry.title, 'summary': entry.summary, 'date': entry.published, 'link': entry.link }, 200 except (IncompleteRead, ConnectionError, KeyError, AttributeError) as e: # 捕获网络异常、字段缺失等常见错误,等待100ms后重试 time.sleep(0.1) continue # 所有重试都失败返回友好提示 return {'msg': '当前新闻源暂时不可用,请稍后重试'}, 503 # 各个分类接口直接调用公共函数即可 class WorldNews(Resource): def get(self): return fetch_news(source.world_news) class TechNews(Resource): def get(self): return fetch_news(source.tech_sources) class BusinessNews(Resource): def get(self): return fetch_news(source.business) class SportsNews(Resource): def get(self): return fetch_news(source.sports) class ScienceNews(Resource): def get(self): return fetch_news(source.science) class HealthNews(Resource): def get(self): return fetch_news(source.health) class EntertainmentNews(Resource): def get(self): return fetch_news(source.entertainment) api.add_resource(WorldNews, '/world') api.add_resource(TechNews, '/tech') api.add_resource(BusinessNews, '/business') api.add_resource(SportsNews, '/sports') api.add_resource(ScienceNews, '/science') api.add_resource(HealthNews, '/health') api.add_resource(EntertainmentNews, '/entertainment') if __name__ == '__main__': app.run()
2. 可选优化:自行控制HTTP请求逻辑
如果还是频繁出现该错误,可以不用feedparser自带的请求能力,先用requests库拉取RSS内容,再传给feedparser解析,你可以自定义超时时间、请求头、重试策略,可控性更高:
def fetch_news(source_list, max_retry=2): for _ in range(max_retry + 1): try: rss_source = random.choice(list(source_list)) # 自行发请求,设置5秒超时,自定义UA避免被源站拦截 resp = requests.get(rss_source, timeout=5, headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36' }) resp.raise_for_status() feed = feedparser.parse(resp.content) if not feed.entries: continue entry = random.choice(feed.entries) return { 'title': entry.title, 'summary': entry.summary, 'date': entry.published, 'link': entry.link }, 200 except (IncompleteRead, ConnectionError, requests.exceptions.RequestException, KeyError, AttributeError) as e: time.sleep(0.1) continue return {'msg': '当前新闻源暂时不可用,请稍后重试'}, 503
内容的提问来源于stack exchange,提问作者bigman1234
相关产品推荐
相关产品推荐

