Maison >développement back-end >Tutoriel Python >Récupération de données de jeux de société BoardGameGeek avec Python

Récupération de données de jeux de société BoardGameGeek avec Python

Patricia Arquette
Patricia Arquetteoriginal
2024-10-15 22:15:02749parcourir

BoardGameGeek board games data fetching with Python

Ce script récupérera les données des jeux de société depuis l'API BoardGameGeek et stockera les données dans un fichier CSV. La réponse de l'API est au format XML et comme il n'y a pas de point final pour récupérer plusieurs données de jeux de société à la fois, cela fonctionnera en faisant une requête au point final pour un seul jeu de société basé sur l'ID du ou des jeux de société, tout en incrémentant l'ID après chaque demande dans la plage d'ID donnée.

Consultez le dépôt sur mon profil GitHub

Les informations récupérées et stockées pour chaque jeu de société sont les suivantes :

nom, game_id, note, poids, année_publiée, min_players, max_players, min_play_time, max_pay_time, min_age,owned_by, catégories, mécaniciens, designers, artistes et éditeurs.

Nous commençons par importer les bibliothèques nécessaires à ce script :

# Import libraries
from bs4 import BeautifulSoup
from csv import DictWriter
import pandas as pd
import requests
import time

Nous devrons définir les en-têtes de la requête et la pause entre chaque requête (en secondes). Les informations sur la limite de taux de requêtes ne sont pas disponibles dans la documentation de l'API BGG et il existe des informations non officielles dans leurs forums selon lesquelles elle est limitée à 2 requêtes par seconde. La pause entre les requêtes devra peut-être être ajustée si le script commence à atteindre le taux limite.

# Define request url headers
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:85.0) Gecko/20100101 Firefox/85.0",
    "Accept-Language": "en-GB, en-US, q=0.9, en"
}

# Define sleep timer value between requests
SLEEP_BETWEEN_REQUEST = 0.5

La prochaine étape consiste à définir la gamme d'identifiants de jeux de société qui doivent être récupérés depuis BGG et traités. Au moment de la création de ce script, la limite supérieure pour laquelle il existe des données de jeu de société existantes est d'environ 402 000 identifiants et ce nombre est très susceptible d'augmenter à l'avenir.

# Define game ids range
game_id = 264882 # initial game id
last_game_id = 264983 # max game id (currently, it's around 402000)

Ce qui suit est une fonction qui sera appelée lorsque le script sera terminé en fonction de la plage d'ID. De plus, s'il y a une erreur lors de la demande, cette fonction sera appelée afin de stocker toutes les données ajoutées à la liste des jeux jusqu'au moment où l'exception s'est produite.

# CSV file saving function
def save_to_csv(games):
    csv_header = [
        'name', 'game_id', 'rating', 'weight', 'year_published', 'min_players', 'max_players',
        'min_play_time', 'max_play_time', 'min_age', 'owned_by', 'categories',
        'mechanics', 'designers', 'artists', 'publishers'
    ]
    with open('BGGdata.csv', 'a', encoding='UTF8') as f:
        dictwriter_object = DictWriter(f, fieldnames=csv_header)
        if f.tell() == 0:
            dictwriter_object.writeheader()
        dictwriter_object.writerows(games)

La partie suivante présente la logique principale de ce script. Il exécutera le code dans la plage des identifiants, ce qui signifie qu'il fera des requêtes à l'API BGG, obtiendra toutes les données en utilisant BeautifulSoup, effectuera les vérifications nécessaires si les données sont liées aux jeux de société (il existe des données liées à d'autres catégories. Reportez-vous à l'API BGG pour plus d'informations.), après cela, il traitera et ajoutera les données à la liste des jeux et enfin les stockera dans le fichier CSV.

# Create an empty 'games' list where each game will be appended
games = []

while game_id <= last_game_id:
    url = "https://boardgamegeek.com/xmlapi2/thing?id=" + str(game_id) + "&stats=1"

    try:
        response = requests.get(url, headers=headers)
    except Exception as err:
        # In case of exception, store to CSV the fetched items up to this point.
        save_to_csv(games)
        print(">>> ERROR:")
        print(err)


    soup = BeautifulSoup(response.text, features="html.parser")
    item = soup.find("item")

    # Check if the request returns an item. If not, break the while loop
    if item:
        # If the item is not a board game - skip
        if not item['type'] == 'boardgame':
            game_id += 1
            continue

        # Set values for each field in the item
        name = item.find("name")['value']
        year_published = item.find("yearpublished")['value']
        min_players = item.find("minplayers")['value']
        max_players = item.find("maxplayers")['value']
        min_play_time = item.find("minplaytime")['value']
        max_play_time = item.find("maxplaytime")['value']
        min_age = item.find("minage")['value']
        rating = item.find("average")['value']
        weight = item.find("averageweight")['value']
        owned = item.find("owned")['value']
        categories = []
        mechanics = []
        designers = []
        artists = []
        publishers = []

        links = item.find_all("link")

        for link in links:
            if link['type'] == "boardgamecategory":
                categories.append(link['value'])
            if link['type'] == "boardgamemechanic":
                mechanics.append(link['value'])
            if link['type'] == "boardgamedesigner":
                designers.append(link['value'])
            if link['type'] == "boardgameartist":
                artists.append(link['value'])
            if link['type'] == "boardgamepublisher":
                publishers.append(link['value'])

        game = {
            "name": name,
            "game_id": game_id,
            "rating": rating,
            "weight": weight,
            "year_published": year_published,
            "min_players": min_players,
            "max_players": max_players,
            "min_play_time": min_play_time,
            "max_play_time": max_play_time,
            "min_age": min_age,
            "owned_by": owned,
            "categories": ', '.join(categories),
            "mechanics": ', '.join(mechanics),
            "designers": ', '.join(designers),
            "artists": ', '.join(artists),
            "publishers": ', '.join(publishers),
        }

        # Append the game (item) to the 'games' list

        games.append(game)

    else:
        # If there is no data for the request - skip to the next one
        print(f">>> Empty item. Skipped item with id ({game_id}).")
        game_id += 1
        continue

    # Increment game id and set sleep timer between requests
    game_id += 1
    time.sleep(SLEEP_BETWEEN_REQUEST)

save_to_csv(games)    

Ci-dessous, vous pouvez prévisualiser les premières lignes d'enregistrements du fichier CSV en tant que pandas DataFrame.

# Preview the CSV as pandas DataFrame
df = pd.read_csv('./BGGdata.csv')
print(df.head(5))

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn