Flask API爬取异常排查:为何仅返回最后一个目标页面内容
问题原因分析
你遇到的问题核心有两个关键点:
- 内容未收集直接覆盖/提前返回:如果你的
return text.encode('utf-8')是放在for page in pages循环内部(就像你贴的代码那样),函数会在处理完第一个页面后立刻返回,直接终止函数执行,后面的页面根本不会被处理;但你说API返回的是最后一个页面的内容,那大概率是你实际代码里把return放在了循环外面——这时候循环会遍历所有页面,但每次都会用新页面的内容覆盖text变量,最后return的自然是最后一次循环的结果,也就是最后一个页面的内容。
而你在Flask外运行正常,是因为你可能在脚本里是逐个打印每个页面的内容,或者手动做了内容收集,但在Flask路由函数里没有做这个操作,只是单纯覆盖变量后返回。
- 变量名冲突(次要但需注意):你用了
page作为循环变量,之后又把它赋值为urllib.request.urlopen(page_link)的结果,这会覆盖循环变量的原始值,虽然不会直接导致当前问题,但会让代码可读性变差,容易引发其他隐藏bug,建议改名优化。
修复方案
我们需要修改代码,把每个页面处理后的内容收集起来,最后一次性返回所有内容。具体实现如下:
import urllib.request from bs4 import BeautifulSoup from flask import Flask, render_template, request app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def scraper(): pages=['', 'companies', 'universities', 'about-us', 'kickstart'] # 目标网站的不同页面 all_page_content = [] # 创建列表存储所有页面的处理结果 for page_path in pages: # 重命名循环变量,避免和响应对象冲突 page_link = 'http://www.xxxxxxx.org.uk/' + page_path response = urllib.request.urlopen(page_link ) # 用response替代page,解决变量冲突 soup = BeautifulSoup(response, 'html.parser') for script in soup(["script", "style"]): script.extract() text = soup.get_text() # 获取文本内容 lines = (line.strip() for line in text.splitlines()) chunks = (phrase.strip() for line in lines for phrase in line.split(" ")) cleaned_text = '\n'.join(chunk for chunk in chunks if chunk) # 清理文本中的链接等内容 all_page_content.append(cleaned_text) # 将当前页面的内容添加到列表中 # 把所有页面内容拼接,用自定义分隔符区分不同页面 full_result = '\n\n===== 页面分割线 =====\n\n'.join(all_page_content) return full_result.encode('utf-8') # 返回所有页面的内容 if __name__ == '__main__': app.run()
额外优化建议
- 你可以根据需求调整页面内容的分隔方式,比如用HTML的
<hr>标签分隔(如果需要返回HTML格式),或者用更贴合需求的标识; - 建议添加异常处理,比如捕获
urllib.error.HTTPError或urllib.error.URLError,避免某个页面爬取失败导致整个API崩溃; - 如果目标网站有反爬机制,记得给请求添加
User-Agent等请求头,模拟浏览器请求,降低被封禁的概率。
内容的提问来源于stack exchange,提问作者Faye Pasvouri
相关产品推荐
相关产品推荐

