feat(api): 增加从下厨房复制菜谱的功能
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Ching 2024-03-04 01:56:10 +08:00
parent d03190e810
commit 9787a6230d
2 changed files with 80 additions and 0 deletions

60
app.py
View File

@ -1,12 +1,15 @@
# coding = utf-8 # coding = utf-8
import json import json
import os import os
import re
import requests import requests
from flask import Flask, jsonify, request from flask import Flask, jsonify, request
from pygrocy import EntityType, Grocy from pygrocy import EntityType, Grocy
from barcode import BarcodeSpider from barcode import BarcodeSpider
from recipe import get_recipe_from_xiachufang
import base64
# config = configparser.ConfigParser() # config = configparser.ConfigParser()
# config.read('config.ini') # config.read('config.ini')
@ -174,6 +177,11 @@ def gpc_best_before_days(Code):
return day return day
def convert_image_to_base64(image_content):
base64_image = base64.b64encode(image_content).decode("utf-8")
return base64_image
@app.route("/") @app.route("/")
def index(): def index():
return "Up and running!" return "Up and running!"
@ -225,5 +233,57 @@ def consume():
return jsonify(response_data), 400 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 += "<h2>用料</h2>\n"
description += "<ul>\n"
for ingredient in xcf_recipe["ingredients"]:
description += f'<li>{ingredient}</li>\n'
description += "</ul>\n"
if xcf_recipe['steps']:
description += "<h2>做法</h2>\n"
for idx, step in enumerate(xcf_recipe["steps"]):
description += f"<h3>步骤 {idx+1}</h3>\n"
description += f'<p>{step[0]}</p>\n'
if len(step) == 1:
description += "<br>"
continue
img = requests.get(step[1])
img_data = 'data:image/png;base64,' + convert_image_to_base64(img.content)
description += f'\n<img src=\"{img_data}\">\n\n'
description += "<br>"
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__": if __name__ == "__main__":
app.run(host="0.0.0.0", port=9288) app.run(host="0.0.0.0", port=9288)

20
recipe.py Normal file
View File

@ -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}