【Python】speedtest-cliで回線のスピードテストを定期実行する

通信速度の測定をしたいことがありますよね。PCを新調したとき、WiFi速度が気になる時、どうも最近不調だなと思って調べたい時etc…
インターネット速度テストもありますが、結構結果がばらつきます。
今回はPythonプログラムで回線のスピードテストをする方法をご紹介します。
定期実行できるので、一日の平均などが放っておくだけで簡単に計測できるようになります。

ひとまずネットワークの速度を測れるようにします。
次に定期実行して、結果をグラフ表示するところまでやってみたいと思います。
このようなイメージです。

こんな風に計測結果が得られれば、ばらつきも平均値も分かりますね。
そのために必要なことは次です。

やること1
・speedtest-cliライブラリのインストール
・速度測定

やること2
・速度測定をjsonファイル出力
・測定結果をグラフ出力

最後にサンプルコードも掲載しています。
それでは、順に見ていきましょう!

目次

やること1

今回ご紹介するspeedtest-cliはOokla Speedtestを利用しています。
Ookla Speedtestは、Ooklaが提供するオンラインツールです。
世界中で広く使用されているインターネット速度測定サービスです。
ウェブベースやモバイルアプリを通じて、ダウンロード速度、アップロード速度、pingを測定し、
回線の速度パフォーマンスを確認できます。

Speedtest.net
Speedtest by Ookla - The Global Broadband Speed Test Use Speedtest on all your devices with our free desktop and mobile apps.

speedtest-cliは、Sergey Lvov氏によって作成されたPythonのコマンドラインツールです。
Ookla Speedtestの非公式なツールですが、インストールから測定まで簡単なためよく利用されています。
コマンドラインから簡単に利用できるほか、これから説明するPythonでの利用もできるように設計されています。
Ookla SpeedtestのWeb APIを利用していて、オープンソースプロジェクトとして提供されています。

speedtest-cliライブラリのインストール

それではライブラリをインストールしてみましょう。
pipでインストールできます。

pip speedtest-cli

速度測定

かんたんに速度測定することができます。

import speedtest

st = speedtest.Speedtest()
st.get_best_server()

# 速度測定を実行
download_speed = st.download() / 1024 / 1024  # Mbpsに変換
upload_speed = st.upload() / 1024 / 1024  # Mbpsに変換
ping = st.results.ping

print("[測定結果]")
print(f"download_speed: {download_speed}Mbps")
print(f"upload_speed: {upload_speed}Mbps")
print(f"ping: {ping}ms")

このような形で計測できます。

これでインターネット速度テストを代替することができました。

やること2

速度測定はできるようになりました。
やってみて貰うと分かりますが、結果がばらつきます。
定期実行してjsonファイルに出力しておけば、平均値を求めたり、時間による変動を調べやすくなります。

ということで、jsonファイル出力と、グラフ表示をやっていきましょう!

速度測定をjsonファイル出力

次のようなjsonファイル出力を目指したいと思います。

{
        "timestamp": "2023-11-11 10:53:13",
        "download_speed": 536.167055487074,
        "upload_speed": 173.52329350572143,
        "ping": 17.422
    },

jsonファイルにデータを追加していく想定です。
speedtest_results.jsonに、先ほどの測定データを追記するようにします。
タイムスタンプも追加しています。
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")の部分ですね。

import from datetime import datetime

# 現在のデータを読み込む
try:
    with open("speedtest_results.json", "r") as json_file:
        data = json.load(json_file)
except FileNotFoundError:
    data = []
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 新しいデータを追加
result_dict = {
    "timestamp": timestamp,
    "download_speed": download_speed,
    "upload_speed": upload_speed,
    "ping": ping
}

data.append(result_dict)

# 結果をJSONファイルに保存
with open("speedtest_results.json", "w") as json_file:
    json.dump(data, json_file, indent=4)  

これでjsonファイルに出力することができました。
関数にしておいて、例えば10分ごとに実行で計測結果のばらつきと時間変化を測れるようになります。

測定結果をグラフ出力

上記のようにして、計測結果を集めたら、
今度は視覚的に表示してみたいと思います。

グラフ表示にはmatplotlib、データ整理にpandasを利用します。
ライブラリをインストールします。

pip install matplotlib pandas

matplotlibとpandasを使ってグラフを作成します。
予め作成しておいたspeedtest_results.jsonファイルから、
Download Speedを時系列で抜き出してグラフ表示します。

import pandas as pd
import json
import matplotlib.pyplot as plt
from datetime import datetime

# JSONファイルからデータを読み込む
with open("speedtest_results.json", "r") as json_file:
    data = json.load(json_file)

# データフレームに変換
df = pd.DataFrame(data)

# timestamp列をdatetime型に変換
df['timestamp'] = pd.to_datetime(df['timestamp'])

# 平均値を計算
average_download_speed = df['download_speed'].mean()

# ダウンロード速度のプロット
plt.figure(figsize=(10, 6))
plt.plot(df['timestamp'], df['download_speed'], label='Download Speed (Mbps)', marker='o')
plt.axhline(y=average_download_speed, color='r', linestyle='--', label=f'Average: {average_download_speed:.2f} Mbps')
plt.ylabel('Download Speed (Mbps)')
plt.legend()

# タイトルとレイアウトの調整
plt.title('Download Speed Over Time with Average')
plt.xlabel('Timestamp')
plt.xticks(rotation=45)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

実行結果がこのようになります。

これをupload_speed、pingにも適用すると冒頭に表示した結果になります。

サンプルコード1_通信速度の測定

それでは、ここまでのコードを合体して、サンプルコードを紹介したいと思います。
その1は通信速度の測定部分のみです。再掲です。

import speedtest

st = speedtest.Speedtest()
st.get_best_server()

# 速度測定を実行
download_speed = st.download() / 1024 / 1024  # Mbpsに変換
upload_speed = st.upload() / 1024 / 1024  # Mbpsに変換
ping = st.results.ping

print("[測定結果]")
print(f"download_speed: {download_speed}Mbps")
print(f"upload_speed: {upload_speed}Mbps")
print(f"ping: {ping}ms")

サンプルコード2_定期的に通信速度測定

その2は先ほどのコードを定期実行して、jsonファイルに出力するものです。

import speedtest
import json
from datetime import datetime
import time

def run_speedtest():
    try:
        st = speedtest.Speedtest()
        st.get_best_server()
        
        # 速度測定を実行
        download_speed = st.download() / 1024 / 1024  # Mbpsに変換
        upload_speed = st.upload() / 1024 / 1024  # Mbpsに変換
        ping = st.results.ping
        
        # 現在のデータを読み込む
        try:
            with open("speedtest_results.json", "r") as json_file:
                data = json.load(json_file)
        except FileNotFoundError:
            data = []
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        # 新しいデータを追加
        result_dict = {
            "timestamp": timestamp,
            "download_speed": download_speed,
            "upload_speed": upload_speed,
            "ping": ping
        }
        
        data.append(result_dict)
        
        # 結果をJSONファイルに保存
        with open("speedtest_results.json", "w") as json_file:
            json.dump(data, json_file, indent=4)        
         
        # 結果を表示
        print(f"timestamp: {timestamp}")
        print(f"download_speed: {download_speed}")
        print(f"upload_speed: {upload_speed}")
        print(f"ping: {ping}")
        # print("速度測定結果をJSONファイルに保存しました:")
        # print(json.dumps(result_dict, indent=4))

    except Exception as e:
        print(f"エラー: {str(e)}")

if __name__ == "__main__":
    while True:
        run_speedtest()
        time.sleep(600)

600秒(10分)ごとにスピードテストを実行します。
実行結果を、speedtest_results.jsonファイルに出力します。

サンプルコード3_測定結果をグラフ表示

その3は結果表示です。
speedtest_results.jsonファイルを読み込み、
download_speedと、upload_speed、pingの測定結果を時系列でチャート表示します。
赤い点線で平均値を記載しています。

import pandas as pd
import json
import matplotlib.pyplot as plt
from datetime import datetime

# JSONファイルからデータを読み込む
with open("speedtest_results.json", "r") as json_file:
    data = json.load(json_file)

# データフレームに変換
df = pd.DataFrame(data)

# timestamp列をdatetime型に変換
df['timestamp'] = pd.to_datetime(df['timestamp'])

# 平均値を計算
average_download_speed = df['download_speed'].mean()
average_upload_speed = df['upload_speed'].mean()
average_ping = df['ping'].mean()

# サブプロットを作成
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(10, 12), sharex=True)

# ダウンロード速度のプロット
ax1.plot(df['timestamp'], df['download_speed'], label='Download Speed (Mbps)', marker='o')
ax1.axhline(y=average_download_speed, color='r', linestyle='--', label=f'Average: {average_download_speed:.2f} Mbps')
ax1.set_ylabel('Download Speed (Mbps)')
ax1.legend()

# アップロード速度のプロット
ax2.plot(df['timestamp'], df['upload_speed'], label='Upload Speed (Mbps)', marker='o')
ax2.axhline(y=average_upload_speed, color='r', linestyle='--', label=f'Average: {average_upload_speed:.2f} Mbps')
ax2.set_ylabel('Upload Speed (Mbps)')
ax2.legend()

# ピンクのプロット
ax3.plot(df['timestamp'], df['ping'], label='Ping (ms)', marker='o')
ax3.axhline(y=average_ping, color='r', linestyle='--', label=f'Average: {average_ping:.2f} ms')
ax3.set_xlabel('Timestamp')
ax3.set_ylabel('Ping (ms)')
ax3.legend()

# タイトルとレイアウトの調整
plt.suptitle('Speedtest Results Over Time with Averages', y=0.95, fontsize=16)
plt.xticks(rotation=45)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

実行結果が冒頭のグラフになります。
再掲します。

今回は以上となります。
この記事が少しでもお役に立てれば幸いです。
それでは、読んで頂きありがとうございました!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次