feat: tag management — scrape, edit, search existing, import to Mealie/Tandoor
- Scraper extracts tags from mindmegette.hu (<a class="tag">) and schema.org keywords - Tag editor UI with removable chips, search/autocomplete for existing tags, custom add - Mealie: auto-create tags via POST /api/organizers/tags, include in recipe PATCH - Tandoor: include keywords in recipe POST (auto-created by name) - New GET /tags endpoint returns existing tags from both services for search Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ def scrape(url: str) -> dict:
|
||||
"image_url": str | None,
|
||||
"ingredients": [{"quantity": str, "unit": str, "food": str, "extra": str}, ...],
|
||||
"instructions": [str, ...],
|
||||
"tags": [str, ...],
|
||||
"original_url": str,
|
||||
}
|
||||
|
||||
@@ -139,12 +140,22 @@ def _parse_mindmegette(soup: BeautifulSoup, url: str) -> dict:
|
||||
if txt:
|
||||
instructions.append(txt)
|
||||
|
||||
# --- Tags ---
|
||||
tags = []
|
||||
tag_wrapper = soup.select_one("div.desktop-wrapper")
|
||||
if tag_wrapper:
|
||||
for a in tag_wrapper.select("a.tag"):
|
||||
tag_text = a.get_text(strip=True)
|
||||
if tag_text:
|
||||
tags.append(tag_text)
|
||||
|
||||
return {
|
||||
"title": title or "Ismeretlen recept",
|
||||
"description": description,
|
||||
"image_url": image_url,
|
||||
"ingredients": ingredients,
|
||||
"instructions": instructions,
|
||||
"tags": tags,
|
||||
"original_url": url,
|
||||
}
|
||||
|
||||
@@ -161,6 +172,7 @@ def _parse_generic(soup: BeautifulSoup, url: str) -> dict:
|
||||
|
||||
ingredients = []
|
||||
instructions = []
|
||||
tags = []
|
||||
|
||||
# Try schema.org JSON-LD
|
||||
for script in soup.find_all("script", type="application/ld+json"):
|
||||
@@ -180,6 +192,12 @@ def _parse_generic(soup: BeautifulSoup, url: str) -> dict:
|
||||
instructions.append(item)
|
||||
elif isinstance(item, dict):
|
||||
instructions.append(item.get("text", ""))
|
||||
# Extract keywords
|
||||
kw = data.get("keywords", "")
|
||||
if isinstance(kw, str):
|
||||
tags = [k.strip() for k in kw.split(",") if k.strip()]
|
||||
elif isinstance(kw, list):
|
||||
tags = [str(k).strip() for k in kw if str(k).strip()]
|
||||
break
|
||||
except (json.JSONDecodeError, TypeError, AttributeError):
|
||||
continue
|
||||
@@ -190,6 +208,7 @@ def _parse_generic(soup: BeautifulSoup, url: str) -> dict:
|
||||
"image_url": image_url,
|
||||
"ingredients": ingredients,
|
||||
"instructions": instructions,
|
||||
"tags": tags,
|
||||
"original_url": url,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user