ごごちと申します。
仮想通貨投資の、特に分散型取引所(DEX)の投資を1年半やっています。
これまで仮想通貨の投資成績を手作業で記録してきたのですが、
記録を自動化したいと思い、
ゴールデンウィークを利用してPythonスクレイピングを活用して
Debankの情報を自動記録するプログラムを作成することにしました。
先日は、PythonスクレイピングでDebankの自動ログ取得の記事を書きました。
前の記事から追加でやりたかったことは以下の通りです。
- 投資金額に対する現在の評価額によるリターンの可視化(グラフ表示)
- プログラムの定期実行
- 手作業で記録した1年半分のログのマージ
現在では、これらを全て実装し動作することを確認できました。
今回は、1のグラフ化の部分を紹介したいと思います。
2.のプログラムの定期実行、および、3.の手作業で記録したログのマージは
次回の記事で紹介したいと思います。
(2023年5月6日追記)
2.プログラムの定期実行はこちら
スリープ中でもPythonスクレイピングプログラムを定期実行する方法【タスクスケジューラ】【Windows10】
(2023年5月7日追記)
Python環境構築について記事を書きました。
DebankのPythonスクレイピングプログラムの環境構築!chromedriverまで解説!
成績のグラフ表示
今回はリターンとLP報酬の2項目について、
DEX全体、Uniswap、PancakeSwapの3種類の形で
合計6種類のグラフを記録できるようにしました。
投資金額に対するリターン
筆者がログ記録で一番注目する箇所は、
現在の評価額が投資金額に対してどれくらいのリターンになっているかです。
ここでリターンは以下で定義しています。
リターン = (現在の評価額-投資金額 ) / (投資金額)
リターンを時系列でグラフ化し、成績を常に把握できるようにしました。
横軸は日時となっています。
青色になっている左y軸がドル単位になっています。
青の破線が積み立て金額(Deposit_$)
青の実線が現在の評価額(Total_$)
に対応しています。
緑になっている右y軸が%単位になっています。
緑の実線がリターン(Total_return_%)
に対応しています。
pandasを使うと横軸の時刻を良い感じに調整してくれるので便利です。
DEX全体 のリターン
Uniswap V3 のリターン
PancakeSwap V3 のリターン
LP報酬(Reward)
次に興味があるのは、(Liquidity Provider : LP)による報酬がどれだけ発生しているかです。
分散型取引所を活用する動機のひとつは、LP報酬によるインカムゲインであるため、
どれだけ報酬が発生しているか、どれくらいの勢いで増えているかを見えるようにしました。
横軸は日時となっています。
青色になっている左y軸がドル単位になっています。
青の実線が現在のLP報酬額(Reward_$)
に対応しています。
緑になっている右y軸が%単位になっています。
緑の実線がDEXの総評価額に対するLP報酬額の割合(Reward_%)
に対応しています。
筆者は1か月に1回積立投資をする際に、報酬を回収するので、長期的にはギザギザのグラフになります。
DEX全体 の LP報酬
Uniswap V3 の LP報酬
PancakeSwap V3 の LP報酬
プログラム
プログラムの仕様は以下の通りです。
平常時および定期実行時
python portfolio.py で実行すると、Debankにログインし、スクレイピングを行います。
既存の「record_YYYYMMDD_HHMMSS.xlsx」を読み取り、現時点のレコードを追加して新しい
「record_YYYYMMDD_HHMMSS.xlsx」を作成します。
もし既存のxlsxファイルがない場合でも新規で作成します。
実行フォルダには上記で紹介した6種類のグラフ「Graph_1.png」なども保存され、xlsxグラフのGraphシートに保存されます。
xlsxファイルには「Graph」,「summary」,「Uniswap V3」,「PancakeSwap V3」,「wallet」,「price」
の6種類のシートがあります。
xlsxファイルを開いたときにGraphが表示されるようにしており、最新の取得結果も見えるようにしました。
「summary」等の数値ログも、最新の結果が一番上になるよう、日付の降順で並び替えています。
報酬の回収や積み立て金額の更新時
積み立てを行ったときや報酬を回収したときの更新時には
コマンドライン引数で判定することにしました。
報酬を回収するとDebankでは報酬額がゼロとなってしまうので、累積報酬額に加算する必要があります。
また、積立金額も手入力で定義する必要があります。
報酬を回収した時にはコマンドライン引数に1を渡します。
報酬を回収した時の実行方法
python portfolio.py 1
コマンドライン引数に1を指定することで、回収を行う直前の報酬額を累積報酬額に追加します。
また報酬の回収を行うタイミングでは積み立てを行うことも多いので、忘れずに積み立て金額を修正します。
いろいろ方法を考えましたが、なかなか良い方法を思いつきませんでした。
失敗しても戻れるようにログは毎回取っておくようにしたいと思います。
積み立て更新がない時やWindowsタスクスケジューラによる定期実行時は自動でコマンドライン引数は不要です。
portfolio.py
実行したコードを紹介します。
ChatGPTを使って何とか意図する動作をするように重視したので、保守性や可読性など改善の余地はあります。
以前のプログラムとの変更点は以下の通りです。
- 積立金額の入力部(15-26行目)
- リターンと報酬のグラフ作成関数(149-228行目)
- グラフ作成部分(333-367行目)
import pandas as pd
import time
from datetime import datetime
import openpyxl
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.styles import Font
import os.path
import glob
from selenium import webdriver
from selenium.webdriver.common.by import By
import matplotlib.pyplot as plt
import sys #コマンドライン引数を受け取る
# 累積の入金額を手入力
Deposit_total = {
"Uniswap V3": 3911,
"PancakeSwap V3":704
}
# プログラム実行時、報酬を回収したなら1を渡す
if len(sys.argv) > 1:
is_add_Reward = int(sys.argv[1])
else:
is_add_Reward = 0
print("is_add_Reward",is_add_Reward==1)
# 手作業で取得していた累積報酬額(更新不要)
Reward_initial = {
"Uniswap V3": 278,
"PancakeSwap V3":106
}
# wallet情報をまとめるための関数
def create_wallet(TokenWallet_elements):
# DataFrameを作成
df_wallet = pd.DataFrame(index=[now])
df_wallet["Total_$"]=0
#行の数だけ繰り返す
for i,token in enumerate(TokenWallet_elements):
text = token.text.split("\n")
asset = text[0]
price = float(text[1].replace(",", "").replace("$", ""))
amount = float(text[2].replace(",", ""))
USD_value = float(text[3].replace(",", "").replace("$", ""))
if asset not in df_wallet.columns:
df_wallet[asset]=price
df_wallet[asset +"_amount"]=amount
df_wallet[asset +"_USD_value_$"]=USD_value
#同じトークンでチェーンが違うものは足してしまう。
else:
df_wallet[asset]=price
df_wallet[asset +"_amount"]+=amount
df_wallet[asset +"_USD_value_$"]+=USD_value
df_wallet["Total_$"] += USD_value
return df_wallet
# Tokenの価格情報をまとめるための関数
def create_price(TokenWallet_elements):
# DataFrameを作成
df_price = pd.DataFrame(index=[now])
for i,token in enumerate(TokenWallet_elements):
text = token.text.split("\n")
asset = text[0]
balance = float(text[1].replace(",", "").replace("$", ""))
df_price[asset] = [balance]
return df_price
# 取引所毎に成績をまとめるための関数
def create_defi(project):
df_defi = pd.DataFrame(index=[now])
project_name = project.find_element(By.XPATH, './/*[contains(@class,"ProjectTitle_name")]').text
project_portfolio_elements = project.find_elements(By.XPATH, './/*[contains(@class,"table_contentRow")]')
df_defi[project_name+"_total_$"]=0
df_defi[project_name+"_deposit_$"]=Deposit_total[project_name]
df_defi[project_name+"_return_%"] = 0
df_defi[project_name+"_total_Reward_$"]=0
df_defi[project_name+"_total_Reward_%"]=0
df_defi[project_name+"_total_Reward_cumsum_$"]=0
for i,defi in enumerate(project_portfolio_elements):
# 改行文字で区切ってリストに格納
text_list = defi.text.split("\n")
total_asset = float(text_list[-1].replace("$", "").replace(",", ""))
df_defi[f"{i}_"+text_list[0]+"_pool_$"] = [total_asset]
df_defi[f"{i}_"+text_list[0]+"_pool_Reward_$"] = 0
df_defi[f"{i}_"+text_list[0]+"_pool_Reward_%"] = 0
# 各poolごとのループ
for j,text in enumerate(text_list[1:5]):
col = text.split()[1]
value = float(text.replace(",", "").split()[0])
if col not in ["USDC","USDT"]:
price = value*df_price.loc[now,col]
else:
price = value
if j in [2,3]:
col += "_Reward"
df_defi[f"{i}_"+text_list[0]+"_pool_Reward_$"] += price
df_defi[f"{i}_" + col] = value
df_defi[f"{i}_" + col+"_$"] = price
df_defi[f"{i}_"+text_list[0]+"_pool_Reward_%"] = df_defi[f"{i}_"+text_list[0]+"_pool_Reward_$"] /total_asset*100
df_defi[project_name+"_total_$"] += total_asset
df_defi[project_name+"_return_%"] = (df_defi[project_name+"_total_$"]-df_defi[project_name+"_deposit_$"])/(df_defi[project_name+"_deposit_$"])*100
df_defi[project_name+"_total_Reward_$"] += df_defi[f"{i}_"+text_list[0]+"_pool_Reward_$"]
df_defi[project_name+"_total_Reward_%"]=df_defi[project_name+"_total_Reward_$"] /df_defi[project_name+"_total_$"] *100
return df_defi
# 総合成績をまとめるための関数
def create_summary(df_wallet,df_defi):
df_summary = pd.DataFrame(index=[now])
df_summary["all_asset_$"]=0
df_summary["Defi_Total_$"]=0
df_summary["Defi_Total_Deposit_$"]=0
df_summary["Defi_Total_return_%"]=0
df_summary["Defi_Total_Reward_$"]=0
df_summary["Defi_Total_Reward_%"]=0
df_summary["Defi_Total_Reward_cumsum_$"]=0
df_summary["Defi_Total_Reward_cumsum_%"]=0
df_summary["Uniswap_Total_$"]=df_defi["Uniswap V3_total_$"]
df_summary["Uniswap_Total_Deposit_$"]=df_defi["Uniswap V3_deposit_$"]
df_summary["Uniswap_Total_return_%"]=df_defi["Uniswap V3_return_%"]
df_summary["Uniswap_Reward_$"]=df_defi["Uniswap V3_total_Reward_$"]
df_summary["Uniswap_Reward_%"]=df_defi["Uniswap V3_total_Reward_%"]
df_summary["Uniswap_Reward_cumsum_$"]=df_defi["Uniswap V3_total_Reward_cumsum_$"]
df_summary["Uniswap_Reward_cumsum_%"]=df_summary["Uniswap_Reward_cumsum_$"]/df_summary["Uniswap_Total_$"]*100
df_summary["PancakeSwap_Total_$"]=df_defi["PancakeSwap V3_total_$"]
df_summary["PancakeSwap_Total_Deposit_$"]=df_defi["PancakeSwap V3_deposit_$"]
df_summary["PancakeSwap_Total_return_%"]=df_defi["PancakeSwap V3_return_%"]
df_summary["PancakeSwap_Reward_$"]=df_defi["PancakeSwap V3_total_Reward_$"]
df_summary["PancakeSwap_Reward_%"]=df_defi["PancakeSwap V3_total_Reward_%"]
df_summary["PancakeSwap_Reward_cumsum_$"]=df_defi["PancakeSwap V3_total_Reward_cumsum_$"]
df_summary["PancakeSwap_Reward_cumsum_%"]=df_summary["PancakeSwap_Reward_cumsum_$"]/df_summary["PancakeSwap_Total_$"]*100
df_summary["Defi_Total_$"] = df_summary["Uniswap_Total_$"] + df_summary["PancakeSwap_Total_$"]
df_summary["Defi_Total_Deposit_$"]= df_summary["Uniswap_Total_Deposit_$"]+df_summary["PancakeSwap_Total_Deposit_$"]
df_summary["Defi_Total_return_%"]= (df_summary["Defi_Total_$"]-df_summary["Defi_Total_Deposit_$"])/df_summary["Defi_Total_Deposit_$"]*100
df_summary["Defi_Total_Reward_$"]= df_summary["Uniswap_Reward_$"] + df_summary["PancakeSwap_Reward_$"]
df_summary["Defi_Total_Reward_%"]= df_summary["Defi_Total_Reward_$"]/df_summary["Defi_Total_$"]*100
df_summary["Defi_Total_Reward_cumsum_$"]= df_summary["Uniswap_Reward_cumsum_$"] + df_summary["PancakeSwap_Reward_cumsum_$"]
df_summary["Defi_Total_Reward_cumsum_%"]= df_summary["Defi_Total_Reward_cumsum_$"]/df_summary["Defi_Total_$"]*100
df_summary["Wallet_total_$"]=df_wallet["Total_$"]
df_summary["all_asset_$"]=df_summary["Defi_Total_$"]+df_summary["Wallet_total_$"]
return df_summary
# returnのグラフを作成するための関数
def plot_return(df, dex_type:str):
fig1, ax1 = plt.subplots()
ax1.plot(df.index, df[f'{dex_type}_Total_Deposit_$'], label='Deposit_$',color='blue',linestyle='--')
ax1.plot(df.index, df[f'{dex_type}_Total_$'], label='Total_$',color="blue")
# 右側のy軸を作成
ax1_right = ax1.twinx()
ax1_right.plot(df.index, df[f'{dex_type}_Total_return_%'], label='Total_return_%',color='green')
ax1.set_xlabel('Date')
# 左側の軸の設定
ax1.set_ylabel(f'{dex_type}_Total_$', color='blue')
ax1.tick_params(axis='y', colors='blue')
# 右側の軸の設定
ax1_right.set_ylabel(f'{dex_type}_total_return_%', color='green')
ax1_right.tick_params(axis='y', colors='green')
# X軸ラベルを回転
ax1.tick_params(axis='x', rotation=45)
# 凡例を表示するため、プロットを統合する
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax1_right.get_legend_handles_labels()
ax1_right.legend(lines1 + lines2, labels1 + labels2, loc='upper left', bbox_to_anchor=(0, 0.94, 1, 0.2), fontsize=6)
# 右側の軸の一番最後の値を取得
deposit_last_value = df[f'{dex_type}_Total_Deposit_$'].iloc[0]
total_last_value = df[f'{dex_type}_Total_$'].iloc[0]
return_last_value = df[f'{dex_type}_Total_return_%'].iloc[0]
# グラフ上にテキストを表示
ax1.text(df.index[0], deposit_last_value, f'{deposit_last_value} $',color='blue')
ax1.text(df.index[0], total_last_value, f'{total_last_value:.1f} $',color='blue')
ax1_right.text(df.index[0], return_last_value, f'{return_last_value:.2f} %',color='green')
fig1.subplots_adjust(left=0.2, right=0.8, bottom=0.2, top=0.9, wspace=0.1, hspace=0.2)
# グラフタイトルを追加
fig1.suptitle(f'{dex_type}_Return', fontsize=12, fontweight='bold', x=0.5)
return fig1
# rewardのグラフを作成するための関数
def plot_reward(df, dex_type:str):
fig1, ax1 = plt.subplots()
ax1.plot(df.index, df[f'{dex_type}_Reward_$'], label='Reward_$',color="blue")
# 右側のy軸を作成
ax1_right = ax1.twinx()
ax1_right.plot(df.index, df[f'{dex_type}_Reward_%'], label='Reward_%',color='green')
ax1.set_xlabel('Date')
# 左側の軸の設定
ax1.set_ylabel(f'{dex_type}_Reward_$', color='blue')
ax1.tick_params(axis='y', colors='blue')
# 右側の軸の設定
ax1_right.set_ylabel(f'{dex_type}_Reward_%', color='green')
ax1_right.tick_params(axis='y', colors='green')
# X軸ラベルを回転
ax1.tick_params(axis='x', rotation=45)
# 凡例を表示するため、プロットを統合する
lines1, labels1 = ax1.get_legend_handles_labels()
lines2, labels2 = ax1_right.get_legend_handles_labels()
ax1_right.legend(lines1 + lines2, labels1 + labels2, loc='upper left', bbox_to_anchor=(0, 0.94, 1, 0.2), fontsize=6)
# 右側の軸の一番最後の値を取得
reward_last_value = df[f'{dex_type}_Reward_$'].iloc[0]
reward_p_last_value = df[f'{dex_type}_Reward_%'].iloc[0]
# グラフ上にテキストを表示
ax1.text(df.index[0], reward_last_value, f'{reward_last_value:.2f} $',color='blue')
ax1_right.text(df.index[0], reward_p_last_value, f'{reward_p_last_value:.3f} %',color='green')
fig1.subplots_adjust(left=0.2, right=0.8, bottom=0.2, top=0.9, wspace=0.1, hspace=0.2)
# グラフタイトルを追加
fig1.suptitle(f'{dex_type}_Reward', fontsize=12, fontweight='bold', x=0.5)
return fig1
############################################################################################################
#chromeでアクセス
options = webdriver.ChromeOptions()
# XXXにchromedriver.exeの保存場所を入力
service = webdriver.chrome.service.Service(executable_path = 'C:\\Users\\XXX\\XXX\\XXX\\chromedriver.exe')
driver = webdriver.Chrome(service=service, options=options)
# XXX...にMetamaskのアドレスを入力
driver.get('https://debank.com/profile/0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
############################################################################################################
time.sleep(5)
#ページ全体の情報がまとまったmain_containerを取得
main_container = driver.find_element(By.XPATH, '//*[@id="root"]/div/div[2]')
# 現在の日時を取得
now = datetime.now()
#Update Iconをクリック
Update_icon = main_container.find_element(By.XPATH, './/*[contains(@class,"UpdateButton_refreshIcon")]')
Update_icon.click()
time.sleep(10)
# 最新の情報を取得する
TokenWallet_elements = main_container.find_elements(By.XPATH, './/*[contains(@class,"db-table-row")]')
all_project_portfolio_elements = main_container.find_elements(By.XPATH, './/*[contains(@class,"Project_portfolio")]')
# ファイル名のパターンを指定して、最新のファイルを取得する
filename_pattern = 'record_*_.xlsx'
latest_file = max(glob.glob(filename_pattern), key=os.path.getctime, default=None)
# 既存のExcelファイルがある場合、Bookオブジェクトを作成する
book = pd.read_excel(latest_file, sheet_name=None, engine='openpyxl', index_col=0) if latest_file else {}
# 新しいExcelファイル名を作成する
strnow = datetime.now().strftime("%Y%m%d_%H%M%S")
new_filename = f"record_{strnow}_.xlsx"
# Excelファイルに保存するためのWriterオブジェクトを作成
writer = pd.ExcelWriter(new_filename, engine='openpyxl')
# df_Walletを作成
df_wallet = create_wallet(TokenWallet_elements)
# walletシートにデータを追加する
if "wallet" in book:
df_book = book["wallet"]
df_wallet = pd.concat([df_book, df_wallet], axis=0)
df_wallet.sort_index(ascending=False,inplace=True)
df_wallet.to_excel(writer, sheet_name="wallet", index=True)
# df_priceを作成
df_price = create_price(TokenWallet_elements)
# priceシートにデータを追加する
if "price" in book:
df_book = book["price"]
df_price = pd.concat([df_book, df_price], axis=0)
df_price.sort_index(ascending=False,inplace=True)
df_price.to_excel(writer, sheet_name="price", index=True)
# 分散型取引所ごとに成績を分けて取得
df_defi_summary = pd.DataFrame(index=[now])
for project in all_project_portfolio_elements[:-1]:
df_defi = create_defi(project)
project_name = project.find_element(By.XPATH, './/*[contains(@class,"ProjectTitle_name")]').text
# 既存のシートに対して、df_defiの内容を追加する
if project_name in book:
df_book = book[project_name]
# 新規シートを作成して、df_defiの内容を書き込む
else:
df_book = pd.DataFrame()
df_book = pd.concat([df_book, df_defi], axis=0)
if len(df_book) > 1:
# 前日のRewardのcumsumを取得(初めての場合は0を定義)
df_book.loc[df_book.index[-1], project_name+"_total_Reward_cumsum_$"] = df_book.loc[df_book.index[-2], project_name+"_total_Reward_cumsum_$"]
# is_get_Reward==1なら直前のレコードのtotal_Rewardを加算する
if is_add_Reward==1:
df_book.loc[df_book.index[-1], project_name+"_total_Reward_cumsum_$"] += df_book.loc[df_book.index[-2], project_name+"_total_Reward_$"]
else:
df_book.loc[df_book.index[-1], project_name+"_total_Reward_cumsum_$"] = Reward_initial[project_name]
df_book.sort_index(ascending=False,inplace=True)
df_book.to_excel(writer, sheet_name=project_name)
df_defi_summary = pd.concat([df_defi_summary, df_book], axis=1)
# Summaryデータを作成
df_summary = create_summary(df_wallet, df_defi_summary)
# Summaryシートにデータを追加する
if "summary" in book:
df_book = book["summary"]
df_summary = pd.concat([df_book, df_summary], axis=0)
df_summary.sort_index(ascending=False,inplace=True)
df_summary.to_excel(writer, sheet_name="summary", index=True)
# グラフ作成部分
fig1 = plot_return(df_summary,"Defi")
fig2 = plot_return(df_summary,"Uniswap")
fig3 = plot_return(df_summary,"PancakeSwap")
fig4 = plot_reward(df_summary,"Defi_Total")
fig5 = plot_reward(df_summary,"Uniswap")
fig6 = plot_reward(df_summary,"PancakeSwap")
sheet_name_graph = 'Graph'
ws = writer.book.create_sheet(sheet_name_graph)
fig1.savefig(sheet_name_graph+'_1.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_1.png')
ws.add_image(img, 'A1')
fig2.savefig(sheet_name_graph+'_2.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_2.png')
ws.add_image(img, 'I1')
fig3.savefig(sheet_name_graph+'_3.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_3.png')
ws.add_image(img, 'S1')
fig4.savefig(sheet_name_graph+'_4.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_4.png')
ws.add_image(img, 'A31')
fig5.savefig(sheet_name_graph+'_5.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_5.png')
ws.add_image(img, 'I31')
fig6.savefig(sheet_name_graph+'_6.png')
img = openpyxl.drawing.image.Image(sheet_name_graph+'_6.png')
ws.add_image(img, 'S31')
# ファイルを保存してWriterオブジェクトを閉じる
writer.close()
#以降はxlsxファイルを整形するための部分
# Excelファイルを開く
wb = openpyxl.load_workbook(new_filename)
# シート名のリストを取得
sheet_names = wb.sheetnames
# 新しいシート名のリストを作成 (例: A, C, B)
new_sheet_names = ['Graph','summary', 'Uniswap V3', 'PancakeSwap V3','wallet','price']
# シートを並び替え
for i, name in enumerate(new_sheet_names):
j = sheet_names.index(name) # 新しい位置を取得
wb.move_sheet(sheet_names[j], i+1) # シートを移動
# 全シートの列幅を20に指定
ws = wb[name]
for column in ws.columns:
for cell in column:
ws.column_dimensions[cell.column_letter].width = 20
# 全シートの行幅を12に指定
for row in ws.rows:
ws.row_dimensions[row[0].row].height = 12
#全シートのフォントサイズを10に設定する
fontsize = Font(size=10)
for row in ws.iter_rows():
for cell in row:
cell.font = fontsize
#全シートのA列(日付index)の幅を20に設定する
for ws in wb.worksheets:
ws.column_dimensions['A'].width = 25
#全シートの数値を少数第3位まで表示するようにする
for ws in wb.worksheets:
for row in ws.rows:
for cell in row:
if isinstance(cell.value, (int, float)):
cell.number_format = "0.000"
# 変更を保存
wb.save(new_filename)
driver.quit()
追加で共有したいこと
上記のコードを実行することで、
Debankのログを取得と
グラフ表示ができるようになりました。
また、筆者の動機のひとつに、
ログの定期取得があったのですが、
そちらの動作も確認することができました。
PCのスリープ時にも復帰して動作するように仕込むことで、機器に負荷もかけないようにしました。
「24時間PCを点けっぱなしにしたくないけれど、
決まった時間にはログ取得したい」
ということができるようになりました。
GW中の目標として、これらも共有します!
(2023年5月6日追記)
2.プログラムの定期実行はこちら
スリープ中でもPythonスクレイピングプログラムを定期実行する方法【タスクスケジューラ】【Windows10】
(2023年5月7日追記)
Python環境構築環境構築について記事を書きました。
DebankのPythonスクレイピングプログラムの環境構築!chromedriverまで解説!