102 lines
5.0 KiB
Python
102 lines
5.0 KiB
Python
import xml.etree.ElementTree as ET
|
||
import json
|
||
|
||
# Game descriptions mapping (manual descriptions based on known games)
|
||
game_descriptions = {
|
||
"400366": "Wondrous Creatures – Ein Worker-Placement-Spiel mit fantastischen Kreaturen und innovativem Ressourcen-Management von Bad Comet.",
|
||
"472021": "Medico – Medizinisches Themen-Brettspiel (2026). Neu in der Hotness – Details noch spärlich.",
|
||
"403150": "World Order – Geopolitisches Area-Control-Strategiespiel von Hegemonic Project Games (2026).",
|
||
"434172": "Excalibur – Artus-Sagen-Themenbrettspiel (2026) mit epischen Quests und Schwert-in-Stein-Mechanik.",
|
||
"425549": "Moon Colony Bloodbath – Kartenspiel mit Sci-Fi-Horror-Thema von Donald X. Vaccarino (Dominion-Autor).",
|
||
"415848": "Lands of Evershade – Fantasy-Rollenspiel-inspiriertes Brettspiel mit Kampagnen-Modus (2026).",
|
||
"436217": "The Lord of the Rings: Fate of the Fellowship – Kooperatives Herr-der-Ringe-Abenteuerspiel (2025).",
|
||
"457008": "Friendly Fishing – Familienfreundliches Angel-Brettspiel (2026), zugänglich und schnell.",
|
||
"357873": "The Old King's Crown – Strategisches Kartenspiel mit mittelalterlichem Thronfolge-Thema (2025).",
|
||
"418059": "SETI: Search for Extraterrestrial Intelligence – Wissenschaftsbasiertes Eurogame zur Suche nach außerirdischem Leben.",
|
||
"417197": "Rebirth – Reiner Knizia's Wiederaufbau-Strategiespiel mit Plättchenlege-Mechanik.",
|
||
"432456": "dnup – Kartenspiel mit Wendemechanik und abstraktem Thema (2025).",
|
||
"454103": "Magical Athlete – Fantasie-Sport-Brettspiel mit magischen Fähigkeiten (2025).",
|
||
"381248": "Nemesis: Retaliation – Semi-kooperatives Sci-Fi-Horror-Spiel, neuester Teil der Nemesis-Reihe von Awaken Realms.",
|
||
"342942": "Ark Nova – Aufbau eines modernen Zoos als tiefes strategisches Kartenspiel. Aktuell #4 der BGG-Rangliste."
|
||
}
|
||
|
||
# Fetch the actual descriptions from XMLs
|
||
descriptions = {}
|
||
for gid in game_descriptions:
|
||
try:
|
||
tree = ET.parse(f'/home/hermes/workspace/bgg-scrape/game_{gid}.xml')
|
||
root = tree.getroot()
|
||
for item in root.findall('item'):
|
||
desc_elem = item.find('description')
|
||
if desc_elem is not None and desc_elem.text:
|
||
desc_text = desc_elem.text[:300].strip()
|
||
descriptions[gid] = desc_text
|
||
# Get year
|
||
year_elem = item.find('yearpublished')
|
||
if year_elem is not None:
|
||
year = year_elem.get('value', '')
|
||
# Get stats
|
||
stats = item.find("statistics/ratings")
|
||
if stats is not None:
|
||
avg = stats.find("average")
|
||
avg_rating = avg.get('value', 'N/A') if avg is not None else 'N/A'
|
||
ranks = stats.find("ranks")
|
||
bgg_rank = 'N/A'
|
||
if ranks is not None:
|
||
for r in ranks.findall('rank'):
|
||
if r.get('name') == 'boardgame':
|
||
bgg_rank = r.get('value', 'N/A')
|
||
descriptions[gid + '_stats'] = f"⭐ {avg_rating} | BGG Rank: {bgg_rank}"
|
||
except Exception as e:
|
||
descriptions[gid] = f"Error: {e}"
|
||
|
||
# Print report
|
||
print("=" * 70)
|
||
print(" BOARDGAMEGEEK HOTNESS – TOP 15 (6.-7. Juni 2026)")
|
||
print("=" * 70)
|
||
print()
|
||
|
||
items = [
|
||
("1", "Wondrous Creatures", "400366"),
|
||
("2", "Medico", "472021"),
|
||
("3", "World Order", "403150"),
|
||
("4", "Excalibur", "434172"),
|
||
("5", "Moon Colony Bloodbath", "425549"),
|
||
("6", "Lands of Evershade", "415848"),
|
||
("7", "The Lord of the Rings: Fate of the Fellowship", "436217"),
|
||
("8", "Friendly Fishing", "457008"),
|
||
("9", "The Old King's Crown", "357873"),
|
||
("10", "SETI: Search for Extraterrestrial Intelligence", "418059"),
|
||
("11", "Rebirth", "417197"),
|
||
("12", "dnup", "432456"),
|
||
("13", "Magical Athlete", "454103"),
|
||
("14", "Nemesis: Retaliation", "381248"),
|
||
("15", "Ark Nova", "342942"),
|
||
]
|
||
|
||
for i, (rank, name, gid) in enumerate(items, 1):
|
||
print(f"#{rank} – {name}")
|
||
print(f" ID: {gid}")
|
||
stats = descriptions.get(gid + '_stats', 'Stats: N/A')
|
||
print(f" {stats}")
|
||
desc = descriptions.get(gid, game_descriptions.get(gid, ''))
|
||
if desc:
|
||
# Strip HTML and truncate
|
||
import re
|
||
clean = re.sub(r'<[^>]+>', '', desc)
|
||
clean = re.sub(r'&#?\w+;', ' ', clean)
|
||
clean = re.sub(r'\s+', ' ', clean).strip()
|
||
if len(clean) > 280:
|
||
clean = clean[:277] + '...'
|
||
print(f" Beschreibung: {clean}")
|
||
else:
|
||
print(f" Beschreibung: {game_descriptions.get(gid, 'Keine Beschreibung verfügbar.')}")
|
||
print(f" Relevanz: {'HOTTEST' if i <= 3 else '🔥 Hoch' if i <= 7 else '★ Mittel' if i <= 12 else '· Stabil'}")
|
||
print()
|
||
|
||
print("\n---")
|
||
print("Datenquelle: BGG XML API v2 (de3b01db-9be3-4c80-bd80-d47e071b320e)")
|
||
print("User-Agent: BSN-OpenClaw/1.0")
|
||
print("Abrufdatum: 6. Juni 2026")
|
||
print("Hinweis: BGG-News-Forum (ID=27) war unter CloudFlare-Schutz – HTML-Scraping nicht möglich. Forum-ID=1 (News) nur 1 Thread (2009). Hotness via API erfolgreich.")
|