Created
November 11, 2022 14:40
-
-
Save kcleong/610e11d876caf38622850c22d2639f6e to your computer and use it in GitHub Desktop.
Example script to get ikea article numbers from a kitchen plan
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Example output: | |
41x: 60205664 | METOD | grijs | 200 cm | Kitchen cabinets | |
38x: 80338413 | BAGGANÄS | zwart | 143 mm | Knobs and handles | |
24x: 40205599 | METOD | zwart | 8 cm | Kitchen cabinets | |
19x: 70338418 | BAGGANÄS | grijs | 143 mm | Knobs and handles | |
18x: 40327505 | FÖRBÄTTRA | wit | 220x8 cm | Kitchen fronts | |
8x: 00455161 | ÄLMAREN | Kitchen taps, sinks and sink accessories | |
6x: 20317852 | LILLVIKEN | grijs | Kitchen taps, sinks and sink accessories | |
6x: 00380590 | UTRUSTA | grijs | Kitchen fixed interiors | |
5x: 60411720 | ANRÄTTA | grijs | Cooking Appliances | |
5x: 70213569 | METOD | wit | 60x60x80 cm | Kitchen cabinets | |
5x: 50467883 | SMAKLIG | zwart | 59 cm | Cooking Appliances | |
4x: 90213573 | UTRUSTA | wit | 60x60 cm | Kitchen fixed interiors | |
4x: 60499954 | TINAD | wit | 210/79 l | Cooling Appliances | |
4x: 10311539 | LILLVIKEN | grijs | Kitchen taps, sinks and sink accessories | |
4x: 90311540 | LILLVIKEN | grijs | Kitchen taps, sinks and sink accessories | |
4x: 00518192 | VÅGLIG | Appliances Accessories | |
4x: 90250259 | NYTTIG TUB 150 | grijs | Appliances Accessories | |
4x: 80398058 | HÅLLBAR | grijs | 10 l | Sorting solutions | |
3x: 30221458 | METOD | grijs | 60 cm | Kitchen cabinets | |
3x: 40475572 | RENGÖRA | 60 cm | Dish Care Appliances | |
3x: 90421336 | NYTTIG FIL 120 | groen | 2 st. | Appliances Accessories | |
3x: 10389142 | UTDRAG | grijs | 60 cm | Cooking Appliances | |
2x: 40368770 | MATÄLSKARE | grijs | Cooking Appliances | |
2x: 10411765 | ANRÄTTA | grijs | Cooking Appliances | |
2x: 50462480 | UTRUSTA | wit | Kitchen fixed interiors | |
2x: 80433882 | HÅLLBAR | grijs | 10 l | Kitchen accessories | |
2x: 80422869 | HÅLLBAR | wit | 60 cm | Kitchen fixed interiors | |
1x: 40368765 | MATÄLSKARE | grijs | Cooking Appliances | |
1x: 30475233 | AXSTAD | blauw | 45x80 cm | Kitchen fronts | |
1x: 80524882 | UTRUSTA | 110 ° | Kitchen fixed interiors | |
1x: 00401955 | NYTTIG FIL 500 | zwart | 2 st. | Appliances Accessories | |
1x: 70389139 | UNDERVERK | grijs | 60 cm | Cooking Appliances | |
1x: 20204647 | UTRUSTA | grijs | 95 ° | Kitchen fixed interiors | |
1x: 20205543 | METOD | zwart | 60x60x80 cm | Kitchen cabinets | |
1x: 50215475 | METOD | wit | 80x60x80 cm | Kitchen cabinets | |
1x: 90475616 | RENODLAD | 60 cm | Dish Care Appliances | |
""" | |
from collections import Counter | |
from dataclasses import dataclass | |
from typing import Dict | |
import ikea_api | |
import requests | |
KITCHEN_URL = 'https://byme-ikea-prod.s3.eu-west-1.amazonaws.com/data/homebymeProjects/19E27F6B-470C-49CD-AB9A-221613A0A12F/19E27F6B-470C-49CD-AB9A-221613A0A12F.BMPROJ' | |
@dataclass | |
class IkeaProduct: | |
data: Dict | |
def __str__(self): | |
values = ( | |
self.id, | |
self.name, | |
self.color, | |
self.data.get("itemMeasureReferenceText"), | |
self.type_name, | |
self.product_area_name, | |
) | |
return ' | '.join([ | |
value for value in values if value | |
]) | |
def __hash__(self) -> int: | |
return hash(self.id) | |
@property | |
def id(self): | |
return self.data['itemNo'] | |
@property | |
def name(self): | |
return self.data['name'] | |
@property | |
def type_name(self): | |
return self.data.get('type_name') | |
@property | |
def color(self): | |
for color in self.data.get('colors', []): | |
return color['name'] | |
@property | |
def product_area_name(self): | |
return self.data['businessStructure']['productRangeAreaName'] | |
@property | |
def is_kitchen_front(self): | |
raise NotImplementedError() | |
class KitchenDrawerExample: | |
def __init__(self, url): | |
self.url = url | |
self.api_constants = ikea_api.Constants(country="nl", language="nl") | |
def run(self): | |
response = requests.get(self.url) | |
response.raise_for_status() | |
kitchen_json = response.json() | |
article_numbers = list(self.recursively_get_article_number(kitchen_json)) | |
products = [ | |
item for item in map(self.get_product, article_numbers) if item | |
] | |
for product, count in Counter(products).most_common(): | |
print(f'{count}x: {product}') | |
@classmethod | |
def recursively_get_article_number(cls, values): | |
if isinstance(values, dict): | |
for key, value in values.items(): | |
yield from cls.recursively_get_article_number(value) | |
elif isinstance(values, list) or isinstance(values, tuple): | |
for child_value in values: | |
yield from cls.recursively_get_article_number(child_value) | |
elif isinstance(values, str) and values.startswith('ART-'): | |
yield values | |
def ikea_search(self, value): | |
search = ikea_api.Search(self.api_constants) | |
endpoint = search.search(value) | |
return ikea_api.run(endpoint) | |
def get_product(self, product_id): | |
product_id = product_id.replace('ART-', '').replace('-NL', '') | |
search_results = self.ikea_search(product_id) | |
search_response = search_results.get('searchResultPage') | |
product_items = search_response.get('products', {}).get('main', {}).get('items', []) | |
for product_item in product_items: | |
product_data = product_item.get('product') | |
if not product_data: | |
continue | |
product = IkeaProduct(data=product_data) | |
if product.id != product_id: | |
continue | |
return product | |
example = KitchenDrawerExample(KITCHEN_URL) | |
example.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment