电费、话费、宽带:AI 帮你找出账单里能砍的部分(2026 实测)

订阅的问题是「忘了」,账单的问题是「只知道总数」。每月交三百块电费、一百多话费,交了几年,很少有人说得清钱具体花在哪——是空调、是热水器、还是那台常年待机的旧设备。不知道构成,就没有优化的着力点。

所以这条路径的顺序和别的不同:先量化,再优化。跳过量化直接省,结果通常是牺牲了体验却没省下多少。这篇按电费、话费宽带、票据归档三块给具体做法。

电费:先找出真正的耗电大户

电费是账单里最容易出现「结构性异常」的一项,因为它对设备状态极其敏感。常见的几种情况:

  • 热水器温控故障,持续加热不停机,一个月多出上百元
  • 冰箱门密封条老化,制冷效率下降,悄悄多耗电
  • 一台老旧设备常年待机,功率不大但一天 24 小时
  • 电暖器、除湿机这类大功率设备被当成常用电器

这些都不会以「故障」的形式表现出来——设备看起来在正常工作,只是账单在涨。唯一的发现方式是按设备计量用电。

硬件门槛比想象中低。最省事的起点是带功率计量的智能插座,几十块一个,插上就能读到实时功率和累计电量,先测几个你最怀疑的设备。要做到全屋级别,才需要导轨式电表通过 Modbus 之类的方式接入。给出一个常见的精度参考:

方案 精度 成本 适合
带计量的智能插座 ±5%–10% 低 定位单个设备,找异常最实用
导轨式电表 + Modbus 接入 ±1% 中 全屋总表,做长期趋势

重要提示:插座类计量的误差可能有几个百分点,用来做「哪个设备更耗电」的相对比较没问题,用来核对电费账单不合适。核对账单看总表。

用 Home Assistant 做能耗看板

Home Assistant 是开源的家庭自动化平台,它的能源模块基本就是为这个场景准备的:设备级能耗排行、每日/每月趋势、分时电价计算、异常告警。核心是三块配置。

第一步是把实时功率换算成累计电量。很多设备只提供瞬时功率,需要一个积分传感器把它累积起来:

sensor:
  - platform: integration
    name: "今日用电"
    source_sensor: sensor.living_room_power
    unit_prefix: k
    integration_method: trapezoidal
    round: 2

第二步是把电价按峰谷分开配置。这一步直接决定你能不能看出「省钱空间在哪」——只配一个平均电价,峰谷优化的收益就无从计算:

energy:
  grid_sources:
    - source: sensor.total_grid_power
      tariffs:
        - name: "峰时"
          start: "08:00"
          end: "22:00"
          price: 0.60
        - name: "谷时"
          start: "22:00"
          end: "08:00"
          price: 0.30

第三步是异常告警。持续高功率远比瞬时峰值更值得警惕——瞬时超一下可能是空调启动,持续十几分钟以上就可能是设备故障:

automation:
  - alias: "功率超标告警"
    trigger:
      - platform: numeric_state
        entity_id: sensor.total_power
        above: 2000
        for:
          minutes: 10
    action:
      - service: notify.mobile_app
        data:
          title: "功率告警"
          message: "总功率超过 2000W 已持续 10 分钟,检查是否有设备异常"

峰谷电价这块的收益最直接:把可推迟的用电(洗衣机、洗碗机、热水器、充电桩)安排到谷时,在峰谷价差三毛左右的情况下,每往谷时挪一百度电大约省三十元。关键是先知道自己的谷时占比是多少——很多人配了分时电价后才发现,谷时用电只占两成,说明大部分可推迟的用电其实没挪。

账单趋势:用脚本找出异常月份

如果没有条件上硬件,退一步也能做——把过去 12 个月的账单整理成表格,用脚本做同比环比分析。异常月份会自己浮出来,然后针对那几个月份回忆发生了什么。

import csv
import sys


def width(s):
    return sum(2 if ord(c) > 0x2E80 else 1 for c in s)


def pad(s, n):
    return s + " " * max(0, n - width(s))


def f(v):
    v = str(v).replace(",", "").replace("¥", "").replace("¥", "").strip()
    v = "".join(c for c in v if c.isdigit() or c == "." or c == "-")
    return float(v) if v else None


def load(path):
    with open(path, encoding="utf-8-sig") as fh:
        rd = csv.DictReader(fh)
        cols = {c.strip().lower(): c for c in rd.fieldnames if c}
        pk = next((cols[k] for k in ("账期", "月份", "period", "month") if k in cols), None)
        qk = next((cols[k] for k in ("用量", "电量", "kwh", "用量(kwh)") if k in cols), None)
        ak = next((cols[k] for k in ("金额", "费用", "amount", "电费") if k in cols), None)
        vk = next((cols[k] for k in ("谷时用量", "谷", "valley") if k in cols), None)
        if not (pk and qk and ak):
            sys.exit("CSV 需要 账期 / 用量 / 金额 三列,当前表头:%s" % rd.fieldnames)
        rows = []
        for r in rd:
            p = str(r[pk]).strip().replace("/", "-")
            q, a = f(r[qk]), f(r[ak])
            if not p or q is None or a is None:
                continue
            v = f(r[vk]) if vk else None
            rows.append({"p": p[:7], "q": q, "a": a, "v": v, "unit": a / q if q else 0})
        rows.sort(key=lambda x: x["p"])
        return rows


def main():
    path = sys.argv[1] if len(sys.argv) > 1 else "bill.csv"
    rows = load(path)
    if not rows:
        sys.exit("没有解析到数据")

    avg = sum(r["a"] for r in rows) / len(rows)
    avgq = sum(r["q"] for r in rows) / len(rows)
    print("共 %d 期,月均 %.1f 度 / %.2f 元,均价 %.3f 元/度" % (
        len(rows), avgq, avg, avg / avgq if avgq else 0))
    print("-" * 74)
    print(pad("账期", 11) + pad("用量", 10) + pad("金额", 10) +
          pad("环比", 10) + pad("同比", 10) + pad("单价", 8))
    print("-" * 74)

    spikes = []
    for i, r in enumerate(rows):
        prev = rows[i - 1] if i else None
        yoy = None
        for old in rows[:i]:
            if old["p"][5:] == r["p"][5:] and old["p"][:4] != r["p"][:4]:
                yoy = old
        mom = (r["a"] - prev["a"]) / prev["a"] * 100 if prev and prev["a"] else None
        yr = (r["a"] - yoy["a"]) / yoy["a"] * 100 if yoy and yoy["a"] else None
        if mom is not None and mom > 30:
            spikes.append((r["p"], "环比 +%.0f%%" % mom))
        if r["a"] > avg * 1.5:
            spikes.append((r["p"], "高于均值 50%"))
        print(pad(r["p"], 11) + pad("%.1f" % r["q"], 10) + pad("%.2f" % r["a"], 10) +
              pad(("%+.0f%%" % mom) if mom is not None else "-", 10) +
              pad(("%+.0f%%" % yr) if yr is not None else "-", 10) +
              pad("%.3f" % r["unit"], 8))

    print("-" * 74)
    if spikes:
        print("需要回看的月份:")
        for p, why in spikes:
            print("  %s  %s" % (p, why))
    else:
        print("没有明显异常月份")

    valleys = [r for r in rows if r["v"] is not None]
    if valleys:
        cut = sum(r["v"] for r in valleys) / sum(r["q"] for r in valleys)
        print("n谷时用电占比 %.0f%%" % (cut * 100))
        if cut < 0.3:
            print("  占比偏低:把可推迟的用电(洗衣机、热水器、充电桩)挪到谷时,")
            print("  按峰谷价差 0.3 元/度算,每挪 100 度约省 30 元。")


if __name__ == "__main__":
    main()

用一份 12 期电费数据跑出来的结果:

共 12 期,月均 312.9 度 / 178.50 元,均价 0.570 元/度
--------------------------------------------------------------------------
账期       用量      金额      环比      同比      单价
--------------------------------------------------------------------------
2026-01    320.0     182.00    -         -         0.569
2026-02    290.0     165.00    -9%       -         0.569
2026-03    240.0     137.00    -17%      -         0.571
2026-04    205.0     117.00    -15%      -         0.571
2026-05    230.0     131.00    +12%      -         0.570
2026-06    410.0     234.00    +79%      -         0.571
2026-07    520.0     297.00    +27%      -         0.571
2026-08    480.0     274.00    -8%       -         0.571
2026-09    260.0     148.00    -46%      -         0.569
2026-10    210.0     120.00    -19%      -         0.571
2026-11    250.0     143.00    +19%      -         0.572
2026-12    340.0     194.00    +36%      -         0.571
--------------------------------------------------------------------------
需要回看的月份:
  2026-06  环比 +79%
  2026-07  高于均值 50%
  2026-08  高于均值 50%
  2026-12  环比 +36%

谷时用电占比 23%
  占比偏低:把可推迟的用电(洗衣机、热水器、充电桩)挪到谷时,
  按峰谷价差 0.3 元/度算,每挪 100 度约省 30 元。

三个有用的视角:

单价列比总金额更有诊断价值。用量随季节变化是正常的,但如果单价开始往上走,说明要么档位进了更高阶梯,要么电价调整了——这两种情况的应对方式完全不同。

同比比环比更可信。电费天然有季节性,六月比五月高 79% 可能只是开空调了。真正要看的是「今年六月比去年六月高多少」,那才是变化。脚本在有跨年数据时会自动算这一列。

连续几个月亮黄灯比单月异常更值得查。单月异常往往有解释,连续三个月高于均值就可能是设备状态变化或者家庭用电结构变了。

话费与宽带:没有一键方案,但有明确做法

说清楚一个现实:话费和宽带套餐没有能直接替你优化的开源工具,因为改套餐涉及运营商合约、绑定业务和地区资费差异,任何脚本都碰不到这一层。

但 AI 在这件事上有两个明确用途:

第一,把账单明细贴给 AI,让它挑出「你在付费但可能不需要」的项。话费账单里常见的冗余包括:已经不用的增值业务包、超出实际需求的流量加装包、被默认开通的彩铃/视频会员、副卡长期闲置但仍在计费。这些项目名往往很含糊,人一眼扫过去会跳过,让 AI 逐条解释「这个是什么、一般多少钱、常见开通原因」,识别率会高很多。

第二,把要问的问题列成清单再去沟通。打客服电话或者去营业厅之前,先明确三件事:当前套餐的确切内容、合约期还剩多久、有没有违约金。这三条问清楚,再谈降档或者换套餐就不会被话术带走。合约期内换套餐通常要付违约金,这一点最容易在推销中被模糊掉。

票据归档:让账单变得可检索

账单类的支出还有个隐性成本:需要的时候找不到。报账、维权、保修、税务,都要翻纸质或散落的 PDF。这件事也有成熟的开源方案。

Paperless-ngx 是目前最主流的开源文档管理系统。把扫描件或 PDF 丢进一个「收件」目录,它自动 OCR、提取文字、按规则打标签和分类(比如识别到「电费」就归到水电费类),之后可以用关键词直接搜到。中文文档需要在配置里显式指定 OCR 语言(设成 chi_sim),否则默认只装了几种西文语言,中文识别会失效。

它的实际用处集中在三处:账单按年月归档后可检索、保修期内快速找到购买凭证、以及长期留存的账单本身就是趋势分析的数据源——三年后你还能查到当时的电价和用量。

几个容易踩的坑

智能插座精度不足以结算。±5%–10% 的误差用于设备间比较没问题,拿来核对电费会产生无意义的争论。要对账就用总表。

先改习惯,再改设备。很多人一上来就换电器,其实待机功耗、峰谷安排、温度设定这些零成本的调整,收益往往比换设备更快更明显。

峰谷优化要算上设备是否支持定时。老设备没有预约功能,硬挪到谷时意味着要人去按开关——这种「省」坚持不了两周。

改套餐前先确认合约期。这是话费类支出最容易吃亏的地方,违约金可能高于你一年省下的钱。

数据别裸奔。Home Assistant 和 Paperless-ngx 都涉及家庭内部数据。要远程访问就加一层反向代理和认证,不要直接把端口暴露在公网上。

国内真正能去办的三件事

量化之后要落到动作上。国内用户可以直接去办的,主要是这三件:

第一,分时电价。部分地区对居民用电提供峰谷分时的计价方式,是否可办、怎么申请、峰谷时段如何划分,各地差异较大,以当地供电公司的公告和官方渠道的说明为准。申请前建议先用本文的脚本算出自己当前谷时用电占比——占比很低的话,办了也省不了多少。

第二,话费降档。这是国内账单里最容易省下钱的一项,但流程比想象中有讲究:合约要自查、渠道要走官方、被拒之后还有两级维权路径(集团投诉专线、工信部电信用户申诉)。申诉有前置条件,必须先向运营商投诉过,完整路径和话术见话费宽带降档被拒怎么办。

第三,账单与票据归档。电费、话费的历史账单本身就是趋势数据;而维权(降档申请、押金纠纷、保修索赔)需要的截图和凭证,平时归档好,用时才拿得出来。中文票据的离线识别与自动归类见票据本地 OCR 归档。

另外,如果你考虑用开源工具替代一部分订阅来降低固定支出,可对照国产开源替代清单,里面按「值得替代」和「不值得折腾」做了区分。

常见问题

不买智能插座,能找出耗电大户吗?

能做粗略判断。方法是用总表的每日数据配合「控制变量」:某一天刻意不用某个设备,对比前后几天的用电量差异。缺点是慢、需要多次试验,而且没法区分同时段的多个设备。如果只是想知道「是不是某台设备有问题」,先租或者借一个计量插座测两天,成本几乎为零。

Home Assistant 上手难度高吗?

比一般的软件要高一些,但能源模块本身配置不复杂——核心就是三个配置文件段落(积分传感器、电价、告警)。真正的门槛在于你得先有能提供功率数据的硬件,没有硬件的话这套系统就没有数据源。所以建议的顺序是:先用一个计量插座测出值得关注的设备,再决定要不要铺开做整体监控。

这些优化一共能省多少?

没有统一答案,取决于你现在的账单结构。但有个稳定的规律:账单里的浪费通常是「少数几项占大头」,而不是平均分布。所以收益高度依赖于能不能定位到那几项。这也是为什么所有方法的第一步都是量化——不是为了省得精细,而是为了找到那几项值得动手的地方。

延伸阅读

评论 (0)