Các nền tảng thương mại điện tử bảo vệ các trang sản phẩm và dữ liệu hàng tồn kho bằng CAPTCHA để ngăn chặn việc mua hàng bằng bot và đối thủ cạnh tranh. CaptchaAI cho phép giám sát kho hàng tự động, theo dõi giá cả và cảnh báo tình trạng còn hàng.
CAPTCHA trên nền tảng thương mại điện tử
| Nền tảng | Loại CAPTCHA | Trình kích hoạt | dữ liệu |
|---|---|---|---|
| Amazon | reCAPTCHA v2 | Truy cập khối lượng lớn | Giá, hàng tồn kho, đánh giá |
| Walmart | reCAPTCHA v3 + Cloudflare | Phát hiện bot | Hàng tồn kho, giá cả |
| Mua tốt nhất | reCAPTCHA v2 | Kiểm tra thêm vào giỏ hàng | Kho hàng, giá cả |
| Mục tiêu | Cloudflare Turnstile | Truy cập tự động | sẵn có |
| Cửa hàng Shopify | Cloudflare Turnstile | Giới hạn tỷ lệ | Dữ liệu sản phẩm |
| eBay | reCAPTCHA v2 | Truy cập tìm kiếm + danh sách | Danh sách, giá cả |
Giám sát sản phẩm
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)
Quét kho toàn danh mục
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
So sánh giá của đối thủ cạnh tranh
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
Lịch giám sát
| Loại sản phẩm | Kiểm tra tần suất | Loại proxy |
|---|---|---|
| Điện tử | Cứ sau 30 phút | Khu dân cư xoay vòng |
| Cửa hàng tạp hóa | Cứ sau 4 giờ | Khu dân cư xoay vòng |
| thời trang | Cứ sau 2 giờ | Khu dân cư |
| Phiên bản giới hạn | Cứ sau 1 phút | đa dạng nguồn yêu cầu |
| Hàng gia dụng | Cứ sau 6 giờ | Khu dân cư |
| Hàng hóa | Cứ sau 12 giờ | Trung tâm dữ liệu (thường là đủ) |
Khắc phục sự cố
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| CAPTCHA trên mỗi trang sản phẩm | IP bị gắn cờ hoặc vượt quá tốc độ | Tăng độ trễ, xoay proxy |
| Giá bị loại bỏ không chính xác | Định giá động được hiển thị bởi JS | Thay vào đó hãy sử dụng Selenium/Puppeteer |
| Trang "kiểm tra robot" | Phát hiện bot kiểu Amazon | Sử dụng tiêu đề thực tế + đa dạng nguồn yêu cầu |
| Chứng khoán hiển thị "không có sẵn" | Tính sẵn có bị giới hạn về mặt địa lý | So khớp proxy với khu vực mục tiêu |
| Thiếu dữ liệu sản phẩm | Cấu trúc trang đã thay đổi | Cập nhật bộ chọn CSS |
Câu hỏi thường gặp
Tôi có thể kiểm tra trang sản phẩm với tần suất như thế nào?
Cứ sau 30-60 phút cho mỗi sản phẩm là an toàn đối với hầu hết các nhà bán lẻ. Giám sát tần số cao hơn (1-5 phút) hoạt động nhưng yêu cầu nhiều proxy hơn và kích hoạt CAPTCHA.
Tôi nên sử dụng phiên xoay hay phiên cố định?
Xoay vòng - mỗi trang sản phẩm là một yêu cầu độc lập. Phiên cố định chỉ cần thiết nếu việc kiểm tra chi tiết sản phẩm yêu cầu điều hướng.
Tôi có thể theo dõi hàng ngàn sản phẩm không?
Vâng. Trải rộng các yêu cầu trên nhiều IP proxy và kiểm tra xen kẽ. Với 1.000 sản phẩm có độ trễ 3 giây, một chu kỳ đầy đủ sẽ mất khoảng 50 phút.
Hướng dẫn liên quan
- Ủy quyền dân cư luân phiên
- Phiên cố định và phiên luân phiên
- Giám sát chuỗi cung ứng
Theo dõi hàng tồn kho bán lẻ trong thời gian thực —lấy khóa CaptchaAI của bạnđể xử lý CAPTCHA tự động.