Tedarik zinciri görünürlüğü yüzlerce tedarikçi portalından, lojistik platformundan ve envanter sisteminden veri gerektirir. Bunların çoğu verilerini CAPTCHA'ların arkasında koruyor. CaptchaAI bu zorlukların üstesinden gelerek işlem hatlarının izlenmesinin kesintisiz çalışmasını sağlar.
CAPTCHA'ların Tedarik Zinciri Verilerini Engellediği Yer
| Kaynak Türü | CAPTCHA Türü | Veri | Frekans |
|---|---|---|---|
| Tedarikçi portalları | reCAPTCHA v2 | Envanter, fiyatlandırma, teslimat süreleri | Günlük |
| Nakliye taşıyıcıları | Cloudflare Turnstile | Takip, ücretler, teslimat ETA'ları | Saatlik |
| Üretici katalogları | Resim CAPTCHA'sı | Ürün özellikleri, MOQ'lar | Haftalık |
| Gümrük portalları | reCAPTCHA v2 | Görev oranları, tarife kodları | Günlük |
| Liman yetkilileri | Resim CAPTCHA'sı | Gemi programları, liman tıkanıklığı | Her 6 saatte bir |
| Ticaret borsaları | reCAPTCHA v3 | Spot fiyatlar, vadeli işlemler | Gerçek zamanlı |
Çoklu Tedarikçi Monitörü
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))
Kargo Oranı Takibi
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 []
Stok Değişikliklerinde Uyarı Verme
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)
Sağlayıcı geri dönüş politikası
- Kritik tedarikçileri isteğe bağlı kaynaklardan ayırın, böylece tek bir arıza tüm izleme raporunun boşa gitmesine neden olmaz.
- Eski verilerin ne zaman kabul edilebilir olduğunu ve eksik bir tedarikçinin ne zaman açık bir olayı tetiklemesi gerektiğini tanımlayın.
- Tedarikçi üzerindeki ısrarlı CAPTCHA baskısını yalnızca bir mühendislik hatası olarak değil, kaynak bulma riski olarak artırın.
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Tedarikçi sayfa düzeni değiştirildi | Sitenin yeniden tasarımı | CSS seçicilerini güncelle |
| Her çekte CAPTCHA | Çok sık kontrol etme | Kontroller arasındaki aralığı artırın |
| Oturumun süresi kontrolün ortasında sona eriyor | Portal zaman aşımı | Yapışkan oturumu kullanın, daha hızlı kontrol edin |
| Oran verileri eksik | Giriş gerekli | Kimlik doğrulama adımı ekle |
| Yanlış fiyatlar görüntüleniyor | Coğrafi tabanlı fiyatlandırma | Proxy konumunu pazarla eşleştirin |
SSS
Tedarikçi envanterini ne sıklıkla kontrol etmeliyim?
Çoğu tedarikçi için günlük. Tedarik kıtlığı sırasında kritik bileşenler için saatlik. Çok sık yapılan kontroller CAPTCHA'ları daha hızlı tetikler.
Yüzlerce tedarikçiyi izleyebilir miyim?
Evet. Her biri arasında gecikme olacak şekilde tedarikçiler arasında rotasyon yapın. Yükü IP'ler arasında dağıtmak için QA test oturumu'ler kullanın.
Tedarik zinciri sitelerinde en yaygın olan CAPTCHA türü hangisidir?
Tedarikçi portallarında reCAPTCHA v2, lojistik/carrier sitelerinde Cloudflare Turnstile. Eski üretici siteleri genellikle resim CAPTCHA'larını kullanır.
İlgili Kılavuzlar
Tedarik zincirinizi görünür tutun —CaptchaAI anahtarınızı alınve tüm tedarikçi portallarında veri toplamayı otomatikleştirin.