|
@@ -1,5 +1,246 @@
|
|
|
-#!/usr/bin/env python3
|
|
|
+import logging
|
|
|
+from typing import Optional
|
|
|
+
|
|
|
+import requests
|
|
|
+from bs4 import BeautifulSoup
|
|
|
+
|
|
|
+logger = logging.getLogger(__name__)
|
|
|
+
|
|
|
+IPDB_URL = "https://www.ipdb.plus/IPDb/puzzle.php?id={id}"
|
|
|
+
|
|
|
+
|
|
|
+def get_first(key: str, result: dict) -> str:
|
|
|
+ obj = ""
|
|
|
+ if obj_list := result.get(key):
|
|
|
+ obj = obj_list[0]
|
|
|
+ return obj
|
|
|
+
|
|
|
+
|
|
|
+def get_title_from_soup(soup) -> str:
|
|
|
+ title = ""
|
|
|
+ try:
|
|
|
+ title = soup.find("h1").get_text()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ return title
|
|
|
+
|
|
|
+
|
|
|
+def get_manufacturer_from_soup(soup) -> str:
|
|
|
+ manufacturer = ""
|
|
|
+ try:
|
|
|
+ manufacturer = (
|
|
|
+ soup.find(class_="infobox").div.contents[0].split("|")[0].strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return manufacturer
|
|
|
+
|
|
|
+
|
|
|
+def get_pieces_count_from_soup(soup) -> int:
|
|
|
+ pieces = 0
|
|
|
+ try:
|
|
|
+ pieces = int(
|
|
|
+ soup.find(class_="infobox")
|
|
|
+ .div.contents[0]
|
|
|
+ .split("|")[1]
|
|
|
+ .split(" ")[1]
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return pieces
|
|
|
+
|
|
|
+
|
|
|
+def get_publish_year_from_soup(soup) -> int:
|
|
|
+ year = 1900
|
|
|
+ try:
|
|
|
+ year = int(
|
|
|
+ soup.find(class_="infobox").div.contents[0].split("|")[2].strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return year
|
|
|
+
|
|
|
+
|
|
|
+def get_material_from_soup(soup) -> str:
|
|
|
+ material = ""
|
|
|
+ try:
|
|
|
+ material = (
|
|
|
+ soup.findAll(class_="infobox")[1]
|
|
|
+ .findAll("div")[1]
|
|
|
+ .contents[2]
|
|
|
+ .split("|")[-1]
|
|
|
+ .strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return material
|
|
|
+
|
|
|
+
|
|
|
+def get_cut_style_from_soup(soup) -> str:
|
|
|
+ cut_style = ""
|
|
|
+ try:
|
|
|
+ cut_style = (
|
|
|
+ soup.findAll(class_="infobox")[1]
|
|
|
+ .findAll("div")[1]
|
|
|
+ .contents[2]
|
|
|
+ .split("|")[-2]
|
|
|
+ .strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return cut_style
|
|
|
+
|
|
|
+
|
|
|
+def get_barcode_from_soup(soup) -> str:
|
|
|
+ barcode = ""
|
|
|
+ try:
|
|
|
+ barcode = (
|
|
|
+ soup.findAll(class_="infobox")[2]
|
|
|
+ .findAll("div")[0]
|
|
|
+ .contents[0]
|
|
|
+ .split("|")[-1]
|
|
|
+ .split(":")[-1]
|
|
|
+ .strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ if not barcode:
|
|
|
+ try:
|
|
|
+ barcode = (
|
|
|
+ soup.findAll(class_="infobox")[3]
|
|
|
+ .findAll("div")[0]
|
|
|
+ .contents[0]
|
|
|
+ .split("|")[-1]
|
|
|
+ .split(":")[-1]
|
|
|
+ .strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return barcode
|
|
|
+
|
|
|
+
|
|
|
+def get_image_url_from_soup(soup) -> str:
|
|
|
+ url = ""
|
|
|
+ try:
|
|
|
+ url = (
|
|
|
+ soup.find(class_="image-container").contents[0].contents[0]["src"]
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return url
|
|
|
+
|
|
|
+
|
|
|
+def get_orientation_from_soup(soup) -> str:
|
|
|
+ orientation = ""
|
|
|
+ try:
|
|
|
+ orientation = (
|
|
|
+ soup.findAll(class_="infobox")[1]
|
|
|
+ .findAll("div")[1]
|
|
|
+ .contents[0]
|
|
|
+ .split("|")[0]
|
|
|
+ .strip()
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return orientation
|
|
|
+
|
|
|
+
|
|
|
+def get_dimensions_from_soup(soup) -> str:
|
|
|
+ dimensions = ""
|
|
|
+ try:
|
|
|
+ height = (
|
|
|
+ soup.findAll(class_="infobox")[1]
|
|
|
+ .findAll("div")[1]
|
|
|
+ .contents[1]["data-bs-height"]
|
|
|
+ )
|
|
|
+ width = (
|
|
|
+ soup.findAll(class_="infobox")[1]
|
|
|
+ .findAll("div")[1]
|
|
|
+ .contents[1]["data-bs-width"]
|
|
|
+ )
|
|
|
+
|
|
|
+ dimensions = "x".join([height, width])
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+ except ValueError:
|
|
|
+ pass
|
|
|
+ except IndexError:
|
|
|
+ pass
|
|
|
+ return dimensions
|
|
|
+
|
|
|
+
|
|
|
+def get_rating_from_soup(soup) -> str:
|
|
|
+ rating = ""
|
|
|
+ try:
|
|
|
+ rating = float(
|
|
|
+ soup.find(class_="num").get_text().strip("(").strip(")")
|
|
|
+ )
|
|
|
+ except AttributeError:
|
|
|
+ rating = None
|
|
|
+ except ValueError:
|
|
|
+ rating = None
|
|
|
+ return rating
|
|
|
|
|
|
|
|
|
def get_puzzle_from_ipdb_id(ipdb_id: str) -> dict:
|
|
|
- return {}
|
|
|
+ puzzle_url = IPDB_URL.format(id=ipdb_id)
|
|
|
+ headers = {"User-Agent": "Vrobbler 0.11.12"}
|
|
|
+ response = requests.get(puzzle_url, headers=headers)
|
|
|
+ puzzle_dict = {"ipdb_id": ipdb_id}
|
|
|
+
|
|
|
+ if response.status_code != 200:
|
|
|
+ logger.warn(
|
|
|
+ "Bad response from untappd.com", extra={"response": response}
|
|
|
+ )
|
|
|
+ return puzzle_dict
|
|
|
+
|
|
|
+ soup = BeautifulSoup(response.text, "html.parser")
|
|
|
+ puzzle_dict["title"] = get_title_from_soup(soup)
|
|
|
+ puzzle_dict["orientation"] = get_orientation_from_soup(soup)
|
|
|
+ puzzle_dict["manufacturer"] = get_manufacturer_from_soup(soup)
|
|
|
+ puzzle_dict["pieces_count"] = get_pieces_count_from_soup(soup)
|
|
|
+ puzzle_dict["ipdb_image_url"] = get_image_url_from_soup(soup)
|
|
|
+ puzzle_dict["dimensions_in_inches"] = get_dimensions_from_soup(soup)
|
|
|
+ puzzle_dict["publish_year"] = get_publish_year_from_soup(soup)
|
|
|
+ puzzle_dict["material"] = get_material_from_soup(soup)
|
|
|
+ puzzle_dict["cut_style"] = get_cut_style_from_soup(soup)
|
|
|
+ puzzle_dict["barcode"] = get_barcode_from_soup(soup)
|
|
|
+ return puzzle_dict
|