使用bs4的find_all爬取Newegg商品评分仅返回单个元素,网页存在更多匹配项
问题分析
你遇到的情况核心原因是:Newegg的用户评论区评分属于动态加载内容。requests只能获取页面初始加载的静态HTML,而评论及对应评分数据是页面加载完成后,通过JavaScript异步请求后端接口获取并渲染的,所以初始HTML里只有一个匹配的元素,后续加载的评分根本没被requests抓到。
解决方案
有两种可行的解决方式:
方式一:用Selenium模拟浏览器加载完整页面
Selenium会模拟真实浏览器的渲染流程,等所有动态内容加载完成后再抓取数据,步骤如下:
- 先安装Selenium和对应浏览器驱动(比如ChromeDriver,要和你的Chrome版本匹配)
- 示例代码:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 初始化Chrome驱动(确保ChromeDriver路径正确,或者配置到环境变量) driver = webdriver.Chrome() target_url = 'https://www.newegg.com/msi-geforce-rtx-3060-rtx-3060-ventus-2x-12g-oc/p/N82E16814137632?Description=gpu&cm_re=gpu-_-14-137-632-_-Product' driver.get(target_url) # 等待评论区评分元素加载完成,超时设置10秒 try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '.rating.rating-4')) ) # 抓取所有符合class条件的元素 all_ratings = driver.find_elements(By.CSS_SELECTOR, '.rating.rating-4') print(f"共找到 {len(all_ratings)} 个符合要求的评分元素") finally: # 用完关闭浏览器 driver.quit()
方式二:直接请求评论数据的API接口
这种方式效率更高,不需要模拟浏览器,步骤如下:
- 打开浏览器开发者工具(按F12),切换到「Network」标签,刷新页面后筛选「XHR」请求,找到包含评论数据的接口(一般url里会有review、comment这类关键词)
- 复制接口地址和请求头,直接用requests请求获取JSON格式数据,示例代码:
import requests # 替换成你抓包得到的评论API地址 review_api = "https://api.newegg.com/product/api/reviews?ItemNumber=14-137-632&PageSize=20&Page=1" # 必要请求头,避免被接口拦截 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' } response = requests.get(review_api, headers=headers) review_data = response.json() # 从返回的JSON里提取每个评论的评分 for item in review_data.get('Reviews', []): rating_score = item.get('Rating') print(f"用户评分: {rating_score}")
补充提示
- 用requests获取page内容后,可以把内容存成HTML文件打开查看,就能确认目标元素是否在静态HTML里,快速判断是不是动态加载的问题
- 抓API接口时,如果请求被拦截,要检查请求头里的其他参数(比如Referer、Cookie),把浏览器里的参数复制过来即可
内容的提问来源于stack exchange,提问作者majduddin alboon
相关产品推荐
相关产品推荐

