DoorDash
URL шаблон: https://www.doordash.com/store/{slug}/{store_id}/
Источник данных: ScraperAPI render=true → HTML с RSC payload (Next.js App Router)
Стратегия парсинга
- GET через ScraperAPI с `render=true` — нужен JS-рендер для Next.js.
- Из HTML вытягиваем все вызовы `self.__next_f.push([1, "..."])` — RSC chunks.
- В одном из чанков (декодируем unicode-escape) ищем маркер `{"__typename":"StorePageFeedResult"`.
- От маркера парсим JSON по балансировке скобок до закрывающей `}`.
- Из объекта `feed` извлекаем `storeHeader`, `menuBook`, `mxInfo`, `reviewPreview`, `itemLists`.
Поля ресторана
| поле | откуда / как | пример |
|---|---|---|
store_id | feed.storeHeader.id | 946296 |
menu_id | feed.menuBook.id | 23475357 |
name | feed.storeHeader.name | 'Boston Pizza' |
description | feed.storeHeader.description | 'Italian-American chain...' |
price_range | feed.storeHeader.priceRangeDisplayString | '$$' |
rating | feed.reviewPreview.consumerReviewData.avgRating | 4.2 |
num_ratings | feed.reviewPreview.consumerReviewData.numRatings | 1234 |
num_ratings_str | feed.reviewPreview...numRatingsDisplayString | '1.2K+' |
is_open | feed.mxInfo.operationInfo.operationStatusInfo.operationStatus == OPEN | true |
open_status | feed.mxInfo.operationInfo.operationStatusInfo.description | 'Closes at 11 PM' |
is_dashpass | feed.storeHeader.isDashpassPartner | true |
offers_delivery | feed.storeHeader.offersDelivery | true |
offers_pickup | feed.storeHeader.offersPickup | true |
offers_catering | feed.storeHeader.offersCatering | false |
hours_today | feed.menuBook.displayOpenHours | '11:00 AM – 11:00 PM' |
hours_week | feed.mxInfo.operationInfo.storeOperationHourInfo.hours | {monday:'11:00–23:00',...} |
address / street / city / state / country | feed.mxInfo.address.* | '1234 Main St, Toronto, ON, CA' |
coordinates | feed.mxInfo.address.{lat,lng} | {lat:..., lng:...} |
phone | feed.mxInfo.phoneno | '+1416...' |
website | feed.mxInfo.website | 'https://bostonpizza.com' |
Поля меню (для каждого блюда)
| поле | откуда / как | пример |
|---|---|---|
category | itemList.name | 'Pizza' |
description | itemList.description | null или текст категории |
name | item.name | 'Pepperoni Pizza' |
description | item.description | 'Italian style pepperoni...' |
price | item.displayPrice | '$15.99' |
old_price | item.displayStrikethroughPrice | null или цена |
image_url | item.imageUrl | 'https://doordash.com/cdn/...jpg' |
Пример запроса
{
"platform": "doordash",
"url": "https://www.doordash.com/store/slug/store_id/"
}
Опции options.scraperapi описаны в общей документации.
Нюансы
- DoorDash защищён Cloudflare — без `render=true` в ScraperAPI не пройдёт.
- Маркер `StorePageFeedResult` может быть НЕ в самом большом RSC-chunk-е — мы перебираем все.
- Если ScraperAPI вернёт 5xx — встроенный retry повторит до 3 раз с exp backoff.
- Меню без флагов popular/dietary в текущем feed — добавим если найдём в feed-объекте.