首页 > 后端开发 > Python教程 > 从《部落冲突》API 下载玩家数据

从《部落冲突》API 下载玩家数据

WBOY
发布: 2024-08-23 06:00:39
原创
746 人浏览过

Downloading Player Data from Clash of Clans API

您是《部落冲突》爱好者,同时也热衷于数据分析或应用程序开发吗?在这篇文章中,我将引导您完成使用 Python 从《部落冲突》API 下载玩家数据的过程。这对于部落管理工具、玩家统计分析,甚至构建您自己的《部落冲突》相关应用程序非常有用。

先决条件

在我们深入之前,请确保您已经:

  1. 您的机器上安装了Python
  2. Python编程基础知识
  3. 《部落冲突》开发者帐户(我们将介绍如何获取此帐户)

第 1 步:设置您的开发者帐户

首先,您需要注册一个《部落冲突》开发者帐户:

  1. 前往《部落冲突》API 开发者网站
  2. 创建帐户并登录
  3. 生成 API 密钥 - 您需要它来访问数据

第 2 步:安装所需的库

我们将在此项目中使用多个 Python 库。使用 pip 安装它们:

pip install requests pandas tqdm ratelimit
登录后复制

第三步:代码

让我们将代码分解为可管理的块:

导入库并设置

import time
import math
import json
import requests
import logging
import pandas as pd
from concurrent.futures import ThreadPoolExecutor, as_completed
from ratelimit import limits, sleep_and_retry
from tqdm import tqdm
登录后复制

提取氏族标签

file_path = 'others/clans.json'

# Function to open the file and extract tags, specifying the encoding
def extract_tags_from_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:  # Specifying the encoding here
        data = json.load(file)
        return [item.get("tag") for item in data.get("items", [])]

# Extract tags from the specified file
try:
    extracted_tags = extract_tags_from_file(file_path)
    print(extracted_tags)

except UnicodeDecodeError as e:
    print(f"Error reading the file: {e}")
登录后复制
# the extracted clan tags have '#' in beigning we have to replace it with URL encode '%23'
def update_tags(extracted_tags):
    # Replace '#' with '%23' for each tag in the list
    updated_tags = [tag.replace('#', '%23') for tag in extracted_tags]
    return updated_tags

# Get the updated list of tags
updated_extracted_tags = update_tags(extracted_tags)

# Print or return the updated list
print(updated_extracted_tags)
登录后复制

提取玩家标签

# Replace your API_KEY
api_key = 'your_api_key_here'  

# Base URL for the Clash of Clans API clans endpoint
base_url = 'https://api.clashofclans.com/v1/clans/'

# Header to include in the request
headers = {
   'Authorization': f'Bearer {api_key}',
   'Accept': 'application/json'
}

# Function to get clan member list for each clan tag
def get_clan_members(clan_tags):
    clan_members = {}  # Dictionary to store clan members list by clan tag

    for tag in clan_tags:
        # Constructing the full URL for the clan members endpoint
        full_url = f'{base_url}{tag}/members'
        response = requests.get(full_url, headers=headers)

        if response.status_code == 200:
            # Successful response
            data = response.json()
            # Assuming the API returns a list of clan members directly
            clan_members[tag] = data.get('items', [])

        else:
            # Handle errors or unsuccessful responses
            print(f'Failed to fetch clan members for {tag}: HTTP {response.status_code}')

    return clan_members

# Get clan members for each tag
clan_members_lists = get_clan_members(updated_extracted_tags)

# Example: print the result for the first clan
first_tag = updated_extracted_tags[0]
print(f'Clan members for {first_tag}:', clan_members_lists[first_tag])
登录后复制

将数据转换为 pandas DataFrame

# Assuming clan_members_lists is your dictionary from the modified get_clan_members function
def convert_to_dataframe(clan_members_lists):
# Create a list of tuples (clan_tag, player_tag) for all clans
    data = [(clan_tag, player_tag) for clan_tag, player_tags in clan_members_lists.items() for player_tag in player_tags]

# Convert the list of tuples into a DataFrame
    df = pd.DataFrame(data, columns=['Clan Tag', 'Player Tag'])

    return df

# Convert the dictionary to a DataFrame
df_clan_members = convert_to_dataframe(clan_members_lists)
print(df_clan_members)
登录后复制
def convert_to_dataframe(clan_members_lists):
    # Initialize an empty list to store the data
    data = []

    # Loop through each clan tag and its corresponding list of members
    for clan_tag, members in clan_members_lists.items():
        for member in members:
            # For each member, extract the clan tag and the player tag, ensuring the player tag is a string
            player_tag = member['tag']  # Assuming 'tag' key exists and its value is the player's tag
            data.append((clan_tag, player_tag))

    # Convert the list of tuples into a DataFrame
    df = pd.DataFrame(data, columns=['Clan Tag', 'Player Tag'])

    # Optional: Convert clan and player tags to ensure they are URL-friendly
    # This step is optional and depends on whether you need to use these tags in URLs
    df['Clan Tag'] = df['Clan Tag'].apply(lambda x: x.replace('%23', '#'))
    # df['Player Tag'] = df['Player Tag'].apply(lambda x: x.replace('#', '%23'))

    return df

# Example usage with your clan_members_lists dictionary
# Make sure to replace 'clan_members_lists' with your actual dictionary variable
df_clan_members = convert_to_dataframe(clan_members_lists)
print(df_clan_members)

df_clan_members.to_csv('datasets/clan_and_player_tags.csv', index=False)
登录后复制

提取玩家信息

# Set up logging to file
logging.basicConfig(filename='others/error_log.log', level=logging.ERROR, 
                    format='%(asctime)s - %(levelname)s - %(message)s')

# Load the CSV file into a DataFrame
df = pd.read_csv('datasets/clan_and_player_tags.csv')  # Update this path to your actual CSV file location

# API details
api_key = 'your_api_key_here'
headers = {'Authorization': 'Bearer ' + api_key}

# Rate limit: 10 requests per second (adjust as needed)
@sleep_and_retry
@limits(calls=10, period=1)
def call_api(url):
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json()

def fetch_player_details(tag):
    url = f'https://api.clashofclans.com/v1/players/{tag.replace("#", "%23")}'
    try:
        data = call_api(url)
        return {
            'name': data.get('name', ''),
            'role': data.get('role', ''),
            'league': data.get('league', {}).get('name', ''),
            'builderBaseLeague': data.get('builderBaseLeague', {}).get('name', ''),
            'townHallLevel': data.get('townHallLevel', 0),
            'builderHallLevel': data.get('builderHallLevel', 0),
            'expLevel': data.get('expLevel', 0),
            'trophies': data.get('trophies', 0),
            'bestTrophies': data.get('bestTrophies', 0),
            'builderBaseTrophies': data.get('builderBaseTrophies', 0),
            'bestBuilderBaseTrophies': data.get('bestBuilderBaseTrophies', 0),
            'attackWins': data.get('attackWins', 0),
            'defenseWins': data.get('defenseWins', 0),
            'warStars': data.get('warStars', 0),
            'clanCapitalContributions': data.get('clanCapitalContributions', 0),
            'donations': data.get('donations', 0),
            'donationsReceived': data.get('donationsReceived', 0),
        }
    except requests.exceptions.RequestException as e:
        logging.error(f'Error fetching data for {tag}: {e}')

def process_batch(batch):
    player_details = []
    with ThreadPoolExecutor(max_workers=20) as executor:
        future_to_tag = {executor.submit(fetch_player_details, tag): tag for tag in batch}
        for future in as_completed(future_to_tag):
            tag = future_to_tag[future]
            try:
                details = future.result()
                player_details.append(details)
            except Exception as exc:
                logging.error(f'{tag} generated an exception: {exc}')

    return player_details

def save_checkpoint(data, filename):
    with open(filename, 'w') as f:
        json.dump(data, f)

def load_checkpoint(filename):
    try:
        with open(filename, 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return []

def main():
    batch_size = 1000
    checkpoint_file = 'others/player_details_checkpoint.json'

    # Load checkpoint if it exists
    player_details = load_checkpoint(checkpoint_file)
    start_index = len(player_details)

    num_batches = math.ceil((len(df) - start_index) / batch_size)

    for i in tqdm(range(start_index, len(df), batch_size), total=num_batches, desc="Processing batches"):
        batch = df['Player Tag'].iloc[i:i+batch_size].tolist()
        batch_details = process_batch(batch)
        player_details.extend(batch_details)

        # Save checkpoint after each batch
        save_checkpoint(player_details, checkpoint_file)

     # Filter out None values from player_details
    player_details = [detail for detail in player_details if detail is not None]

    # Create a new DataFrame with the player details
    details_df = pd.DataFrame(player_details)

    # Merge the original DataFrame with the new details DataFrame
    final_df = pd.concat([df, details_df], axis=1)

    # Save the final DataFrame to a new CSV file
    final_df.to_csv('datasets/player_details.csv', index=False)
    print("Data fetching and processing complete. Results saved to 'Clan_and_Player_Details.csv'")

if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    print(f"Total execution time: {end_time - start_time:.2f} seconds")
登录后复制

运行脚本

运行脚本:

  1. 将“YOUR_API_KEY_HERE”替换为您的实际 API 密钥
  2. 确保您有一个名为 clan_and_player_tags.csv 的 CSV 文件,其中包含“玩家标签”列
  3. 运行脚本

脚本将批量处理玩家标签,获取每个玩家的详细信息,并将结果保存在新的 CSV 文件中。

结论

此脚本提供了一种从 Clash of Clans API 下载玩家数据的可靠方法。它包括错误处理、速率限制以遵守 API 约束,并使用多线程来提高性能。

请记住始终遵守 API 使用条款和条件。快乐编码,一起冲突吧!


以上是从《部落冲突》API 下载玩家数据的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板