bgg.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. from typing import Optional
  2. import requests
  3. from bs4 import BeautifulSoup
  4. SEARCH_ID_URL = (
  5. "https://boardgamegeek.com/xmlapi/search?search={query}&exact=1"
  6. )
  7. GAME_ID_URL = "https://boardgamegeek.com/xmlapi/boardgame/{id}"
  8. def take_first(thing: Optional[list]) -> str:
  9. first = ""
  10. try:
  11. first = thing[0]
  12. except IndexError:
  13. pass
  14. if first:
  15. first = first.get_text()
  16. return first
  17. def lookup_boardgame_id_from_bgg(title: str) -> Optional[int]:
  18. soup = None
  19. headers = {"User-Agent": "Vrobbler 0.11.12"}
  20. game_id = None
  21. url = SEARCH_ID_URL.format(query=title)
  22. r = requests.get(url, headers=headers)
  23. if r.status_code == 200:
  24. soup = BeautifulSoup(r.text, "xml")
  25. if soup:
  26. result = soup.findAll("boardgame")
  27. if not result:
  28. return game_id
  29. game_id = result[0].get("objectid", None)
  30. return game_id
  31. def lookup_boardgame_from_bgg(lookup_id: str) -> dict:
  32. soup = None
  33. game_dict = {}
  34. headers = {"User-Agent": "Vrobbler 0.11.12"}
  35. title = ""
  36. bgg_id = None
  37. try:
  38. bgg_id = int(lookup_id)
  39. except ValueError:
  40. title = lookup_id
  41. if not bgg_id:
  42. bgg_id = lookup_boardgame_id_from_bgg(title)
  43. url = GAME_ID_URL.format(id=bgg_id)
  44. r = requests.get(url, headers=headers)
  45. if r.status_code == 200:
  46. soup = BeautifulSoup(r.text, "xml")
  47. if soup:
  48. seconds_to_play = None
  49. minutes = take_first(soup.findAll("playingtime"))
  50. if minutes:
  51. seconds_to_play = int(minutes) * 60
  52. game_dict = {
  53. "title": take_first(soup.findAll("name", primary="true")),
  54. "description": take_first(soup.findAll("description")),
  55. "year_published": take_first(soup.findAll("yearpublished")),
  56. "publisher_name": take_first(soup.findAll("boardgamepublisher")),
  57. "cover_url": take_first(soup.findAll("image")),
  58. "min_players": take_first(soup.findAll("minplayers")),
  59. "max_players": take_first(soup.findAll("maxplayers")),
  60. "recommended_age": take_first(soup.findAll("age")),
  61. "run_time_seconds": seconds_to_play,
  62. }
  63. return game_dict