Platform pesan-antar makanan melindungi data harga mereka dengan CAPTCHA dan deteksi bot. Layanan perbandingan harga, peneliti pasar, dan alat analisis restoran memerlukan akses otomatis untuk membandingkan harga menu, biaya pengiriman, dan promosi di DoorDash, Uber Eats, Grubhub, dan platform lainnya.
CAPTCHA di Platform Food Delivery
| Platform | Tipe CAPTCHA | Pemicu | Data yang Dilindungi |
|---|---|---|---|
| DoorDash | reCAPTCHA v3 + Cloudflare | Deteksi bot | Menu, harga, biaya |
| Uber Eats | Cloudflare Turnstile | Akses otomatis | Daftar restoran, harga |
| Grubhub | reCAPTCHA v2 | Rate limiting | Item menu, promosi |
| Postmates | Cloudflare Challenge | Deteksi scraping | Biaya pengiriman, ETA |
| Just Eat | reCAPTCHA v2 | Pencarian berulang | Data restoran |
| Instacart | reCAPTCHA v3 | Deteksi bot | Harga bahan makanan |
Pembanding Harga Multi-Platform
import requests
import time
import re
from bs4 import BeautifulSoup
import json
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY, "method": method,
"googlekey": sitekey, "pageurl": pageurl, "json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Timeout")
class FoodDeliveryComparator:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 "
"Mobile/15E148 Safari/604.1",
"Accept-Language": "en-US,en;q=0.9",
})
def search_restaurants(self, platform_url, location, cuisine=None):
"""Search restaurants on a delivery platform."""
params = {"address": location}
if cuisine:
params["cuisine"] = cuisine
url = f"{platform_url}/search"
resp = self.session.get(url, params=params, timeout=30)
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, url)
return self._parse_restaurants(resp.text)
def get_menu(self, restaurant_url):
"""Get menu with prices from a specific restaurant."""
resp = self.session.get(restaurant_url, timeout=30)
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, restaurant_url)
return self._parse_menu(resp.text)
def compare_restaurant_across_platforms(self, restaurant_name, platforms, location):
"""Compare same restaurant's pricing across delivery platforms."""
results = []
for platform in platforms:
try:
restaurants = self.search_restaurants(
platform["url"], location,
)
# Find matching restaurant
match = None
for r in restaurants:
if restaurant_name.lower() in r["name"].lower():
match = r
break
if match and match.get("url"):
menu = self.get_menu(match["url"])
results.append({
"platform": platform["name"],
"restaurant": match["name"],
"delivery_fee": match.get("delivery_fee", ""),
"delivery_time": match.get("delivery_time", ""),
"menu_items": len(menu),
"sample_prices": menu[:5],
})
else:
results.append({
"platform": platform["name"],
"restaurant": restaurant_name,
"status": "not found",
})
except Exception as e:
results.append({
"platform": platform["name"],
"error": str(e),
})
time.sleep(5)
return results
def track_delivery_fees(self, platforms, location, output_file):
"""Track delivery fees across platforms for analysis."""
all_data = []
for platform in platforms:
try:
restaurants = self.search_restaurants(
platform["url"], location,
)
for r in restaurants[:20]: # Top 20 per platform
all_data.append({
"platform": platform["name"],
"restaurant": r["name"],
"delivery_fee": r.get("delivery_fee", ""),
"delivery_time": r.get("delivery_time", ""),
"rating": r.get("rating", ""),
})
time.sleep(5)
except Exception as e:
print(f"Error on {platform['name']}: {e}")
with open(output_file, "w") as f:
json.dump(all_data, f, indent=2)
return all_data
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile',
'challenge-platform',
])
def _solve_and_retry(self, html, url):
match = re.search(r'data-sitekey="([^"]+)"', html)
if not match:
return self.session.get(url)
sitekey = match.group(1)
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
return self.session.post(url, data={"cf-turnstile-response": token})
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _parse_restaurants(self, html):
soup = BeautifulSoup(html, "html.parser")
restaurants = []
for card in soup.select(".restaurant-card, .store-card, .merchant"):
name_el = card.select_one(".name, .store-name, h3")
if name_el:
restaurants.append({
"name": name_el.get_text(strip=True),
"url": self._link(card),
"delivery_fee": self._text(card, ".delivery-fee, .fee"),
"delivery_time": self._text(card, ".delivery-time, .eta"),
"rating": self._text(card, ".rating, .stars"),
})
return restaurants
def _parse_menu(self, html):
soup = BeautifulSoup(html, "html.parser")
items = []
for item in soup.select(".menu-item, .item-card"):
items.append({
"name": self._text(item, ".item-name, .name"),
"price": self._text(item, ".price, .item-price"),
"description": self._text(item, ".description, .item-desc"),
})
return items
def _text(self, el, selector):
found = el.select_one(selector)
return found.get_text(strip=True) if found else ""
def _link(self, card):
a = card.select_one("a")
return a.get("href", "") if a else ""
# Usage
comparator = FoodDeliveryComparator(
proxy="http://user:pass@mobile.proxy.com:5000"
)
# Compare platforms
platforms = [
{"name": "Platform A", "url": "https://delivery-a.example.com"},
{"name": "Platform B", "url": "https://delivery-b.example.com"},
{"name": "Platform C", "url": "https://delivery-c.example.com"},
]
comparison = comparator.compare_restaurant_across_platforms(
restaurant_name="Pizza Palace",
platforms=platforms,
location="10001",
)
for result in comparison:
print(f"{result.get('platform')}: Fee={result.get('delivery_fee')} "
f"ETA={result.get('delivery_time')}")
Rekomendasi Proxy
| Platform | Proxy Terbaik | Alasan |
|---|---|---|
| DoorDash | Mobile (4G) | Deteksi bot berat, mengharapkan traffic mobile |
| Uber Eats | Mobile (4G) | Platform mobile-first |
| Grubhub | Residensial | Proteksi standar |
| Instacart | Residensial | Deteksi bot sedang |
| Just Eat | Rotating residensial | Cloudflare standar |
Aplikasi delivery mobile-first — egress jaringan mobile yang diotorisasi dengan User-Agent iPhone/Android memberikan hasil terbaik.
Poin Data untuk Dilacak
| Metrik | Nilai Bisnis |
|---|---|
| Harga item menu | Paritas harga dan analisis markup |
| Biaya pengiriman | Perbandingan biaya platform |
| Jumlah pesanan minimum | Analisis hambatan akses |
| Perkiraan waktu pengiriman | Perbandingan tingkat layanan |
| Promosi/discounts | Intelijen pemasaran |
| Ketersediaan restoran | Analisis cakupan |
Pemecahan Masalah
| Masalah | Penyebab | Perbaikan |
|---|---|---|
| Hasil restoran kosong | Lokasi tidak valid atau halaman CAPTCHA | Set zip/alamat pengiriman yang benar |
| Harga menu berbeda dari app | Perbedaan harga web vs app | Gunakan mobile UA untuk harga setara app |
| Cloudflare challenge loop | sinyal browser mismatch | Gunakan egress jaringan mobile yang diotorisasi + mobile UA |
| Restoran ada di satu platform tapi tidak di lain | Coverage berbeda | Tandai sebagai "tidak tersedia" untuk perbandingan |
| Biaya pengiriman salah | Pricing berbasis lokasi | Samakan geo proxy dengan lokasi target |
Pertanyaan Umum
Mengapa harga berbeda di setiap platform delivery?
Restoran menetapkan harga berbeda per platform untuk memperhitungkan komisi yang bervariasi (15–30%). Biaya pengiriman dan biaya layanan juga bervariasi per platform.
Haruskah saya menggunakan mobile atau desktop untuk scraping app delivery?
Mobile — ini adalah platform mobile-first. egress jaringan mobile yang diotorisasi dengan User-Agent iPhone/Android menghasilkan traffic yang paling terlihat autentik.
Seberapa sering saya harus membandingkan harga?
Mingguan untuk analisis pasar umum. Harian selama periode promosi atau sprint riset kompetitif.
Panduan Terkait
- Monitoring Inventaris Retail dengan Penanganan CAPTCHA
- egress jaringan mobile yang diotorisasi untuk CAPTCHA
- Rotating egress jaringan yang diotorisasi untuk Solve CAPTCHA
Bandingkan harga food delivery dalam skala besar — dapatkan API key CaptchaAI Anda dan otomatiskan analisis lintas platform.