General-API/src/routers/recipe.py

78 lines
2.2 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from recipe_scrapers import scrape_html, scrape_me, WebsiteNotImplementedError, NoSchemaFoundInWildMode
from typing import List, Optional
from pydantic import BaseModel
import logging
router = APIRouter(
prefix="/recipe",
tags=["Recipes", "Web scraping"],
responses={404: {"description": "Not found"}}
)
class IngredientGroup(BaseModel):
ingredients: List[str]
purpose: Optional[str]
class Nutrients(BaseModel):
calories: Optional[str]
carbohydrateContent: Optional[str]
proteinContent: Optional[str]
fatContent: Optional[str]
saturatedFatContent: Optional[str]
cholesterolContent: Optional[str]
sodiumContent: Optional[str]
fiberContent: Optional[str]
sugarContent: Optional[str]
servingSize: Optional[str]
class Recipe(BaseModel):
author: Optional[str]
canonical_url: str
category: str = None
cook_time: int = None
cuisine: str = None
description: str = None
host: str = None
image: str = None
ingredient_groups: List[IngredientGroup]
ingredients: List[str]
instructions: str = None
instructions_list: List[str]
language: str = 'en'
nutrients: Optional[Nutrients]
prep_time: int = None
ratings: float = None
site_name: str = None
title: str = None
total_time: int = None
yields: str = None
@router.get("/")
async def parse_recipe_site(url: str):
recipe_dict = await getRecipe(url)
ret = Recipe.parse_obj(recipe_dict)
return ret
async def getRecipe(url: str) -> str:
logging.info("Recipe requested from " + url)
if len(url) == 0:
raise HttpException(status_code=400, detail="url cannot be empty")
ret = ""
try:
recipe = scrape_me(url, wild_mode=True)
recipe_dict = recipe.to_json()
except NoSchemaFoundInWildMode:
raise HTTPException(status_code=400, detail="Failed to find a recipe on the site. We may have failed to fetch it, or it might really not be a recipe site")
except Exception:
raise HTTPException(status_code=500, detail="Failed to obtain recipe")
logging.info("Recipe found")
logging.info(recipe_dict)
return recipe_dict