能否用Beautiful Soup从动态图表提取指定时间的比特币价格?
解决CoinMarketCap图表特定时间点价格提取的思路
嘿,我刚好处理过类似的需求,直接用Beautiful Soup确实搞不定动态渲染的图表数据,但有几个靠谱的办法能实现你的目标,不用靠模拟鼠标移动:
1. 直接抓取后端API(最推荐)
CoinMarketCap的图表数据都是通过后端API加载的,根本不用跟前端交互。你可以用浏览器开发者工具(F12 → Network标签),筛选XHR/Fetch请求,找带ohlcv、history或者price关键词的接口。比如比特币的小时级历史价格接口,通常会允许你指定时间范围和数据频率(hourly)。
举个简单的实现步骤:
- 打开比特币页面,在Network里找到返回历史价格的API请求,复制它的URL和参数
- 用Python的
requests库发送GET请求,带上必要的参数(比如目标时间范围的时间戳、频率hourly) - 解析返回的JSON数据,找到和你目标时间
2017-12-15 04:49:51最接近的小时级数据点(因为是小时级,数据一般是每小时一个记录,比如04:00的价格)
示例代码大概是这样:
import requests from datetime import datetime # 把目标时间转成时间戳(根据API要求的格式,可能是秒或毫秒) target_time = datetime(2017, 12, 15, 4, 49, 51) timestamp = int(target_time.timestamp()) # 假设找到的API接口是这个(实际以你抓的为准) url = "https://api.coinmarketcap.com/data-api/v3/cryptocurrency/historical" params = { "id": "1", # 比特币的ID "convertId": "2781", # USD的ID "timeStart": timestamp - 3600, # 目标时间前1小时 "timeEnd": timestamp + 3600, # 目标时间后1小时 "interval": "hourly" } response = requests.get(url, params=params) data = response.json() # 遍历返回的价格数据,找到对应时间点 for entry in data["data"]["quotes"]: entry_time = datetime.fromtimestamp(entry["timestamp"] / 1000) print(f"时间: {entry_time}, 价格: {entry['quote']['price']}")
2. 提取页面隐藏的初始数据
有些时候,页面会把所有图表数据打包在某个<script>标签里(比如Next.js项目的__NEXT_DATA__),你可以用Beautiful Soup找到这个标签,提取里面的JSON内容:
from bs4 import BeautifulSoup import requests import json url = "https://coinmarketcap.com/currencies/bitcoin/" response = requests.get(url) soup = BeautifulSoup(response.text, "html.parser") # 找包含初始数据的script标签 script_tag = soup.find("script", id="__NEXT_DATA__") if script_tag: data = json.loads(script_tag.string) # 在data里找到历史价格相关的字段,不同版本可能位置不同 # 比如可能在data['props']['pageProps']['currency']['ohlcvHistorical'] historical_data = data["props"]["pageProps"]["currency"]["ohlcvHistorical"] # 然后筛选目标时间的数据
3. 用无头浏览器获取渲染后的数据
如果前两种方法都不行,还可以用Selenium或Playwright这类工具模拟浏览器加载页面,然后提取前端的全局变量或者图表数据:
from selenium import webdriver from selenium.webdriver.chrome.options import Options import json options = Options() options.add_argument("--headless=new") driver = webdriver.Chrome(options=options) driver.get("https://coinmarketcap.com/currencies/bitcoin/") # 执行JS代码获取页面里的价格数据 price_data = driver.execute_script("return window.__INITIAL_STATE__.cryptocurrency.details.ohlcv.hourly.data") # 解析数据,匹配目标时间 driver.quit()
为什么直接用Beautiful Soup不行?
你看到的鼠标移动才显示的价格,是前端通过JavaScript从内存里的数据集动态渲染的,这些数据不会出现在初始的HTML源码里,所以Beautiful Soup只能拿到静态内容,抓不到动态加载的数据集。
总结一下,优先用API的方法,最稳定也最高效,不用处理前端渲染的各种问题。
内容的提问来源于stack exchange,提问作者Jcmoney1010
相关产品推荐
相关产品推荐

