✨ use tandoor json, directly from the api
This commit is contained in:
parent
f89a9683e0
commit
b2ab88b216
80 changed files with 20922 additions and 1996 deletions
135
2_to_markdown.py
135
2_to_markdown.py
|
@ -13,28 +13,44 @@ from config import *
|
|||
include_title = False
|
||||
|
||||
|
||||
def valid_duration(duration):
|
||||
if not duration:
|
||||
return False
|
||||
if duration == "0":
|
||||
return False
|
||||
return True
|
||||
|
||||
def valid_description(description):
|
||||
if not description:
|
||||
return False
|
||||
return True
|
||||
|
||||
def parse_duration(duration):
|
||||
if not duration:
|
||||
return ""
|
||||
match = re.match(r"PT(?:(\d+)H)?(?:(\d+)M)?", duration)
|
||||
if not match:
|
||||
return duration
|
||||
hours, minutes = match.groups()
|
||||
hours = f"{int(hours)}h " if hours else ""
|
||||
minutes = f"{int(minutes)}m" if minutes else ""
|
||||
return f"{hours}{minutes}".strip()
|
||||
|
||||
def normalize_amount(a):
|
||||
if a == round(a):
|
||||
return round(a)
|
||||
else:
|
||||
return a
|
||||
|
||||
def md_for_step_ingredients(step):
|
||||
md = []
|
||||
for ingredient in step['ingredients']:
|
||||
i_amount = ingredient["amount"]
|
||||
i_amount = normalize_amount(i_amount)
|
||||
|
||||
if not ingredient.get("unit"):
|
||||
i_unit = ""
|
||||
else:
|
||||
i_unit = ingredient["unit"]["name"]
|
||||
# TODO → 1_clean_json.py
|
||||
if i_unit == "g / Gramm":
|
||||
i_unit = "g"
|
||||
elif i_unit == "kg / Kilogramm":
|
||||
i_unit = "kg"
|
||||
|
||||
if not ingredient.get("food"):
|
||||
# TODO → 1_clean_json.py
|
||||
continue
|
||||
i_name = ingredient["food"]["name"]
|
||||
|
||||
if i_amount:
|
||||
md.append(f"- {i_amount} {i_unit} {i_name}")
|
||||
else:
|
||||
md.append(f"- {i_name}")
|
||||
return md
|
||||
|
||||
def format_recipe_to_markdown(recipe):
|
||||
md = []
|
||||
|
@ -49,68 +65,50 @@ def format_recipe_to_markdown(recipe):
|
|||
|
||||
# Details
|
||||
details_parts = []
|
||||
if valid_duration(recipe.get('prepTime')):
|
||||
details_parts.append(f"Prep time: {parse_duration(recipe['prepTime'])}")
|
||||
if valid_duration(recipe.get('cookTime')):
|
||||
details_parts.append(f"Cook time: {parse_duration(recipe['cookTime'])}")
|
||||
if valid_duration(recipe.get('totalTime')):
|
||||
details_parts.append(f"Total time: {parse_duration(recipe['totalTime'])}")
|
||||
if 'recipeYield' in recipe:
|
||||
details_parts.append(f"Portionen: {recipe['recipeYield']}")
|
||||
prep_time = recipe.get("working_time") or 0
|
||||
total_time = (recipe.get("working_time") or 0) + (recipe.get("waiting_time") or 0)
|
||||
if prep_time:
|
||||
details_parts.append(f"Prep time: {prep_time}")
|
||||
if total_time:
|
||||
details_parts.append(f"Total time: {total_time}")
|
||||
if 'servings' in recipe:
|
||||
details_parts.append(f"Portionen: {recipe['servings']}")
|
||||
# TODO servings_text
|
||||
if details_parts:
|
||||
for p in details_parts:
|
||||
md.append(f"* {p}\n")
|
||||
|
||||
# Ingredients
|
||||
if 'recipeIngredient' in recipe:
|
||||
md.append("\n## Zutaten")
|
||||
for ingredient in recipe['recipeIngredient']:
|
||||
md.append(f"- {ingredient}")
|
||||
md.append("\n## Zutaten (gesamt)")
|
||||
for step in recipe["steps"]:
|
||||
md += md_for_step_ingredients(step)
|
||||
|
||||
# Instructions
|
||||
if 'recipeInstructions' in recipe:
|
||||
if 'steps' in recipe:
|
||||
md.append("\n## Zubereitung")
|
||||
instructions = recipe['recipeInstructions']
|
||||
if isinstance(instructions, list):
|
||||
for i, step in enumerate(instructions, 1):
|
||||
assert isinstance(step, dict)
|
||||
text = step.get('text', '').strip()
|
||||
steps = recipe['steps']
|
||||
for i, step in enumerate(steps, 1):
|
||||
step_name = step["name"] or "<span></span>"
|
||||
md.append(f"{i}. {step_name}")
|
||||
md += md_for_step_ingredients(step)
|
||||
md.append(f"{step["instructions_markdown"]}")
|
||||
|
||||
# "ingredient-only" steps shouldn't exist, but they do
|
||||
if not text:
|
||||
continue
|
||||
|
||||
md.append(f"{i}.\n{text}")
|
||||
else:
|
||||
for i, line in enumerate(instructions.strip().split('\n'), 1):
|
||||
if line.strip():
|
||||
md.append(f"{i}. {line.strip()}")
|
||||
|
||||
# Nutrition
|
||||
if 'nutrition' in recipe:
|
||||
md.append("\n## Nutrition")
|
||||
for key, value in recipe['nutrition'].items():
|
||||
if key != "@type":
|
||||
md.append(f"- **{key.replace('_', ' ').capitalize()}**: {value}")
|
||||
# Nutrition TODO
|
||||
# if 'nutrition' in recipe and recipe['nutrition']:
|
||||
# md.append("\n## Nutrition")
|
||||
# for key, value in recipe['nutrition'].items():
|
||||
# if key != "@type":
|
||||
# md.append(f"- **{key.replace('_', ' ').capitalize()}**: {value}")
|
||||
|
||||
return '\n'.join(md) + '\n'
|
||||
|
||||
def main(json_file):
|
||||
with open(json_file, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
def main():
|
||||
|
||||
# If the JSON-LD is embedded in @graph or a list
|
||||
# if isinstance(data, list):
|
||||
# recipe = next((item for item in data if item.get('@type') == 'Recipe'), data[0])
|
||||
# elif '@graph' in data:
|
||||
# recipe = next((item for item in data['@graph'] if item.get('@type') == 'Recipe'), data['@graph'][0])
|
||||
if isinstance(data, list) and data[0].get('@type') == 'Recipe':
|
||||
recipes = data
|
||||
elif data.get('@type') == 'Recipe':
|
||||
recipes = [data]
|
||||
else:
|
||||
print("No Recipe object found in JSON.")
|
||||
return
|
||||
recipes = []
|
||||
for json_file in os.listdir(OUTDIR_JSON):
|
||||
with open(os.path.join(OUTDIR_JSON, json_file), 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
recipes.append(data)
|
||||
|
||||
for recipe in tqdm(recipes):
|
||||
markdown_fn = f"{recipe.get('name', 'Untitled Recipe')}.md"
|
||||
|
@ -121,8 +119,5 @@ def main(json_file):
|
|||
f.write(markdown)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python recipe_to_md.py <path_to_recipe_json>")
|
||||
else:
|
||||
main(sys.argv[1])
|
||||
main()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue