68 lines
2.4 KiB
Markdown
68 lines
2.4 KiB
Markdown
# Batch Recipe Import
|
|
|
|
Import recipes in bulk via the Mealie API. The scraper extracts full recipe data (ingredients, steps, images, times) from any supported URL.
|
|
|
|
## Python Script
|
|
|
|
```python
|
|
import requests
|
|
import time
|
|
|
|
MEALIE = "http://127.0.0.1:9925"
|
|
EMAIL = "your@email.com"
|
|
PASSWORD = "your-password"
|
|
|
|
# Authenticate
|
|
resp = requests.post(
|
|
f"{MEALIE}/api/auth/token",
|
|
data={"username": EMAIL, "password": PASSWORD, "grant_type": ""},
|
|
headers={"Content-Type": "application/x-www-form-urlencoded"}
|
|
)
|
|
token = resp.json()["access_token"]
|
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
|
|
|
# Recipe URLs (one per line)
|
|
urls = [
|
|
"https://www.bbcgoodfood.com/recipes/classic-lasagne",
|
|
"https://www.budgetbytes.com/one-pot-creamy-cajun-chicken-pasta/",
|
|
"https://www.recipetineats.com/thai-green-curry/",
|
|
]
|
|
|
|
for url in urls:
|
|
resp = requests.post(
|
|
f"{MEALIE}/api/recipes/create/url",
|
|
json={"url": url},
|
|
headers=headers,
|
|
timeout=60
|
|
)
|
|
if resp.status_code in (200, 201):
|
|
print(f" OK: {url.split('/')[-2]}")
|
|
else:
|
|
print(f" FAIL: {url.split('/')[-2]} — {resp.status_code}")
|
|
time.sleep(1.5) # Be polite to recipe sites
|
|
```
|
|
|
|
## Bulk curl (no Python needed)
|
|
|
|
```bash
|
|
# Get token
|
|
TOKEN=$(curl -s -X POST "http://127.0.0.1:9925/api/auth/token" \
|
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
-d "grant_type=&username=you@email.com&password=yourpass" \
|
|
| grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
|
|
|
|
# Import a single recipe
|
|
curl -s -X POST "http://127.0.0.1:9925/api/recipes/create/url" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"url": "https://www.bbcgoodfood.com/recipes/classic-lasagne"}'
|
|
```
|
|
|
|
## Notes
|
|
|
|
- URLs must be full recipe pages, not search results or category pages.
|
|
- If a site returns HTTP 400 consistently, it likely blocks automated scrapers — see `scraper-sites.md` for alternatives.
|
|
- First import may be slow (Mealie's scraper downloads the page, parses schema.org JSON-LD, and extracts structured data).
|
|
- **Real-world success rate:** ~50-60% across mixed URLs. Expect roughly half to fail on the first pass. Rerun failures from a reliable source (BBC Good Food, RecipeTin Eats) to fill gaps.
|
|
- **From Hermes:** use `execute_code` with `import requests` — the sandboxed Python environment can call `http://127.0.0.1:9925` directly. No need for curl or external scripts.
|