Metabase统计日用水电量

获取剩余水电信息

原理:使用selenium库自动化爬取租房水电信息

在linux中配置定时运行脚本,定期爬取信息存储在本地csv文件中,并同步到数据库中,作为大数据可视化平台数据源。

本人的租房后端数据为剩余水电量

  • 数据库初始化语句
1
2
3
4
5
6
7
CREATE TABLE utility_usage (
id INT AUTO_INCREMENT PRIMARY KEY,
room_number INT,
remaining_water FLOAT,
remaining_electricity FLOAT,
date DATE
);
  • python程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import re
import csv
from datetime import datetime
import mysql.connector

def extract_numbers(text):
# 使用正则表达式匹配所有数字
numbers = re.findall(r'\d+\.\d+|\d+', text)
# 将匹配到的数字连接成一个字符串
return ''.join(numbers)

def extract_info():

chrome_options = Options()
chrome_options.add_argument("headless")
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument("--window-size=1920x1080")

# 初始化浏览器
driver = webdriver.Chrome(options=chrome_options)

# 打开目标网站
driver.get('https://xxxxx/login') # 请替换为你的目标网站URL

# 使用XPATH定位输入框
username_field = driver.find_element(By.XPATH, '//input[@type="tel" and @placeholder="请输入手机号"]')
password_field = driver.find_element(By.XPATH, '//input[@type="password" and @placeholder="请输入密码"]') # 请替换为实际的密码输入框的XPATH
#
username_field.send_keys('xxxxxx') # 请替换为你的用户名
password_field.send_keys('xxxxxxx') # 请替换为你的密码
password_field.send_keys(Keys.RETURN)

# 点击登录按钮
login_button = driver.find_element(By.XPATH, '//button[contains(@class, "van-button") and .//span[text()="登录"]]')
login_button.click()

# 等待页面加载
time.sleep(2)

# 点击“我的”
my_button = driver.find_element(By.XPATH, '//div[contains(@class, "van-tabbar-item") and .//span[text()="我的"]]') # 请替换为实际的“我的”按钮的XPATH
my_button.click()

# 等待页面加载
time.sleep(2)

# 点击“缴费充值”
recharge_button = driver.find_element(By.XPATH, '//div[contains(@class, "tabcoloritem") and .//p[text()="缴费充值"]]') # 请替换为实际的“缴费充值”按钮的XPATH
recharge_button.click()

# 等待页面加载
time.sleep(2)
#
# 点击“充值”
top_up_button = driver.find_element(By.XPATH, '//div[contains(@class, "tabTitle2Grey") and text()="充值"]') # 请替换为实际的“充值”按钮的XPATH
top_up_button.click()

# 等待页面加载
time.sleep(5)

# 获取“房间号”、剩余水、剩余电信息
room_number = driver.find_element(By.XPATH, '//div[contains(@style, "font-size: 14px") and contains(@style, "font-weight: 600")]').text
remaining_water = driver.find_element(By.XPATH, '//p[contains(@class, "red") and contains(text(), "吨")]').text
remaining_electricity = driver.find_element(By.XPATH, '//p[contains(@class, "red") and contains(text(), "度")]').text

room_number = extract_numbers(room_number)
remaining_water = extract_numbers(remaining_water)
remaining_electricity = extract_numbers(remaining_electricity)

# 关闭浏览器
driver.quit()
# 获取当前日期
current_date = datetime.now().strftime('%Y-%m-%d %H:%M')
info = [int(room_number), float(remaining_water), float(remaining_electricity), current_date]

return info

def append_to_csv(info, csv_file_path):
# 打开CSV文件,准备写入
with open(csv_file_path, mode='a', newline='') as file:
writer = csv.writer(file)
# 写入信息
writer.writerow(info)


def insert_into_mysql(info, db_config):
# 连接到MySQL数据库
connection = mysql.connector.connect(**db_config)
cursor = connection.cursor()

# 插入数据的SQL语句
insert_query = "INSERT INTO utility_usage (room_number, remaining_water, remaining_electricity, date) VALUES (%s, %s, %s, %s)"

# 执行插入操作
cursor.execute(insert_query, info)

# 提交事务
connection.commit()

# 关闭连接
cursor.close()
connection.close()

if __name__ == "__main__":
# CSV文件路径
csv_file_path = 'output.csv'

# MySQL数据库配置
db_config = {
'host': 'xxx.xxx.xxx.xxx',
'user': 'xxxx',
'password': 'xxxx',
'database': 'xxxxx'
}

# 提取信息
info = extract_info()

# 写入CSV文件
append_to_csv(info, csv_file_path)

# 插入到MySQL数据库
insert_into_mysql(info, db_config)

print(info)
  • 数据库表结构
id room_number remaining_water remaining_electricity date
1 8212 2.96 82.58 2024-08-05 19:08:00
2 8212 2.96 82.55 2024-08-05 19:36:00

Metabase数据可视化平台接入

官网地址

Metabase部署(docker)

1
2
docker pull metabase/metabase:latest
docker run -d -p 12345:3000 --name metabase metabase/metabase

启动时会提示接入数据库

数据接入

  • 创建新集合utility

创建问题剩余电

该数据集统计数据库中所有的记录,即30分钟一次的剩余电量数据。

数据源选择表utility_usage

汇总选择自定义表达式便于重命名

  • 自定义表达式
1
Sum([Remaining Electricity])


进行可视化

创建日剩余电

该数据集统计每日剩余电量的最小值,即每日的最后一次记录代表该日的剩余电量。

  • 自定义表达式获取当天剩余电量的最小值
1
Min([Remaining Electricity])

  • Date格式选择按天

统计日消耗量

能爬取到的数据只有剩余量,想要统计日消耗量,暂时选择用当日最小值减去前日最小值,即当日日剩余电量减去前一日日剩余电量。

充钱那天肯定出问题后边再想办法解决。

  • 先创建前一日日剩余电量数据集
1
2
-- 创建自定义列,使日期加1
datetimeAdd([Date], 1, "day")

  • 汇总选择获取最小值并通过自定义日期列汇总
1
Min([Remaining Electricity])

  • 创建日耗电数据表

  • 使用当日最小值汇总

  • 用本表Date与前一天剩余电量表的y_Date联合

  • 创建自定义日耗电字段
1
case([前一天剩余电 - Date: Day → y_ele] >= [x_ele], [前一天剩余电 - Date: Day → y_ele] - [x_ele], 0)

  • 同理创建水消耗量的数据表

仪表展示


Metabase统计日用水电量
https://blog.erhuoyan.cn/2024/08/06/98f9dcf28f84/
作者
erhuoyan
发布于
2024年8月6日
许可协议