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

如何抓取AEMO网站script标签内的30分钟电价需求表数据?

解决AEMO可视化页面Selenium爬取数据的问题

我来帮你搞定这个问题!你遇到的情况是典型的单页应用(SPA)动态渲染问题——AEMO这个页面用了Aurelia框架,初始返回的HTML只是启动框架的脚本,实际的按钮、表格都是JS运行后才生成的,所以你直接拿page_source只能看到那些加载用的标签。下面给你两种可行的解决方案:

方法一:改进Selenium的等待与交互逻辑

我们需要让Selenium等待页面完全渲染,再定位并点击按钮,最后提取表格数据。修改后的代码如下:

import pandas as pd
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

url = "https://www.aemo.com.au/aemo/apps/visualisations/elec-nem-priceanddemand.html"
browser = webdriver.Safari(executable_path='/usr/bin/safaridriver')
browser.get(url)

try:
    # 等待加载动画消失,确认页面框架初始化完成
    WebDriverWait(browser, 30).until(
        EC.invisibility_of_element_located((By.CLASS_NAME, "splash"))
    )
    
    # 等待"显示表格"按钮可点击(建议用浏览器F12确认按钮的准确选择器,比如xpath/class)
    show_table_btn = WebDriverWait(browser, 20).until(
        EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Show Table')]"))
    )
    show_table_btn.click()
    
    # 等待表格主体加载完成
    WebDriverWait(browser, 20).until(
        EC.presence_of_element_located((By.TAG_NAME, "tbody"))
    )
    
    # 直接用pandas读取页面中的表格数据
    df = pd.read_html(browser.page_source)[0]
    print("抓取到的前5行数据:")
    print(df.head())
    
except Exception as e:
    print(f"执行出错: {str(e)}")
finally:
    browser.quit()

关键注意事项:

  • 按钮的选择器可能随页面更新变化,一定要自己用浏览器开发者工具(F12)确认准确的xpath、class或id。
  • 等待时间可以根据你的网络状况调整,30秒足够应对大多数加载场景。

方法二:直接调用AEMO的API(更高效稳定)

其实这类可视化页面的数据都是通过后台API获取的,跳过模拟浏览器直接请求API是更优的方案——速度快、资源占用低,还能避免元素定位失败的问题。

你可以通过浏览器的「网络面板」(F12 → Network)查看页面的XHR请求,找到数据源接口。下面是一个示例代码:

import requests
import pandas as pd

# 替换为你从网络面板获取的实际API地址
api_url = "https://api.aemo.com.au/aemo/data/nem/priceanddemand/5min/latest?rows=200"
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15"
}

response = requests.get(api_url, headers=headers)
if response.status_code == 200:
    data = response.json()
    df = pd.DataFrame(data)
    print("API返回的前5行数据:")
    print(df.head())
else:
    print(f"请求失败,状态码: {response.status_code}")

为什么推荐这个方法?

  • 无需启动浏览器,性能开销极小,批量爬取时优势明显。
  • 数据是结构化的JSON格式,直接解析即可,不用处理HTML表格的各种兼容问题。
  • 避开了Selenium可能遇到的反爬策略、元素定位失效等问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:53:08