2 回答

TA貢獻1795條經驗 獲得超7個贊
所以,我稍微思考了一下你的問題,這就是我的想法。
基本上,數據存儲的最佳選擇是輕量級數據庫,如評論中所建議的。然而,通過一些計劃、一些跳躍和一些黑客代碼,你可以通過一個簡單的(某種)JSON
最終得到一個.csv
如下所示的文件:
注意:這些值是相同的,因為我不想等待一兩天排行榜才真正更新。
我所做的就是重新排列從 API 請求返回的數據,并構建一個如下所示的結構:
"BobTheElectrician": {
"id": 7160010,
"rank": 14,
"score_data": {
"2020-10-24 18:45": 4187,
"2020-10-24 18:57": 4187,
"2020-10-24 19:06": 4187,
"2020-10-24 19:13": 4187
}
每個球員都是你的主要關鍵,除其他外,都有其scores_data
價值。這反過來又為您運行腳本的每一天dict
保留價值。points
現在,訣竅是讓它JSON
看起來像.csv
你想要的。問題是——如何?
好吧,既然您打算更新所有玩家的數據(我只是假設),他們都應該具有相同數量的
score_data
.的鍵
score_data
是您的時間戳。抓住任何玩家的score_data
鑰匙,你就會得到日期標題,對嗎?話雖如此,您可以以
.csv
相同的方式構建行:從 中獲取玩家的姓名及其所有分值score_data
。這應該會給你一個列表的列表,對吧?正確的。
然后,當您擁有所有這些后,您只需將其轉儲到一個.csv
文件中即可!
把它們放在一起:
import csv
import json
import os
import random
import time
from urllib.parse import urlencode
import requests
API_URL = "https://community.koodomobile.com/widget/pointsLeaderboard?"
LEADERBOARD_FILE = "leaderboard_data.json"
def get_leaderboard(period: str = "allTime", max_results: int = 20) -> list:
payload = {"period": period, "maxResults": max_results}
return requests.get(f"{API_URL}{urlencode(payload)}").json()
def dump_leaderboard_data(leaderboard_data: dict) -> None:
with open("leaderboard_data.json", "w") as jf:
json.dump(leaderboard_data, jf, indent=4, sort_keys=True)
def read_leaderboard_data(data_file: str) -> dict:
with open(data_file) as f:
return json.load(f)
def parse_leaderboard(leaderboard: list) -> dict:
return {
item["name"]: {
"id": item["id"],
"score_data": {
time.strftime("%Y-%m-%d %H:%M"): item["points"],
},
"rank": item["leaderboardPosition"],
} for item in leaderboard
}
def update_leaderboard_data(target: dict, new_data: dict) -> dict:
for player, stats in new_data.items():
target[player]["rank"] = stats["rank"]
target[player]["score_data"].update(stats["score_data"])
return target
def leaderboard_to_csv(leaderboard: dict) -> None:
data_rows = [
[player] + list(stats["score_data"].values())
for player, stats in leaderboard.items()
]
random_player = random.choice(list(leaderboard.keys()))
dates = list(leaderboard[random_player]["score_data"])
with open("the_data.csv", "w") as output:
w = csv.writer(output)
w.writerow([""] + dates)
w.writerows(data_rows)
def script_runner():
if os.path.isfile(LEADERBOARD_FILE):
fresh_data = update_leaderboard_data(
target=read_leaderboard_data(LEADERBOARD_FILE),
new_data=parse_leaderboard(get_leaderboard()),
)
leaderboard_to_csv(fresh_data)
dump_leaderboard_data(fresh_data)
else:
dump_leaderboard_data(parse_leaderboard(get_leaderboard()))
if __name__ == "__main__":
script_runner()
該腳本還會檢查您是否有一個JSON冒充正確數據庫的文件。如果沒有,它將寫入排行榜數據。下次運行該腳本時,它將更新JSON并生成一個新.csv文件。
希望這個答案能引導您走向正確的方向。

TA貢獻1820條經驗 獲得超2個贊
嘿,既然您將其加載到 panda 框架中,那么操作就相當簡單了。我先運行你的代碼
import pandas as pd
import time
timestr = time.strftime("%Y-%m-%d %H:%M")
url_all_time = 'https://community.koodomobile.com/widget/pointsLeaderboard?period=allTime&maxResults=20&excludeRoles='
data = pd.read_json(url_all_time)
table = pd.DataFrame.from_records(data, index=['name'], columns=['points','name'])
table['date'] = pd.Timestamp.today().strftime('%m-%d-%Y')
然后我添加了幾行代碼來根據您的需要修改 panda 框架表。
idxs = table['date'].index
for i,val in enumerate(idxs):
table.at[ val , table['date'][i] ] = table['points'][i]
table = table.drop([ 'date', 'points' ], axis = 1)
在上面的代碼片段中,我使用 pandas 框架通過索引分配值的能力。因此,首先我獲取日期列的索引值,然后遍歷每個索引值以添加所需日期的列(日期列中的值),并根據我們之前提取的索引獲取相應的點
這給了我以下輸出:
name 10-24-2020
Dennis 52570.0
Dinh 40930.0
Sophia 26053.0
Mayumi 25300.0
Goran 24689.0
Robert T 19843.0
Allan M 19768.0
Bernard Koodo 14404.0
nim4165 13629.0
Timo Tuokkola 11216.0
rikkster 7338.0
David AKU 5774.0
Ranjan Koodo 4506.0
BobTheElectrician 4170.0
Helen Koodo 3370.0
Mihaela Koodo 2764.0
Fred C 2542.0
Philosoraptor 2122.0
Paul Deschamps 1973.0
Emilia Koodo 1755.0
然后我可以使用代碼中的最后一行將其保存到 csv 中。類似地,您可以提取更多日期的數據并將其格式化以將其添加到同一個熊貓框架中
table.to_csv('products.csv', index=True, encoding='utf-8')
添加回答
舉報