78 lines
2.2 KiB
Python
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
|
|
|