Platform e-niaga melindungi halaman produk dan data inventaris dengan CAPTCHA untuk mencegah scraping pesaing dan pembelian bot. CaptchaAI memungkinkan pemantauan stok otomatis, pelacakan harga, dan peringatan ketersediaan.
CAPTCHA di Platform E-Commerce
| Peron | Jenis CAPTCHA | Pemicu | Data |
|---|---|---|---|
| Amazon | reCAPTCHA v2 | Akses volume tinggi | Harga, stok, ulasan |
| Walmart | reCAPTCHA v3 + Cloudflare | Deteksi bot | Persediaan, harga |
| Pembelian Terbaik | reCAPTCHA v2 | Cek tambahkan ke troli | Stok, harga |
| Sasaran | Cloudflare Turnstile | Akses otomatis | Ketersediaan |
| Toko Shopify | Cloudflare Turnstile | Pembatasan tarif | Data produk |
| eBay | reCAPTCHA v2 | Pencarian + akses daftar | Daftar, harga |
Pemantau Produk
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)
Pemindaian Stok Seluruh Kategori
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
Perbandingan Harga Pesaing
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
Jadwal Pemantauan
| Jenis Produk | Periksa Frecookiensi | Jenis Proxy |
|---|---|---|
| Elektronik | Setiap 30 menit | Perumahan berputar |
| Bahan makanan | Setiap 4 jam | Perumahan berputar |
| Mode | Setiap 2 jam | Perumahan |
| Rilis terbatas | Setiap 1 menit | Proxy seluler |
| Barang-barang rumah tangga | Setiap 6 jam | Perumahan |
| Barang komoditas | Setiap 12 jam | Pusat data (seringkali cukup) |
Pemecahan Masalah
| Masalah | Penyebab | Solusi |
|---|---|---|
| CAPTCHA di setiap halaman produk | IP ditandai atau tarif terlampaui | Tingkatkan penundaan, putar proxy |
| Harga yang salah tergores | Penetapan harga dinamis yang diberikan oleh JS | Gunakan Selenium/Puppeteer sebagai gantinya |
| Halaman "Pemeriksaan robot". | Deteksi bot ala Amazon | Gunakan header realistis + proxy perumahan |
| Stok menunjukkan "tidak tersedia" | Ketersediaan terbatas secara geografis | Cocokkan proxy dengan wilayah target |
| Data produk tidak ada | Struktur halaman berubah | Perbarui pemilih CSS |
Pertanyaan Umum
Seberapa sering saya dapat memeriksa halaman produk?
Setiap 30-60 menit per produk aman bagi sebagian besar pengecer. Pemantauan frecookiensi lebih tinggi (1-5 menit) berfungsi tetapi memerlukan lebih banyak proxy dan memicu CAPTCHA.
Haruskah saya menggunakan sesi bergilir atau sesi tempel?
Rotasi – setiap halaman produk merupakan permintaan independen. Sesi melekat hanya diperlukan jika pemeriksaan detail produk memerlukan navigasi.
Bisakah saya memantau ribuan produk?
Ya. Sebarkan permintaan ke beberapa IP proxy dan lakukan pemeriksaan secara bertahap. Pada 1.000 produk dengan penundaan 3 detik, satu siklus penuh memerlukan waktu ~50 menit.
Panduan Terkait
- Memutar Proxy Perumahan
- Sesi Lengket vs Berputar
- Pemantauan Rantai Pasokan
Lacak inventaris ritel secara real time –dapatkan kunci CaptchaAI Andauntuk penanganan CAPTCHA otomatis.