如何抓取ProductReview网站中‘See all Answers’按钮下隐藏的评论评分数据?
如何抓取ProductReview页面中隐藏在"See all Answers"按钮下的评分数据?
我尝试从ProductReview的AAMI汽车保险页面抓取评论内容,每个评论容器包含5项评分(性价比、客户服务等)。但页面初始加载时,大部分评分信息隐藏在‘See all Answers’按钮下方,因此仅能抓取顶部显示的2项评分。
当前使用的代码如下:
from bs4 import BeautifulSoup as bsoup import requests url = 'https://www.productreview.com.au/listings/aami-car-insurance?page=1#reviews' req = requests.get(url) soup = bsoup(req.text, 'html.parser') reviews = soup.find_all('div', attrs = {'class' , 'mb-0__MF overflow-hidden_Yg5 card_UzP card-full_soR card-full-md_tUp'}) ratings = reviews[0].find_all('div' , attrs = {'class' , 'flex-column__BR d-flex_RNf col-12_hGx col-md-6_qwV'}) ratings我通过网络监视器发现,点击该按钮时会生成一个GET请求以获取数据,请问如何抓取该按钮下方的隐藏数据?
嘿,你观察到点击按钮触发GET请求这点抓得很准!这说明隐藏评分是通过AJAX动态加载的,我们完全可以跳过点击操作,直接模拟这个API请求拿到完整数据,比用浏览器自动化工具高效得多。下面是具体实现步骤和代码:
核心思路
页面初始只返回部分评分,点击"See all Answers"时,前端会向网站API发送请求,传入评论ID和列表ID来获取全量评分。我们只需要:
- 从初始页面提取
listing_id(列表唯一ID)和review_id(每条评论的唯一ID) - 构造对应的API请求URL
- 发送请求并解析返回的JSON数据
步骤1:提取关键参数
从初始HTML中获取两个核心值:
- listing_id:对应AAMI汽车保险的列表ID,可以从页面meta标签、评论容器的
data-listing-id属性中提取 - review_id:每条评论的唯一标识,每个评论容器都带有
data-review-id属性,直接提取即可
步骤2:模拟API请求获取完整评分
下面是修改后的完整代码,包含请求头模拟、参数提取和错误处理:
from bs4 import BeautifulSoup as bsoup import requests import time # 添加延迟避免IP被封禁 # 初始页面URL base_url = 'https://www.productreview.com.au/listings/aami-car-insurance?page=1#reviews' # 模拟浏览器请求头,防止被网站拦截 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': 'application/json, text/plain, */*', 'Referer': base_url } # 获取初始页面并解析 req = requests.get(base_url, headers=headers) req.raise_for_status() # 检查请求是否成功 soup = bsoup(req.text, 'html.parser') # 提取listing_id(这里从meta标签提取,可根据页面结构调整) listing_id_tag = soup.find('meta', {'name': 'listing-id'}) if not listing_id_tag: # 备选提取方式:从第一条评论的data属性获取 # listing_id = reviews[0].get('data-listing-id') print("无法找到listing_id,请检查页面结构") exit() listing_id = listing_id_tag['content'] # 获取所有评论容器 reviews = soup.find_all('div', attrs={'class': 'mb-0__MF overflow-hidden_Yg5 card_UzP card-full_soR card-full-md_tUp'}) # 遍历每条评论获取完整评分 for idx, review in enumerate(reviews, 1): review_id = review.get('data-review-id') if not review_id: print(f"第{idx}条评论未找到review_id,跳过") continue # 构造API请求URL api_url = f'https://www.productreview.com.au/api/listings/{listing_id}/reviews/{review_id}/attributes' try: # 发送API请求 api_req = requests.get(api_url, headers=headers) api_req.raise_for_status() rating_data = api_req.json() # 解析并输出评分 print(f"\n=== 第{idx}条评论(ID: {review_id})完整评分 ===") for item in rating_data: print(f"- {item['name']}: {item['rating']}/5") # 添加1秒延迟,避免请求过于频繁 time.sleep(1) except requests.exceptions.RequestException as e: print(f"获取第{idx}条评论评分失败: {str(e)}")
重要注意事项
- 请求头必须带:网站会校验
User-Agent和Referer,缺失会导致403禁止访问 - 参数提取要灵活:网站页面结构可能更新,如果当前提取方式失效,需重新查看源码调整
- 控制请求频率:添加延迟避免短时间内大量请求导致IP被封禁
- 分页扩展:如需抓取多页评论,只需修改
base_url中的page参数,每页重新提取评论ID即可
内容的提问来源于stack exchange,提问作者Durgesh Chouhan
相关产品推荐
相关产品推荐

