As plataformas de entrega de alimentos protegem seus dados de preços com CAPTCHAs e detecção de bots. Serviços de comparação de preços, pesquisadores de mercado e ferramentas de análise de restaurantes precisam de acesso automatizado para comparar preços de menus, taxas de entrega e promoções em DoorDash, Uber Eats, Grubhub e outras plataformas.
CAPTCHAs em plataformas de entrega
| Plataforma | Tipo CAPTCHA | Gatilho | Dados protegidos |
|---|---|---|---|
| Porta Dash | reCAPTCHA v3 + Cloudflare | Detecção de bots | Menus, preços, taxas |
| Uber come | Cloudflare Turnstile | Acesso automatizado | Listagens de restaurantes, preços |
| Grubhub | reCAPTCHA v2 | Limitação de taxa | Itens do menu, promoções |
| Postmates | Cloudflare Turnstile em staging | Detecção de raspagem | Taxas de entrega, ETAs |
| Apenas coma | reCAPTCHA v2 | Pesquisas repetidas | Dados do restaurante |
| Instacart | reCAPTCHA v3 | Detecção de bots | Preços de mercearia |
Comparador de preços multiplataforma
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')}")
Recomendações de proxy
| Plataforma | mais adequado proxy | Por que |
|---|---|---|
| Porta Dash | Móvel (4G) | Detecção pesada de bots, espera dispositivos móveis |
| Uber come | Móvel (4G) | Plataforma mobile-first |
| Grubhub | Residencial | Proteção padrão |
| Instacart | Residencial | Detecção moderada de bots |
| Apenas coma | Residencial rotativo | Cloudflare padrão |
Os aplicativos de entrega priorizam os dispositivos móveis – os proxies móveis com User-Agents móveis produzem os mais adequado resultados.
Pontos de dados para rastrear
| Métrica | Valor comercial |
|---|---|
| Preços dos itens do cardápio | Paridade de preços e análise de markup |
| Taxas de entrega | Comparação de taxas de plataforma |
| Quantidades mínimas de pedido | Análise de barreira de acesso |
| Estimativas de tempo de entrega | Comparação de nível de serviço |
| Promoções/discounts | Inteligência de marketing |
| Disponibilidade do restaurante | Análise de cobertura |
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| Resultados de restaurantes vazios | Local não veiculado ou página CAPTCHA | Defina o CEP do endereço de entrega correto |
| Preços do cardápio diferentes do app | Discrepância de preços entre Web e aplicativos | Use o UA móvel para obter preços equivalentes ao aplicativo |
| Ciclo de desafio Cloudflare | Incompatibilidade de sinal de navegador | Use rede mobile autorizada + UA móvel |
| Restaurante encontrado em uma plataforma, mas não em outra | Cobertura diferente | Marcar como "não disponível" em comparação |
| Taxas de entrega incorretas | Preços dependentes da localização | Combine a localização geográfica do proxy com o local de destino |
Perguntas frequentes
Por que os preços são diferentes nas plataformas de entrega?
Os restaurantes definem preços diferentes por plataforma para compensar as taxas de comissão variadas (15-30%). As taxas de entrega e taxas de serviço também variam de acordo com a plataforma.
Devo usar dispositivos móveis ou desktop para coletar aplicativos de entrega?
Mobile - essas são plataformas mobile-first. Um rede mobile autorizada com iPhone/Android User-Agent produz o tráfego com aparência mais autêntica.
Com que frequência devo comparar preços?
Semanalmente para análise geral do mercado. Diariamente durante períodos promocionais ou sprints de pesquisa competitivos.
Guias Relacionados
- Monitoramento de estoque de varejo
- Proxies móveis para CAPTCHA
- Proxies residenciais rotativos
Compare os preços de entrega de alimentos em grande escala -obtenha sua chave CaptchaAIe automatizar a análise entre plataformas.