网页爬取:审查元素与soup.prettify输出差异及爬取方式对比
关于ICE布伦特原油期货页面爬取的两个技术问题
1. 为何soup对象中能看到contracts字典列表,浏览器审查元素却看不到?
这是因为页面表格是前端JavaScript动态渲染的结果:
- 用
requests获取到的是服务器返回的原始HTML,其中包含未执行的JS代码,contracts字典列表就是渲染表格的原始数据源,所以soup能解析到这部分内容。 - 浏览器打开页面时会自动执行JS,把
contracts里的数据转换成你看到的<table>表格DOM元素,此时审查元素显示的是渲染后的最终结构,原始的contracts数据已被JS处理,自然看不到。
2. 两种爬取方式的差异、优劣及实现方法
差异对比
| 维度 | 基于CSS选择器爬取(需渲染DOM) | 解析soup中的字典列表 |
|---|---|---|
| 依赖环境 | 需要浏览器/无头浏览器(如Selenium),依赖JS渲染页面 | 仅需requests+bs4,无需执行JS |
| 数据来源 | 渲染后的DOM表格 | 服务器返回的原始数据源 |
| 效率 | 慢(需等待渲染),资源占用高 | 快,资源占用低 |
| 反爬风险 | 易被检测(模拟浏览器行为) | 风险较低(普通HTTP请求) |
| 稳定性 | 易受页面布局变更影响(CSS类名、列顺序改动就失效) | 数据源结构相对稳定(后端字段一般不会频繁修改) |
哪种更优?
优先选择解析soup中的字典列表。原因:
- 直接获取后端原始数据,无渲染开销,速度更快;
- 数据结构更稳定,不像前端DOM易随页面改版变化;
- 无需依赖浏览器环境,部署维护更简单。
仅当原始HTML中找不到数据源、必须依赖JS渲染才能获取数据时,才考虑CSS选择器+Selenium的方式。
实现方法
方法1:解析soup中的contracts字典列表
import requests from bs4 import BeautifulSoup import json url = "https://www.theice.com/products/219/Brent-Crude-Futures/data?marketId=5166946" 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(url, headers=headers) soup = BeautifulSoup(response.text, "html.parser") # 遍历script标签,定位包含contracts的内容 for script in soup.find_all("script"): if script.string and '"contracts"' in script.string: # 提取contracts对应的JSON数组 content = script.string start_idx = content.find('"contracts":') + len('"contracts":') end_idx = content.find(']', start_idx) + 1 contracts_data = json.loads(content[start_idx:end_idx]) break # 筛选并打印Sep22合约数据 for contract in contracts_data: if contract["contractMonth"] == "Sep22": print(f"合约月份: {contract['contractMonth']}, 最新价格: {contract['last']}")
方法2:基于CSS选择器爬取(需Selenium)
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options import time url = "https://www.theice.com/products/219/Brent-Crude-Futures/data?marketId=5166946" # 配置无头Chrome,避免弹出浏览器窗口 chrome_options = Options() chrome_options.add_argument("--headless=new") chrome_options.add_argument("--disable-gpu") chrome_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") driver = webdriver.Chrome(options=chrome_options) driver.get(url) # 等待页面渲染完成(时间可根据网络情况调整) time.sleep(3) # 用CSS选择器定位表格行,筛选Sep22合约 table_rows = driver.find_elements(By.CSS_SELECTOR, ".table.table-bigdata tbody tr") for row in table_rows: month = row.find_element(By.CSS_SELECTOR, "td:first-child").text.strip() if month == "Sep22": last_price = row.find_element(By.CSS_SELECTOR, "td:nth-child(3)").text.strip() print(f"合约月份: {month}, 最新价格: {last_price}") driver.quit()
内容的提问来源于stack exchange,提问作者redpowertie
相关产品推荐
相关产品推荐

