使用BeautifulSoup提取网页Pros后文本失败,求修复方案及学习资源
代码修复方案
原代码存在的问题
- 冗余文件操作:开头
voip_p = open("voip.ms_pros.txt")未关闭,后续又用with open重新打开,会引发文件访问冲突 - 变量名错误:
response = requests.get(url)后误用res.text,变量名不匹配 - 分页URL格式错误:getapp的分页参数是
?page=而非/page=,原URL无法正确访问分页内容 - 选择器逻辑偏差:
p:-soup-contains("Pros")仅选中包含"Pros"的标签,未获取其后续的实际内容,且该选择器需要lxml解析器支持 - 无反爬处理:直接请求易被网站拦截
修复后的代码
import requests from bs4 import BeautifulSoup # 模拟浏览器请求头,降低反爬拦截概率 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" } page = 1 # 用w模式初始化文件,确保编码为utf-8避免乱码 with open('voip.ms_pros.txt', 'w', encoding='utf-8') as voip_p: while page <= 14: # 循环1-14页,避免死循环 # 修正分页URL格式 url = f"https://www.getapp.ca/reviews/2035391/voip-ms?page={page}" try: response = requests.get(url, headers=headers) response.raise_for_status() # 检查请求是否成功 # 使用lxml解析器,支持灵活选择器(需提前安装:pip install lxml) soup = BeautifulSoup(response.text, "lxml") # 遍历每个评论卡片 for review_card in soup.select('div.review-card'): # 定位包含"Pros"的标题元素 pros_title = review_card.find('p', string=lambda text: text and 'Pros' in text) if pros_title: # 获取Pros标题的下一个兄弟元素(即内容部分) pros_content = pros_title.find_next_sibling('p') if pros_content: voip_p.write(pros_content.get_text(strip=True) + '\n') voip_p.write('-' * 80 + '\n') print(f"第{page}页数据抓取完成") page += 1 except Exception as e: print(f"第{page}页抓取失败: {str(e)}") page += 1
代码修改说明
- 移除冗余文件打开语句,改用
with open的w模式初始化文件,指定utf-8编码避免乱码 - 添加
User-Agent请求头,模拟浏览器请求 - 修正分页URL格式,匹配网站的分页规则
- 切换到lxml解析器,支持更灵活的元素定位方式
- 调整逻辑:先遍历评论卡片,定位Pros标题后获取其后续的内容元素,精准抓取Pros之后的文本
- 添加异常处理,避免单页抓取失败导致程序终止
自学资源推荐
- 基础入门
- Python核心语法:廖雪峰Python教程,从变量、循环到函数、类,系统掌握Python基础
- 爬虫库官方文档:requests、BeautifulSoup官方文档,直接学习库的API和用法
- 工具技能
- 浏览器开发者工具:学会用F12查看页面HTML结构、网络请求,快速定位需要抓取的元素
- 实战进阶
- 静态页面实战:从简单的博客、新闻站点开始,练习元素定位和文本提取
- 反爬基础:学习User-Agent伪装、IP代理、Cookie处理等基础反爬技巧
- 动态页面处理:了解Selenium、Scrapy等工具,应对JavaScript渲染的页面
内容的提问来源于stack exchange,提问作者ash
相关产品推荐
相关产品推荐

