Python爬取充电器Web界面数据电压电流返回0.00问题求助
问题原因
你当前使用requests直接请求页面返回的是服务端初始HTML模板,充电器的实时电压、电流、安时数、运行时长数据都是前端JavaScript运行时通过异步请求拉取后端接口后,动态填充到对应ID的元素节点中的。初始模板中这些位置的默认值就是0.00或者空值,所以BeautifulSoup解析时无法获取到真实的实时数据。
解决方案
方案1:直接请求后端数据接口(推荐,性能最高、最稳定)
操作步骤:
- 打开浏览器访问充电器Web界面,按下
F12打开开发者工具,切换到「网络」标签,刷新页面后筛选「Fetch/XHR」类型的请求 - 逐个查看请求的返回内容,找到包含
voltage、current、MCBAmpere、MCBRunTime字段的接口请求 - 复制该接口的URL、请求头、鉴权参数,直接用
requests请求这个接口,解析返回的JSON即可直接拿到真实数值,无需解析HTML页面
方案2:使用无头浏览器模拟页面加载
如果接口有加密、鉴权逻辑不好复现,可以用Selenium等工具模拟浏览器完整加载页面,等待JS执行完成后再提取数据,示例修改如下:
import csv import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By import datetime end = 13.67 # 转为数值类型,后续比较不用转格式 def holedaten(driver): driver.get('http://mcb:8080/') # 也可以用显式等待指定目标元素加载完成,比固定sleep更高效 time.sleep(1) zeitaktuell = datetime.datetime.now() datum = zeitaktuell.strftime("%d-%m-%Y") uhrzeit = zeitaktuell.strftime("%H:%M:%S") Udev = driver.find_element(By.ID, 'voltageset').text Ubatt = driver.find_element(By.ID, 'voltage').text Ibatt = driver.find_element(By.ID, 'current').text Ahges = driver.find_element(By.ID, 'MCBAmpere').text mcbdauer = driver.find_element(By.ID, 'MCBRunTime').text return [datum, uhrzeit, Udev, Ubatt, Ibatt, Ahges, mcbdauer] if __name__ == '__main__': # 初始化无头Chrome浏览器,不用弹出可视窗口 chrome_options = Options() chrome_options.add_argument("--headless=new") # 注意要提前安装对应Chrome版本的ChromeDriver driver = webdriver.Chrome(options=chrome_options) # 提前传入登录鉴权信息,避免重复登录 driver.execute_script("return fetch('http://mcb:8080/', {headers: {'Authorization': 'Basic ' + btoa('admin:mcb')}})") with open('real_data.csv', 'w', newline='', encoding='utf-8') as csvfile: condition = True writer = csv.writer(csvfile, delimiter=';', quotechar='"', quoting=csv.QUOTE_MINIMAL) tst = ['Datum', 'Uhrzeit', 'Udev', 'Ubatt', 'Ibatt', 'Ahges', 'mcbdauer', 'Identdauer', 'Batterie'] writer.writerow(tst) while condition: daten = holedaten(driver) writer.writerow(daten) print(daten) # 注意要转成数值类型再比较,字符串比较是按字符顺序判断,结果不准确 if float(daten[3]) <= end: condition = False print("Wert erreicht!") # 控制请求频率,避免给设备造成压力 time.sleep(3) # 用完记得关闭浏览器进程 driver.quit()
额外注意点
你原有代码中电压判断逻辑是字符串直接比较,存在逻辑错误,需要将提取的电压值和阈值都转为float类型后再做大小比较。
内容的提问来源于stack exchange,提问作者Recep Güler
相关产品推荐
相关产品推荐

