Looopでんき スマートタイムONEの価格情報を取得する方法

こんにちは。
我が家ではLooopでんきという基本料がタダで時間によって料金が変わるものを使ってみます。
なにかで価格情報を取得できたらいいなと思い作ってみました。

# !!警告!!
:::note alert
この記事ではLooopでんきの**非公式API(公式のサイトだけど公式から案内されていない)** を利用しています。利用規約はよく見ていませんがなにかに触れるかもしれません。また、なにかあっても公式からのサポートはないので自己責任でお願いします。
:::

# データがどこに有るか探す
下の公式ページからでんき予報が見れます。

https://looop-denki.com/home/denkiforecast/

エリアを選択すると今のkWhあたりの価格とその後の価格が見れます。
明日の単価は前日の16:00から反映されるようです。

# でんき日和等の算出条件
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518724/391fc156-f5e9-9e91-1c9a-2a982fac215c.png)

また、「でんき日和」や「でんき注意報」、「でんき警報」で分類もされてて、算出条件は以下のとおりです。(上記サイトから引用)

## 平日算出方法

|種類|算出方法|
|:-:|:-:|
|でんき日和|当日を除く過去5日間のJEPX平均値より5円以上低い単価のうち、最も低い10コマ|
|でんき注意報|当日を除く過去5日間のJEPX平均値より5円以上高い単価のうち、最も高い10コマ|
|でんき警報|JEPX平均価格が100円を超える全コマ|

## 土日祝日算出方法
|種類|算出方法|
|:-:|:-:|
|でんき日和|当日を除く過去**3**日間のJEPX平均値より5円以上低い単価のうち、最も低い10コマ|
|でんき注意報|当日を除く過去**3**日間のJEPX平均値より5円以上高い単価のうち、最も高い10コマ|
|でんき警報|JEPX平均価格が100円を超える全コマ|

平日は過去5日間ですが、土日祝は3日間になっています。
最初「JEPXってなんなんだよ！！」と若干キレながら調べたら「一般社団法人 日本卸電力取引所」らしいです。

https://www.jepx.jp/

メタタグのdescriptionには、
> 一般社団法人 日本卸電力取引所は、我が国で唯一の卸電力取引市場を開設・運営する取引所です。

と書いてありました。電気の取引所らしいです。

今回は別によく分からなくてもいいので飛ばします。

# API
開発者コンソールを開いて眺めていると発見しました。

「looop-denki.com/api/prices?select_area=(エリアコード)」
エリアコードは以下のようになっています。
| 電力会社 | エリアコード |
|:-:|:-:|
| 北海道電力 | 01|
| 東北電力 | 02 |
| 東京電力 | 03 |
| 中部電力 | 04 |
| 北陸電力 | 05 |
| 関西電力 | 06 |
| 中国電力 | 07 |
| 四国電力 | 08 |
| 九州電力 | 09 |
| 沖縄電力 | 10 |

僕の住んでる関西電力の場合は
「looop-denki.com/api/prices?select_area=06」
のようになります。

ここにアクセスすると次のようなJSONでデータをもらえます。

<details><summary>JSONデータ</summary>

~~~json:looop-denki.com/api/prices?select_area=06
{
	"0": {
		"price_data": [
			15.39,
			15.04,
			14.93, ...
		],
		"level": [
			0,
			0,
			0, ...
		],
		"text": {
			"1": {
				"price": 15.39,
				"level": 0
			},
			"2": {
				"price": 15.04,
				"level": 0
			},
			"3": {
				"price": 14.93,
				"level": 0
			}...
		},
		"yAxes_max": 40,
		"yAxes_min": 0
	},
	"label": [
		"0",
		"0.5",
		"1" ...
	],
	"timelist": [
		"0:00~0:29",
		"0:30~0:59",
		"1:00~1:29" ...
	]
 2まで
}
~~~
</details>
クソ長いので短くしてあります。

本家ではグラフ表示もあるため余計に色々データが入っていました。
まず最初に "0" "1" "2" とあり、0=昨日 1=今日 2=明日 となっています。
次にprice_dataには価格がカンマ切りで入っています。
levelはでんき日和などのデータで 0=なし -0.5=でんき日和 0.5=でんき注意報 1=でんき警報となっています。
その下のtextには上記がいい感じにまとまって入っています。
label(下)とtimelistはグラフの軸用だと思います。

# 完成したプログラム
## main.py(現在の時間のみ表示)
~~~python:main.py
import requests
import json
from datetime import datetime

print("""

Looopでんき スマートタイムONE(電灯)
でんき単価取得

作者: 小川 智也(https://ogatomo.net/)

""")

# エリアコード
# area.mdをご覧ください

# e.x. 関西電力 = 06
area = "06"

if area == "01" :
    area_name = "北海道"
elif area == "02" :
    area_name = "東北"
elif area == "03" :
    area_name = "東京"
elif area == "04" :
    area_name = "中部"
elif area == "05" :
    area_name = "北陸"
elif area == "06" :
    area_name = "関西"
elif area == "07" :
    area_name = "中国"
elif area == "08" :
    area_name = "四国"
elif area == "09" :
    area_name = "九州"
elif area == "10" :
    area_name = "沖縄"
else:
    area_name = "(不明)"

now = datetime.now()
now_time = now.strftime('%Y年%m月%d日 %H:%M:%S')

print(f"==========\nエリア: {area} {area_name}電力\n現在は{now_time}です。\n==========\n")

url = f'https://looop-denki.com/api/prices?select_area={area}'
headers = {"content-type": "application/json"}
r = requests.get(url,headers=headers)

text = r.json()
#r_json = json.dumps(text, indent=4)
# print(r_json)

# 今日を取得
today = text["1"]["text"]
#print(today)

current_time = now.time()
total_minutes = current_time.hour * 60 + current_time.minute
interval_number = (total_minutes // 30) + 1

for i in range(1,48,1):
    if i == interval_number:
        priceNo = str(i)
        price = today[priceNo]["price"]
        time = text["timelist"][i-1]
        if today[priceNo]["level"] == -0.5 :
            biyori = "でんき日和"
        elif today[priceNo]["level"] == 0.5 :
            biyori = "でんき注意報"
        elif today[priceNo]["level"] == 1 :
            biyori = "でんき警報"
        else:
            biyori = ""
        print(f"{time}: {price}円 {biyori}")
~~~

## all.py(すべて表示)
~~~python:all.py
import requests
import json
from datetime import datetime

print("""

Looopでんき スマートタイムONE(電灯)
でんき単価取得

作者: 小川 智也(https://ogatomo.net/)

""")
# エリアコード
# area.mdをご覧ください

# e.x. 関西電力 = 06
area = "06"

if area == "01" :
    area_name = "北海道"
elif area == "02" :
    area_name = "東北"
elif area == "03" :
    area_name = "東京"
elif area == "04" :
    area_name = "中部"
elif area == "05" :
    area_name = "北陸"
elif area == "06" :
    area_name = "関西"
elif area == "07" :
    area_name = "中国"
elif area == "08" :
    area_name = "四国"
elif area == "09" :
    area_name = "九州"
elif area == "10" :
    area_name = "沖縄"
else:
    area_name = "(不明)"

now = datetime.now()
now_time = now.strftime('%Y年%m月%d日 %H:%M:%S')

print(f"==========\nエリア: {area} {area_name}電力\n現在は{now_time}です。\n==========\n")

url = f'https://looop-denki.com/api/prices?select_area={area}'
headers = {"content-type": "application/json"}
r = requests.get(url,headers=headers)

text = r.json()

# 今日を取得
today = text["1"]["text"]
for i in range(1,48,1):
    priceNo = str(i)
    price = today[priceNo]["price"]
    time = text["timelist"][i-1]
    if today[priceNo]["level"] == -0.5 :
        biyori = "でんき日和"
    elif today[priceNo]["level"] == 0.5 :
        biyori = "でんき注意報"
    elif today[priceNo]["level"] == 1 :
        biyori = "でんき警報"
    else:
        biyori = ""

    print(f"{time}: {price}円 {biyori}")

~~~