Wolt
URL шаблон: https://wolt.com/{lang}/{country}/{city}/restaurant/{slug}
Источник данных: Playwright (DOM) + Wolt consumer-api (HTTP JSON)
Стратегия парсинга
- Открываем страницу в Playwright (Chromium с прокси), нормализуем URL к английской локали (`/en/`).
- Ждём появления селектора `[data-test-id="MenuSection"]`.
- Гоняем JS-extractor через `page.evaluate(...)` — собираем DOM-поля: имя, телефон, адрес, теги, часы, меню.
- Параллельно дёргаем `https://consumer-api.wolt.com/order-xp/web/v1/venue/slug/{slug}/dynamic/` — это даёт более полные данные о статусе/доставке/часах.
- Объединяем DOM + API. API имеет приоритет для часов, рейтинга, мин. заказа и расписания.
Поля ресторана
| поле | откуда / как | пример |
|---|---|---|
name | h1 на странице → DOM | 'Café Milano | Ristorante & Pizzeria' |
slug | из URL | 'caf-milano-ristorante-pizzeria' |
url | нормализованный URL (en-локаль) | 'https://wolt.com/en/...' |
rating | API: venue.header.delivery_method_statuses[].metadata | 4.5 |
is_open | API: venue.open_status.is_open | true |
open_status | API: venue.open_status.value | 'OPEN_NOW' |
next_open / next_close | API: venue.open_status | '2026-05-04T11:00:00Z' |
min_order_eur | API: order_minimum / metadata | 10.0 |
delivery_estimate_min/max/label | API: venue.delivery_configs[homedelivery].estimate | 20-30 min |
phone | DOM: a[href^="tel:"] | '+49241...' |
address | DOM: блок Address (h3 + p) → массив строк | ['Jülicher Str. 69','52070 Aachen'] |
coordinates | парсинг maps_url (q=lat,lng) | {lat:50.78, lng:6.10} |
maps_url | DOM: a[href*="maps.google"] | 'https://maps.google.com/?q=...' |
delivery_hours | API delivery_specs (если есть) или DOM table | {monday:'11:00-23:00',...} |
tags | DOM: блок "See similar venues" → ссылки | ['Burger','Snacks & drinks'] |
description | DOM footer p (>20 символов) | null или текст |
deals | API venue_raw.discounts[].description.title | ['10% off'] |
Поля меню (для каждого блюда)
| поле | откуда / как | пример |
|---|---|---|
category | DOM: [data-test-id="MenuSectionTitle"] h2 | 'SALATE 🥗' |
note | DOM: <p> сразу после заголовка категории | null |
name | item-card-header span | '242. New York Steak Salad' |
description | item-card-header → следующий <p> | null или текст |
price | item-card-price → текст | '€11.90' |
old_price | item-card-price → <del> | null или '€14.90' |
unit_price | из item-card-price (€/л) | '€2.50/l' или null |
discount_label | item-card-discount-badge | '-10%' или null |
popular | item-card-popularity-badge или текст "Popular" | true/false |
age_restricted | наличие "18+" в карточке | true/false |
deposit | регекс "Excl. ... (XXX)" | null или строка залога |
image_url | item-card-image img.src | 'https://...wolt.com/...jpg' |
Пример запроса
{
"platform": "wolt",
"url": "https://wolt.com/lang/country/city/restaurant/slug"
}
Опции options.scraperapi описаны в общей документации.
Нюансы
- Прокси обязателен — без прокси Wolt API часто отвечает 451 / редиректит.
- Если API не отвечает (ошибка) — данные из DOM используются как есть, рейтинг и часы могут быть пустыми.
- Картинки блюд лежат на CDN Wolt и доступны напрямую (можно <img src=...>).