From 9787a6230d5e94e760d6fdc82fabb17e5ad7f5f8 Mon Sep 17 00:00:00 2001 From: Ching Date: Mon, 4 Mar 2024 01:56:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(api):=20=E5=A2=9E=E5=8A=A0=E4=BB=8E?= =?UTF-8?q?=E4=B8=8B=E5=8E=A8=E6=88=BF=E5=A4=8D=E5=88=B6=E8=8F=9C=E8=B0=B1?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ recipe.py | 20 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 recipe.py diff --git a/app.py b/app.py index 47c5dbc..61d7190 100644 --- a/app.py +++ b/app.py @@ -1,12 +1,15 @@ # coding = utf-8 import json import os +import re import requests from flask import Flask, jsonify, request from pygrocy import EntityType, Grocy from barcode import BarcodeSpider +from recipe import get_recipe_from_xiachufang +import base64 # config = configparser.ConfigParser() # config.read('config.ini') @@ -174,6 +177,11 @@ def gpc_best_before_days(Code): return day +def convert_image_to_base64(image_content): + base64_image = base64.b64encode(image_content).decode("utf-8") + return base64_image + + @app.route("/") def index(): return "Up and running!" @@ -225,5 +233,57 @@ def consume(): return jsonify(response_data), 400 +@app.route("/add_recipe", methods=["POST"]) +def add_recipe(): + data = request.json + source = data.get("source", "xiachufang") + url = data.get("url", "") + if source != "xiachufang": + response_data = {"message": "Invalid source"} + return jsonify(response_data), 400 + if not url: + response_data = {"message": "Invalid url"} + return jsonify(response_data), 400 + try: + # https://www.xiachufang.com/recipe/107141278/?recipe_type=1&page_scene=6 + recipe_number = re.search(r'(\d+)', url).group(1) + resp = grocy.get_generic_objects_for_type(EntityType.RECIPES, ['name~%s' % recipe_number]) + if resp: + response_data = {"message": "Recipe already exists"} + return jsonify(response_data), 400 + xcf_recipe = get_recipe_from_xiachufang(url) + description = "" + if xcf_recipe['ingredients']: + description += "

用料

\n" + description += "\n" + if xcf_recipe['steps']: + description += "

做法

\n" + for idx, step in enumerate(xcf_recipe["steps"]): + description += f"

步骤 {idx+1}

\n" + description += f'

{step[0]}

\n' + if len(step) == 1: + description += "
" + continue + img = requests.get(step[1]) + img_data = 'data:image/png;base64,' + convert_image_to_base64(img.content) + description += f'\n\n\n' + description += "
" + + data_grocy = { + "name": xcf_recipe["name"] + " - " + recipe_number, + "description": description + } + grocy.add_generic(EntityType.RECIPES, data_grocy) + response_data = {"message": "Recipe added successfully"} + except Exception as e: + error_message = str(e) + response_data = {"message": error_message} + return jsonify(response_data), 400 + return jsonify(response_data), 200 + + if __name__ == "__main__": app.run(host="0.0.0.0", port=9288) diff --git a/recipe.py b/recipe.py new file mode 100644 index 0000000..68ce597 --- /dev/null +++ b/recipe.py @@ -0,0 +1,20 @@ +import requests +import bs4 + +ua = 'Mozilla/5.0.html (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.html.2171.71 Safari/537.36' + +def get_recipe_from_xiachufang(url): + headers = {'User-Agent': ua} + response = requests.get(url, headers=headers) + response.raise_for_status() + soup = bs4.BeautifulSoup(response.text, 'html.parser') + name = soup.find('h1', class_='page-title').text.strip() + ingredients = [] + for ingredient in soup.find('div', class_='ings').find('table').find_all('tr'): + ingredients.append(' / '.join([td.text.strip() for td in ingredient.find_all('td')])) + + steps = [] + for step in soup.find('div', class_='steps').find('ol').find_all('li'): + steps.append([step.find('p').text.strip(), step.find('img')['src']]) + + return {'name': name, 'ingredients': ingredients, 'steps': steps}