feat(api): 增加从下厨房复制菜谱的功能
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d03190e810
commit
9787a6230d
60
app.py
60
app.py
@ -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
20
recipe.py
Normal 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}
|
||||||
Loading…
x
Reference in New Issue
Block a user