Trường Hợp Sử Dụng

Giám sát chuỗi cung ứng với xử lý CAPTCHA

Khả năng hiển thị chuỗi cung ứng yêu cầu dữ liệu từ hàng trăm cổng thông tin nhà cung cấp, nền tảng hậu cần và hệ thống kiểm kê. Nhiều người trong số này bảo vệ dữ liệu của họ bằng CAPTCHA. CaptchaAI xử lý những thách thức này để các đường ống giám sát hoạt động không bị gián đoạn.


Trường hợp CAPTCHA chặn dữ liệu chuỗi cung ứng

Loại nguồn Loại CAPTCHA dữ liệu Tần số
Cổng thông tin nhà cung cấp reCAPTCHA v2 Hàng tồn kho, giá cả, thời gian giao hàng hàng ngày
hãng vận chuyển Cloudflare Turnstile Theo dõi, giá cả, ETA giao hàng Hàng giờ
Danh mục nhà sản xuất CAPTCHA hình ảnh Thông số sản phẩm, MOQ hàng tuần
Cổng thông tin hải quan reCAPTCHA v2 Thuế suất, mã số thuế hàng ngày
Chính quyền cảng CAPTCHA hình ảnh Lịch tàu, ùn tắc cảng Cứ sau 6 giờ
Trao đổi hàng hóa reCAPTCHA v3 Giá giao ngay, giá kỳ hạn thời gian thực

Màn hình đa nhà cung cấp

import requests
import time
import re
import json
import base64
from datetime import datetime

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"

def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "userrecaptcha",
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    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,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")

def solve_turnstile(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "turnstile",
        "sitekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    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,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")

def solve_image(image_bytes):
    img_b64 = base64.b64encode(image_bytes).decode()
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "base64",
        "body": img_b64, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(20):
        time.sleep(3)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")

class SupplyChainMonitor:
    def __init__(self, suppliers, proxy=None):
        self.suppliers = suppliers
        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",
        })

    def check_all(self):
        """Check inventory and pricing across all suppliers."""
        report = {
            "timestamp": datetime.now().isoformat(),
            "suppliers": {},
        }

        for supplier in self.suppliers:
            try:
                data = self._check_supplier(supplier)
                report["suppliers"][supplier["name"]] = {
                    "status": "success",
                    "data": data,
                }
            except Exception as e:
                report["suppliers"][supplier["name"]] = {
                    "status": "error",
                    "error": str(e),
                }
            time.sleep(3)

        return report

    def _check_supplier(self, supplier):
        url = supplier["url"]
        resp = self.session.get(url, timeout=30)

        # Handle CAPTCHA based on type
        captcha_type = supplier.get("captcha_type")
        if captcha_type and self._has_captcha(resp.text):
            resp = self._solve_captcha(resp, url, supplier)

        from bs4 import BeautifulSoup
        soup = BeautifulSoup(resp.text, "html.parser")

        return {
            "products": self._extract_inventory(soup),
            "last_updated": self._extract_date(soup),
        }

    def _has_captcha(self, html):
        return any(tag in html.lower() for tag in [
            'data-sitekey', 'g-recaptcha', 'cf-turnstile', 'captcha',
        ])

    def _solve_captcha(self, resp, url, supplier):
        captcha_type = supplier.get("captcha_type", "recaptcha")
        sitekey = supplier.get("sitekey", "")

        if not sitekey:
            match = re.search(r'data-sitekey="([^"]+)"', resp.text)
            sitekey = match.group(1) if match else ""

        if captcha_type == "turnstile":
            token = solve_turnstile(sitekey, url)
            return self.session.post(url, data={"cf-turnstile-response": token})
        elif captcha_type == "image":
            match = re.search(r'src="(/captcha[^"]+)"', resp.text)
            if match:
                img_resp = self.session.get(url.rstrip("/") + match.group(1))
                answer = solve_image(img_resp.content)
                return self.session.post(url, data={"captcha": answer})
        else:
            token = solve_recaptcha(sitekey, url)
            return self.session.post(url, data={"g-recaptcha-response": token})

        return resp

    def _extract_inventory(self, soup):
        items = []
        for row in soup.select("table.inventory tr, .product-row"):
            cols = row.select("td, .col")
            if len(cols) >= 3:
                items.append({
                    "sku": cols[0].get_text(strip=True),
                    "stock": cols[1].get_text(strip=True),
                    "price": cols[2].get_text(strip=True),
                })
        return items

    def _extract_date(self, soup):
        date_el = soup.select_one(".last-updated, .update-time")
        return date_el.get_text(strip=True) if date_el else ""

# Configure suppliers
suppliers = [
    {
        "name": "Supplier A",
        "url": "https://supplier-a.example.com/inventory",
        "captcha_type": "recaptcha",
        "sitekey": "6Lc_xxxxxxx",
    },
    {
        "name": "Carrier B",
        "url": "https://carrier-b.example.com/rates",
        "captcha_type": "turnstile",
        "sitekey": "0x4AAAAAAA_xxx",
    },
    {
        "name": "Manufacturer C",
        "url": "https://manufacturer-c.example.com/catalog",
        "captcha_type": "image",
    },
]

monitor = SupplyChainMonitor(
    suppliers=suppliers,
    proxy="http://user:pass@residential.proxy.com:5000",
)
report = monitor.check_all()
print(json.dumps(report, indent=2))

Giám sát giá vận chuyển

class ShippingRateTracker:
    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",
        })

    def get_rates(self, carrier_url, origin, destination, weight):
        """Fetch shipping rates, handling Turnstile CAPTCHA."""
        resp = self.session.get(carrier_url, timeout=30)

        sitekey_match = re.search(r'data-sitekey="([^"]+)"', resp.text)
        if sitekey_match:
            token = solve_turnstile(sitekey_match.group(1), carrier_url)
            resp = self.session.post(carrier_url, data={
                "origin": origin,
                "destination": destination,
                "weight": weight,
                "cf-turnstile-response": token,
            })

        if resp.status_code == 200:
            return resp.json().get("rates", [])
        return []

Cảnh báo về thay đổi hàng tồn kho

def monitor_with_alerts(monitor, alert_thresholds, check_interval=3600):
    """Continuously monitor and alert on inventory changes."""
    previous_data = {}

    while True:
        report = monitor.check_all()

        for supplier, info in report["suppliers"].items():
            if info["status"] != "success":
                continue

            for product in info["data"].get("products", []):
                sku = product["sku"]
                stock = product.get("stock", "")

                # Parse stock level
                try:
                    stock_qty = int(re.sub(r'\D', '', stock))
                except ValueError:
                    continue

                key = f"{supplier}:{sku}"
                prev_qty = previous_data.get(key, stock_qty)

                threshold = alert_thresholds.get(sku, 10)
                if stock_qty < threshold and prev_qty >= threshold:
                    print(f"ALERT: {supplier} - {sku} dropped to {stock_qty}")

                previous_data[key] = stock_qty

        time.sleep(check_interval)

Chính sách dự phòng của nhà cung cấp

  • Tách các nhà cung cấp quan trọng khỏi các nguồn tùy chọn để một lỗi không làm mất đi toàn bộ báo cáo giám sát.
  • Xác định khi nào dữ liệu cũ được chấp nhận và khi nào nhà cung cấp bị thiếu phải gây ra sự cố rõ ràng.
  • Tăng áp lực CAPTCHA dai dẳng lên nhà cung cấp như một rủi ro tìm nguồn cung ứng chứ không chỉ là lỗi kỹ thuật.

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Bố cục trang nhà cung cấp đã thay đổi Thiết kế lại trang web Cập nhật bộ chọn CSS
CAPTCHA trên mỗi lần kiểm tra Kiểm tra quá thường xuyên Tăng khoảng thời gian giữa các lần kiểm tra
Phiên hết hạn khi đang kiểm tra Hết thời gian chờ của cổng thông tin Sử dụng phiên dính, kiểm tra nhanh hơn
Thiếu dữ liệu về giá Yêu cầu đăng nhập Thêm bước xác thực
Giá hiển thị sai Định giá dựa trên địa lý Khớp vị trí proxy với thị trường

Câu hỏi thường gặp

Tôi nên kiểm tra hàng tồn kho của nhà cung cấp bao lâu một lần?

Hàng ngày đối với hầu hết các nhà cung cấp. Hàng giờ cho các thành phần quan trọng trong thời gian thiếu nguồn cung. Việc kiểm tra quá thường xuyên sẽ kích hoạt CAPTCHA nhanh hơn.

Tôi có thể giám sát hàng trăm nhà cung cấp không?

Vâng. Luân chuyển giữa các nhà cung cấp với độ trễ giữa mỗi nhà cung cấp. Sử dụng proxy luân phiên để phân phối tải trên các IP.

Loại CAPTCHA nào phổ biến nhất trên các trang web của chuỗi cung ứng?

reCAPTCHA v2 trên cổng nhà cung cấp, Cloudflare Turnstile trên các trang web logistics/carrier. Các trang web cũ của nhà sản xuất thường sử dụng CAPTCHA hình ảnh.


Hướng dẫn liên quan


Giữ cho chuỗi cung ứng của bạn luôn hiển thị —lấy khóa CaptchaAI của bạnvà tự động hóa việc thu thập dữ liệu trên tất cả các cổng của nhà cung cấp.

Os comentários estão desativados para este artigo.