You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React动态站点爬取:BeautifulSoup对象与Chrome显示内容不符的问题

问题描述

首次尝试爬取基于React的Booking.com搜索结果页,目标是收集特定酒店在固定条件下的实时价格。之前用简单CSS选择器就能爬取,但现在网站更新后,需要的元素都带含随机数的data-testid属性,旧代码直接失效。

尝试用Selenium捕获JS渲染的数据,再用BeautifulSoup解析,但返回的内容和浏览器显示完全不符:指定的入住退房日期、4位成人等URL参数没生效,本该排在首位的"cup of tea ensemble"酒店也不在对应位置。想知道爬React驱动的网站是不是常遇到这种情况,该怎么解决才能拿到和浏览器一致的数据。

附上当前使用的代码:

from bs4 import BeautifulSoup
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

booking_url = 'https://www.booking.com/searchresults.ja.html?lang=ja&ss=Takayama&dest_id=6411914&dest_type=hotel&checkin=2022-12-22&checkout=2022-12-23&group_adults=4&no_rooms=1&group_children=0&sb_travel_purpose=leisure'
#booking_url = 'https://www.google.co.jp/'

options = Options()
options.add_argument('--headless')

driver = webdriver.Chrome(executable_path='./chromedriver', chrome_options=options)
driver.get(booking_url)
html = driver.page_source.encode('utf-8')

soup = BeautifulSoup(html, 'html.parser')
print(soup)
解决方案

爬React这类动态渲染的网站确实容易遇到这类问题,核心原因大多是反爬拦截、页面未完全渲染或参数未被正确识别,以下是具体解决办法:

  • 优化无头浏览器配置,避免被反爬识别
    纯无头模式很容易被网站检测到,返回的内容会和普通浏览器不一致。可以添加模拟真实浏览器的参数:

    options.add_argument('--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')
    options.add_argument('--window-size=1920,1080')
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    
  • 等待页面完全渲染后再获取源码
    React加载数据需要时间,直接调用page_source可能拿到未加载完成的内容。用Selenium的显式等待,等待酒店列表等关键元素出现:

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    
    # 等待酒店列表容器加载完成,超时10秒
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, 'c82435a4b8')) # 替换为实际稳定的类名
    )
    html = driver.page_source.encode('utf-8')
    
  • 放弃URL参数,手动模拟用户操作填写条件
    部分网站会校验请求的上下文,直接传URL参数可能不生效。可以用Selenium手动点击选择日期、填写人数,模拟真实用户流程:

    # 示例:点击日期选择框,选择入住退房日期(需根据实际元素定位调整)
    checkin_input = driver.find_element(By.ID, 'checkin_date')
    checkin_input.clear()
    checkin_input.send_keys('2022-12-22')
    
    checkout_input = driver.find_element(By.ID, 'checkout_date')
    checkout_input.clear()
    checkout_input.send_keys('2022-12-23')
    
    # 选择4位成人(需根据实际元素定位调整)
    adult_count_btn = driver.find_element(By.CSS_SELECTOR, 'button[data-testid="occupancy-config"]')
    adult_count_btn.click()
    # 点击加号直到人数为4
    for _ in range(3): # 默认是1位,需要加3次
        driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Increase number of Adults"]').click()
    driver.find_element(By.CSS_SELECTOR, 'button[data-testid="occupancy-config-done"]').click()
    
    # 点击搜索按钮
    driver.find_element(By.CSS_SELECTOR, 'button[type="submit"]').click()
    
  • 优化元素定位策略
    避开带随机数的data-testid,优先用稳定的类名、元素文本或层级结构定位。比如要找目标酒店,可以先定位所有酒店名称的容器,再通过文本匹配:

    # 解析页面后找目标酒店
    hotels = soup.find_all('div', class_='c82435a4b8') # 稳定的酒店容器类名
    for hotel in hotels:
        hotel_name = hotel.find('h3', class_='d2fee87262').text.strip() # 稳定的酒店名称类名
        if hotel_name == 'cup of tea ensemble':
            # 提取价格等信息
            price = hotel.find('span', class_='f6431b446c').text.strip()
            print(f"目标酒店价格:{price}")
            break
    

内容的提问来源于stack exchange,提问作者pomme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 03:40:53