You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Beautiful Soup爬取丝芙兰香水仅获前12条数据问题求助

解决丝芙兰香水页面爬取仅获取前12条数据的问题

嘿,我碰到过一模一样的问题!丝芙兰这个香水列表页用了懒加载机制——页面初始只会渲染前12条商品,剩下的48条得等用户滚动到对应位置时,才会通过JavaScript动态加载出来。你用requests.get()拿到的只是页面的静态初始源码,后面的商品元素要么是占位结构,要么内容还没填充,所以就算perfume_containers长度显示60,也提取不到后面的品牌信息。

给你两个靠谱的解决方案:

方案一:用Selenium模拟浏览器动态加载页面

Selenium可以模拟真实浏览器的行为,帮你滚动页面加载所有商品,再获取完整的页面源码。

步骤:

  1. 先安装Selenium和对应浏览器的驱动(比如ChromeDriver,要和你的Chrome版本匹配):
    pip install selenium
    
  2. 运行下面的代码:
from selenium import webdriver
from bs4 import BeautifulSoup
import pandas as pd

# 初始化Chrome浏览器(记得把ChromeDriver路径配置好,或者放在环境变量里)
driver = webdriver.Chrome()
driver.get('https://www.sephora.com/shop/perfume')

# 模拟滚动到底部,触发所有商品加载
last_scroll_height = driver.execute_script("return document.body.scrollHeight")
while True:
    # 滚动到当前页面底部
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    # 等待3秒让商品加载(可以根据网络情况调整)
    driver.implicitly_wait(3)
    # 计算新的页面高度,判断是否加载完所有内容
    new_scroll_height = driver.execute_script("return document.body.scrollHeight")
    if new_scroll_height == last_scroll_height:
        break
    last_scroll_height = new_scroll_height

# 获取加载完成后的完整页面源码
soup = BeautifulSoup(driver.page_source, 'html.parser')
driver.quit()  # 关闭浏览器

# 提取所有商品容器
perfume_containers = soup.find_all('div', class_="css-12egk0t")

brands = []
names = []
prices = []

for container in perfume_containers:
    # 处理品牌提取,兼容可能的不同class(如果还有其他结构,自己补充对应的class)
    brand = container.find('span', class_='css-ktoumz') or container.find('span', class_='css-另一个可能的class')
    if brand:
        brands.append(brand.text.strip())
    else:
        brands.append(None)
    
    # 同理提取商品名称和价格,根据实际页面结构调整class
    name = container.find('span', class_='css-1pgnl76')
    names.append(name.text.strip() if name else None)
    
    price = container.find('span', class_='css-1b8x74j')
    prices.append(price.text.strip() if price else None)

# 整理成DataFrame
perfume_df = pd.DataFrame({
    '品牌': brands,
    '香水名称': names,
    '价格': prices
})

print(perfume_df)

方案二:直接调用API接口(更高效)

其实丝芙兰的商品数据是通过API接口返回的,你可以在浏览器开发者工具里找到这个接口,直接请求获取JSON格式的完整数据,不用处理页面结构的问题。

步骤:

  1. 打开浏览器F12,切换到「Network」标签,滚动页面,找到类似catalog/products的XHR请求,复制它的URL和参数。
  2. requests直接请求这个接口:
import requests
import pandas as pd

# 替换成你找到的API接口URL和参数
api_url = 'https://www.sephora.com/api/catalog/products'
params = {
    'categoryId': 'cat170006',  # 香水分类的ID,从请求里复制
    'currentPage': 1,
    'pageSize': 60,
    'sortBy': 'POPULARITY'
}

# 加上请求头模拟浏览器,避免被拦截
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'
}

response = requests.get(api_url, params=params, headers=headers)
product_data = response.json()

brands = []
names = []
prices = []

# 从JSON数据里提取需要的字段
for product in product_data['products']:
    brands.append(product['brandName'])
    names.append(product['displayName'])
    prices.append(product['currentSku']['listPrice'])

perfume_df = pd.DataFrame({
    '品牌': brands,
    '香水名称': names,
    '价格': prices
})

print(perfume_df)

这个方案比爬页面更稳定,因为API返回的数据结构很规整,不会因为页面UI更新而失效(只要接口不变)。

内容的提问来源于stack exchange,提问作者DJ-coding

火山引擎 最新活动