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

使用Selenium爬取Octopus Energy数据遇NoneType属性错误及优化需求

解决Octopus Energy仪表读数提取问题

问题核心

  1. 直接抓取MeterReadingHistory__content的文本会得到拼接后的混乱内容,需拆分出日期和读数;
  2. 定位动态生成的类名MeterReadingHistorystyled__StyledReadingsContainer-sc-1mqak03-0.cEwaaW时返回None,触发AttributeError。

为什么定位容器失败?

  • 动态类名不稳定:这类带随机后缀的类名是Styled Components等前端框架自动生成的,页面更新或刷新后可能变化;
  • 未等待元素加载:直接调用find_element时,目标元素可能还未渲染完成;
  • 元素结构变化:可能该容器类名已被前端修改,或元素嵌套在未切换的iframe中(需检查页面结构确认)。

高效提取方案(无需正则)

方法1:定位单个读数条目

利用页面结构中每个读数的独立容器,通过显式等待确保元素加载后提取:

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

# 登录后等待读数区域加载完成
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "MeterReadingHistory__content")))

# 定位所有独立的读数条目(需根据实际页面结构调整选择器)
reading_items = wait.until(EC.presence_of_all_elements_located(
    (By.XPATH, "//div[contains(@class, 'MeterReadingHistory__reading')]")
))

data = []
for item in reading_items:
    # 从条目内提取日期和读数(根据页面元素结构调整子元素选择器)
    date = item.find_element(By.XPATH, ".//span[contains(@class, 'MeterReadingHistory__date')]").text
    reading = item.find_element(By.XPATH, ".//span[contains(@class, 'MeterReadingHistory__value')]").text
    data.append({"日期": date, "读数": reading})

# 转换为DataFrame
df = pd.DataFrame(data)
print(df)

方法2:基于文本内容定位

如果类名过于动态,可通过固定文本(如"Your reading")反向定位关联元素:

# 提取所有读数对应的日期和数值
dates = wait.until(EC.presence_of_all_elements_located(
    (By.XPATH, "//div[contains(text(), 'Your reading')]/preceding-sibling::div")
))
readings = wait.until(EC.presence_of_all_elements_located(
    (By.XPATH, "//div[contains(text(), 'Your reading')]/following-sibling::div")
))

# 打包数据并生成DataFrame
data = list(zip([d.text.strip() for d in dates], [r.text.strip() for r in readings]))
df = pd.DataFrame(data, columns=["日期", "读数"])

修复NoneType错误的要点

  1. 验证元素存在性:打开浏览器开发者工具,搜索目标类名,确认元素是否真实存在;
  2. 改用显式等待:替换driver.find_element为等待方法,避免元素未加载时查找:
    container = wait.until(EC.presence_of_element_located(
        (By.CLASS_NAME, "MeterReadingHistorystyled__StyledReadingsContainer-sc-1mqak03-0.cEwaaW")
    ))
    
  3. 检查iframe:如果读数区域嵌套在iframe中,需先切换到iframe再定位元素:
    iframe = wait.until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))
    driver.switch_to.frame(iframe)
    # 之后再执行元素定位
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:47:21