Les plateformes de commerce électronique protègent les pages de produits et les données d'inventaire avec des CAPTCHA pour empêcher le scraping des concurrents et l'achat de robots. CaptchaAI permet une surveillance automatisée des stocks, un suivi des prix et des alertes de disponibilité.
CAPTCHA sur les plateformes de commerce électronique
| Plateforme | Type de CAPTCHA | Déclencheur | Données |
|---|---|---|---|
| Amazone | reCAPTCHA v2 | Accès à gros volumes | Prix, stock, avis |
| Walmart | reCAPTCHA v3 + Cloudflare | Détection de robots | Inventaire, prix |
| Meilleur achat | reCAPTCHA v2 | Vérification de l'ajout au panier | Stock, prix |
| Cible | Cloudflare Turnstile | Accès automatisé | Disponibilité |
| Boutiques Shopify | Cloudflare Turnstile | Limitation du débit | Données produit |
| eBay | reCAPTCHA v2 | Recherche + accès aux listings | Annonces, prix |
Moniteur de produit
import requests
import time
import re
import json
from datetime import datetime
from bs4 import BeautifulSoup
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 RetailMonitor:
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 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
})
def check_product(self, url):
"""Check single product's price and availability."""
resp = self.session.get(url, timeout=30)
# Handle CAPTCHA
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, url)
soup = BeautifulSoup(resp.text, "html.parser")
return {
"url": url,
"title": self._text(soup, "h1, .product-title, #productTitle"),
"price": self._text(soup, ".price, .a-price .a-offscreen, .prod-price"),
"availability": self._text(soup, "#availability, .stock-status, .fulfillment"),
"in_stock": self._check_stock(soup),
"timestamp": datetime.now().isoformat(),
}
def monitor_products(self, product_urls, interval_sec=1800):
"""Continuously monitor products for changes."""
history = {}
while True:
for url in product_urls:
try:
current = self.check_product(url)
# Check for changes
prev = history.get(url)
if prev:
changes = self._detect_changes(prev, current)
if changes:
self._alert(current["title"], changes)
history[url] = current
time.sleep(3)
except Exception as e:
print(f"Error checking {url}: {e}")
print(f"Cycle complete: {len(product_urls)} products checked")
time.sleep(interval_sec)
def track_prices(self, product_urls, output_file="prices.json"):
"""Single price check across all products."""
results = []
for url in product_urls:
try:
data = self.check_product(url)
results.append(data)
time.sleep(3)
except Exception as e:
results.append({"url": url, "error": str(e)})
with open(output_file, "w") as f:
json.dump(results, f, indent=2)
print(f"Tracked {len(results)} products → {output_file}")
return results
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile', 'captcha',
])
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})
else:
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
def _check_stock(self, soup):
stock_el = soup.select_one("#availability, .stock-status")
if stock_el:
text = stock_el.get_text(strip=True).lower()
return "in stock" in text or "available" in text
return None
def _detect_changes(self, prev, current):
changes = []
if prev["price"] != current["price"]:
changes.append(f"Price: {prev['price']} → {current['price']}")
if prev["in_stock"] != current["in_stock"]:
status = "In Stock" if current["in_stock"] else "Out of Stock"
changes.append(f"Stock: → {status}")
return changes
def _alert(self, title, changes):
print(f"ALERT [{title}]: {', '.join(changes)}")
# Usage
monitor = RetailMonitor(
proxy="http://user:pass@residential.proxy.com:5000"
)
products = [
"https://store.example.com/product/abc123",
"https://store.example.com/product/def456",
"https://store.example.com/product/ghi789",
]
# One-time price check
results = monitor.track_prices(products)
# Or continuous monitoring (every 30 min)
# monitor.monitor_products(products, interval_sec=1800)
Analyse des stocks à l'échelle de la catégorie
def scan_category(base_url, category, max_pages=20):
"""Scan an entire product category for stock status."""
monitor = RetailMonitor(
proxy="http://user:pass@residential.proxy.com:5000"
)
all_products = []
for page in range(1, max_pages + 1):
url = f"{base_url}/{category}?page={page}"
resp = monitor.session.get(url, timeout=30)
if monitor._has_captcha(resp.text):
resp = monitor._solve_and_retry(resp.text, url)
soup = BeautifulSoup(resp.text, "html.parser")
items = soup.select(".product-card, .s-result-item")
if not items:
break
for item in items:
all_products.append({
"name": monitor._text(item, ".product-name, .a-text-normal"),
"price": monitor._text(item, ".price, .a-price"),
"stock": monitor._text(item, ".stock, .a-color-success"),
"url": item.select_one("a")["href"] if item.select_one("a") else "",
})
time.sleep(3)
return all_products
Comparaison des prix des concurrents
def compare_product_across_stores(product_name, stores):
"""Compare prices across retailers for the same product."""
results = []
for store in stores:
monitor = RetailMonitor(proxy=store.get("proxy"))
search_url = f"{store['base_url']}/search?q={product_name}"
try:
resp = monitor.session.get(search_url, timeout=30)
if monitor._has_captcha(resp.text):
resp = monitor._solve_and_retry(resp.text, search_url)
soup = BeautifulSoup(resp.text, "html.parser")
first_result = soup.select_one(".product-card, .s-result-item")
if first_result:
results.append({
"store": store["name"],
"price": monitor._text(first_result, ".price"),
"in_stock": "in stock" in first_result.get_text().lower(),
})
except Exception as e:
results.append({"store": store["name"], "error": str(e)})
time.sleep(5)
results.sort(key=lambda x: x.get("price", "zzzz"))
return results
Calendrier de surveillance
| Type de produit | Vérifier la fréquence | Type de mandataire |
|---|---|---|
| Électronique | Toutes les 30 minutes | Résidentiel tournant |
| Épicerie | Toutes les 4 heures | Résidentiel tournant |
| Mode | Toutes les 2 heures | Résidentiel |
| Sorties limitées | Toutes les 1 minutes | Mandataire mobile |
| Articles pour la maison | Toutes les 6 heures | Résidentiel |
| Biens de base | Toutes les 12 heures | Datacenter (souvent suffisant) |
Dépannage
| Problème | Parce que | Corriger |
|---|---|---|
| CAPTCHA sur chaque page produit | IP signalée ou débit dépassé | Augmenter le délai, faire pivoter les proxys |
| Prix incorrect gratté | Tarification dynamique rendue par JS | Utilisez plutôt Selenium/Puppeteer |
| Page "Contrôle du robot" | Détection de robots à la manière d'Amazon | Utilisez des en-têtes réalistes + un proxy résidentiel |
| Le stock indique "indisponible" | Disponibilité géo-restreinte | Faire correspondre le proxy à la région cible |
| Données produit manquantes | La structure des pages a été modifiée | Mettre à jour les sélecteurs CSS |
FAQ
À quelle fréquence puis-je consulter les pages produits ?
Toutes les 30 à 60 minutes par produit sont sans danger pour la plupart des détaillants. La surveillance à plus haute fréquence (1 à 5 minutes) fonctionne mais nécessite davantage de proxys et déclenche des CAPTCHA.
Dois-je utiliser des sessions rotatives ou collantes ?
Rotation : chaque page de produit est une demande indépendante. Les sessions persistantes ne sont nécessaires que si la vérification des détails du produit nécessite une navigation.
Puis-je surveiller des milliers de produits ?
Oui. Répartissez les requêtes sur plusieurs adresses IP proxy et échelonnez les contrôles. Pour 1 000 produits avec des délais de 3 secondes, un cycle complet prend environ 50 minutes.
Guides connexes
- Rotation des procurations résidentielles
- Sessions collantes ou rotatives
- Surveillance de la chaîne d'approvisionnement
Suivez l'inventaire de vente au détail en temps réel -récupérez votre clé CaptchaAIpour la gestion automatisée des CAPTCHA.