Kyllingetærte med butterdejslåg
Brug dine grøntsags- og kyllingerester i en lun tærte til middagsbordet. Det sprøde butterdejslåg er prikken over i'et.

(0)
From 74c5de268029d2559a72a9cd798d0d93773abd48 Mon Sep 17 00:00:00 2001 From: Jacob Rasmussen <2988654+jacrasmussen@users.noreply.github.com> Date: Sun, 2 Feb 2025 23:50:46 +0100 Subject: [PATCH] Add scraper support for spisbedre.dk (#1486) (#1487) * Add scraper support for spisbedre.dk (#1486) * Reorder JSON unit tests --- recipe_scrapers/__init__.py | 2 + recipe_scrapers/spisbedre.py | 143 ++ tests/test_data/spisbedre.dk/spisbedre_1.json | 60 + .../spisbedre.dk/spisbedre_1.testhtml | 328 +++++ tests/test_data/spisbedre.dk/spisbedre_2.json | 63 + .../spisbedre.dk/spisbedre_2.testhtml | 1230 +++++++++++++++++ 6 files changed, 1826 insertions(+) create mode 100644 recipe_scrapers/spisbedre.py create mode 100644 tests/test_data/spisbedre.dk/spisbedre_1.json create mode 100644 tests/test_data/spisbedre.dk/spisbedre_1.testhtml create mode 100644 tests/test_data/spisbedre.dk/spisbedre_2.json create mode 100644 tests/test_data/spisbedre.dk/spisbedre_2.testhtml diff --git a/recipe_scrapers/__init__.py b/recipe_scrapers/__init__.py index 11c06f155..5f784cccb 100644 --- a/recipe_scrapers/__init__.py +++ b/recipe_scrapers/__init__.py @@ -372,6 +372,7 @@ from .southernliving import SouthernLiving from .spainonafork import SpainOnAFork from .spendwithpennies import SpendWithPennies +from .spisbedre import SpisBedre from .springlane import Springlane from .stacyling import StacyLing from .staysnatched import StaySnatched @@ -633,6 +634,7 @@ SavoryNothings.host(): SavoryNothings, SheLikesFood.host(): SheLikesFood, SpainOnAFork.host(): SpainOnAFork, + SpisBedre.host(): SpisBedre, StacyLing.host(): StacyLing, StrongrFastr.host(): StrongrFastr, SugarHero.host(): SugarHero, diff --git a/recipe_scrapers/spisbedre.py b/recipe_scrapers/spisbedre.py new file mode 100644 index 000000000..29a6071dd --- /dev/null +++ b/recipe_scrapers/spisbedre.py @@ -0,0 +1,143 @@ +import json + +from ._abstract import AbstractScraper +from ._grouping_utils import IngredientGroup + + +class SpisBedre(AbstractScraper): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.recipe_json = json.loads( + self.soup.find("div", id="app").attrs["data-page"] + )["props"]["recipe"] + + @classmethod + def host(cls): + return "spisbedre.dk" + + def author(self): + return self.schema.author() + + def title(self): + return self.schema.title() + + def category(self): + return ", ".join([type["name"] for type in self.recipe_json.get("tags", [])]) + + def total_time(self): + return self.schema.total_time() + + def yields(self): + return self.schema.yields() + + def ingredients(self): + result = [] + for ingredient_group in self.ingredient_groups(): + result.extend(ingredient_group.ingredients) + return result + + def ingredient_groups(self): + result = [] + servings = self.recipe_json.get("serving_size", 1) + + def format_ingredient(servings, ingredient): + ingredient_elements = [] + + def ingredient_label(amount, inflection, ingredient, prefix, suffix): + label = [] + if ingredient is None: + return None + + if prefix: + label.append(prefix) + + if inflection in ["singular", "plural"]: + label.append(ingredient.get("name_" + inflection)) + elif amount and amount > 0 and amount < 2: + label.append(ingredient.get("name_singular")) + else: + label.append(ingredient.get("name_plural")) + + if suffix: + label.append(suffix) + + return " ".join(label) + + def unit_label(amount, inflection, texts): + label = [] + if amount is None or texts is None: + return None + + if texts.get("abbreviation"): + label.append(texts.get("abbreviation")) + elif inflection in ["singular", "plural"]: + label.append(texts.get("name_" + inflection)) + elif amount > 0 and amount < 2: + label.append(texts.get("name_singular")) + else: + label.append(texts.get("name_plural")) + + return " ".join(label) + + total_amount = amount = ingredient.get("amount") + if amount: + total_amount = amount * servings + if int(total_amount) == total_amount: + total_amount = int(total_amount) + ingredient_elements.append(str(total_amount)) + + # For some reason unit_id 21 isn't rendered on the site, so we filter it as well + if ingredient.get("unit_id") != 21: + unit = unit_label( + total_amount, + ingredient.get("unit_inflection"), + ingredient.get("unit"), + ) + if unit: + ingredient_elements.append(unit) + + label = ingredient_label( + total_amount, + ingredient.get("ingredient_inflection"), + ingredient.get("ingredient"), + ingredient.get("prefix"), + ingredient.get("suffix"), + ) + if label: + ingredient_elements.append(label) + + return " ".join(ingredient_elements) + + for group in self.recipe_json.get("grouped_ingredients", []): + current_group = {"ingredients": [], "purpose": group.get("title")} + for ingredient in group.get("ingredients", []): + formatted_ingredient = format_ingredient(servings, ingredient) + if formatted_ingredient: + current_group["ingredients"].append(formatted_ingredient) + + result.append(current_group) + + return [ + IngredientGroup( + ingredient_group["ingredients"], ingredient_group["purpose"] + ) + for ingredient_group in result + ] + + def instructions(self): + result = [] + for group in self.recipe_json.get("grouped_instructions", []): + for instruction in group.get("instructions", []): + if instruction.get("instruction"): + result.append(instruction.get("instruction")) + + return "\n".join(result) + + def ratings(self): + return self.schema.ratings() + + def cuisine(self): + return self.schema.cuisine() + + def description(self): + return self.schema.description() diff --git a/tests/test_data/spisbedre.dk/spisbedre_1.json b/tests/test_data/spisbedre.dk/spisbedre_1.json new file mode 100644 index 000000000..0f6c255c6 --- /dev/null +++ b/tests/test_data/spisbedre.dk/spisbedre_1.json @@ -0,0 +1,60 @@ +{ + "author": "Louisa Lorang", + "canonical_url": "https://spisbedre.dk/opskrifter/kyllingetaerte-med-butterdejslag", + "site_name": "SPIS BEDRE", + "host": "spisbedre.dk", + "language": "da", + "title": "Kyllingetærte med butterdejslåg", + "ingredients": [ + "2 stilke bladselleri", + "2 gulerødder", + "1 porre", + "2 fed hvidløg", + "2 spsk. olivenolie til stegning", + "salt og peber", + "50 g smør", + "50 g hvedemel", + "2 dl hønsebouillon", + "2 dl piskefløde", + "300 g kogt kyllingebrystfilet", + "200 g ærter fra frost", + "1 spsk. frisk timian", + "1 rulle butterdej", + "1 æg til pensling" + ], + "ingredient_groups": [ + { + "ingredients": [ + "2 stilke bladselleri", + "2 gulerødder", + "1 porre", + "2 fed hvidløg", + "2 spsk. olivenolie til stegning", + "salt og peber", + "50 g smør", + "50 g hvedemel", + "2 dl hønsebouillon", + "2 dl piskefløde", + "300 g kogt kyllingebrystfilet", + "200 g ærter fra frost", + "1 spsk. frisk timian", + "1 rulle butterdej", + "1 æg til pensling" + ], + "purpose": null + } + ], + "instructions_list": [ + "Rens bladselleri, og skær dem i tynde skiver. Skrub eller skræl gulerødderne, og skær dem i tern. Rens porre, og pil hvidløg. Hak begge dele fint.", + "Steg alle grøntsagerne i olie i en stor, dyb pande. De skal ikke tage farve, men falde let sammen. Krydr dem med salt og peber. Tag grøntsagerne af panden, og læg dem til side på en stor tallerken.", + "Smelt smør i den samme pande. Pisk mel i. Tilsæt langsomt bouillon under piskning. Pisk, til saucen er glat. Tilsæt fløde, og lad saucen simre i 4-5 minutter.", + "Tænd ovnen på 220°. Skær kyllingebrystfilet i strimler. Vend kyllingestrimler, grøntsager og ærter i saucen. Skyl og pluk timian. Kog saucen op, og smag til med timian, salt og peber.", + "Fordel fyldet i en tærteform. Rul butterdejen ud, og læg den forsigtigt over fyldet. Klem overskydende dej sammen rundt i kanten. Klip et par små huller i midten af butterdejslåget, så damp kan slippe ud.", + "Pisk æg med 1½ spsk. koldt vand, og pensl butterdejslåget. Bag tærten i ovnen i ca. 20 minutter, til den er gylden og lækker. Servér den lun, evt. med salat til." + ], + "category": "Hovedretter", + "yields": "4 servings", + "description": "Brug dine grøntsags- og kyllingerester i en lun tærte til middagsbordet. Det sprøde butterdejslåg er prikken over i'et.", + "total_time": 40, + "image": "https://spisbedre-production-app.imgix.net/images/recipes/kyllingetaerte-med-butterdejslag_15964.jpg?fit=crop&crop=focalpoint&fp-x=0.44097082638046&fp-y=0.66429758726712&fp-z=1.25" +} diff --git a/tests/test_data/spisbedre.dk/spisbedre_1.testhtml b/tests/test_data/spisbedre.dk/spisbedre_1.testhtml new file mode 100644 index 000000000..043387d62 --- /dev/null +++ b/tests/test_data/spisbedre.dk/spisbedre_1.testhtml @@ -0,0 +1,328 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Brug dine grøntsags- og kyllingerester i en lun tærte til middagsbordet. Det sprøde butterdejslåg er prikken over i'et.
(0)
Hvad enten der er tale om frokost eller aftensmad, kan du altid spise stegt makrel med møre kartofler toppet med surt og sødt.
++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (1) + + +
+