DEV Community

agenthustler
agenthustler

Posted on

Scraping Food Delivery Apps: Menu Prices, Availability, ETAs

Food delivery is a $300B global market. Scraping menu data, prices, and delivery times enables price comparison tools, market research, and restaurant analytics. Here's how to build it.

Architecture

Food delivery platforms heavily rely on APIs for their mobile and web apps. By intercepting and replicating these API calls, we get structured JSON data instead of messy HTML.

Menu and Price Scraper

pip install requests pandas beautifulsoup4
Enter fullscreen mode Exit fullscreen mode
import requests
import pandas as pd
from datetime import datetime
import time
import json
from bs4 import BeautifulSoup

class FoodDeliveryScraper:
    def __init__(self, api_key):
        self.api_key = api_key
        self.session = requests.Session()

    def _proxy_request(self, url):
        proxy_url = f"http://api.scraperapi.com?api_key={self.api_key}&url={url}"
        return self.session.get(proxy_url, timeout=30)

    def scrape_restaurant_menu(self, platform_url):
        resp = self._proxy_request(platform_url)
        soup = BeautifulSoup(resp.text, "html.parser")
        menu_items = []

        # Try structured data first
        for script in soup.find_all("script", type="application/ld+json"):
            try:
                data = json.loads(script.string)
                if data.get("@type") == "Restaurant":
                    for section in data.get("hasMenu", {}).get("hasMenuSection", []):
                        for item in section.get("hasMenuItem", []):
                            menu_items.append({
                                "name": item.get("name"),
                                "price": item.get("offers", {}).get("price"),
                                "section": section.get("name", ""),
                            })
            except json.JSONDecodeError:
                continue

        # Fallback: HTML parsing
        if not menu_items:
            for item in soup.select(".menu-item, [data-testid='menu-item']"):
                name = item.select_one(".item-name, h3, h4")
                price = item.select_one(".price, .item-price")
                if name:
                    menu_items.append({
                        "name": name.text.strip(),
                        "price": price.text.strip() if price else "N/A",
                    })
        return menu_items

    def compare_prices(self, restaurant_name, platform_urls):
        comparison = []
        for platform, url in platform_urls.items():
            items = self.scrape_restaurant_menu(url)
            for item in items:
                item["platform"] = platform
                item["restaurant"] = restaurant_name
            comparison.extend(items)
            time.sleep(3)
        return pd.DataFrame(comparison)

# Usage
scraper = FoodDeliveryScraper("YOUR_SCRAPERAPI_KEY")
platforms = {
    "ubereats": "https://www.ubereats.com/store/example-restaurant/abc123",
    "doordash": "https://www.doordash.com/store/example-restaurant-456"
}
comparison = scraper.compare_prices("Pizza Palace", platforms)
print(comparison[["name", "price", "platform"]].to_string(index=False))
Enter fullscreen mode Exit fullscreen mode

Price Tracking Over Time

import schedule

def track_prices():
    scraper = FoodDeliveryScraper("YOUR_KEY")
    restaurants = json.load(open("watchlist.json"))
    for restaurant in restaurants:
        df = scraper.compare_prices(restaurant["name"], restaurant["urls"])
        df["date"] = datetime.now().strftime("%Y-%m-%d")
        try:
            history = pd.read_csv("price_history.csv")
            history = pd.concat([history, df])
        except FileNotFoundError:
            history = df
        history.to_csv("price_history.csv", index=False)

schedule.every(6).hours.do(track_prices)
Enter fullscreen mode Exit fullscreen mode

Scaling Considerations

Food delivery scraping requires handling JavaScript-heavy SPAs. ScraperAPI renders pages and solves CAPTCHAs automatically. Use ThorData residential proxies for location-specific pricing data. Track scraper reliability with ScrapeOps.

Conclusion

Food delivery data scraping enables powerful comparison and analytics tools. Focus on structured data extraction from JSON-LD and API responses before falling back to HTML parsing. The combination of price tracking and ETA monitoring creates actionable market intelligence.

Top comments (0)