تعمل شركات الشحن ومنصات الشحن على حماية حاسبات الأسعار وبوابات التتبع باستخدام اختبارات CAPTCHA. تحتاج الفرق اللوجستية ومنصات المقارنة إلى الوصول الآلي لمقارنة الأسعار وتتبع الشحنات ومراقبة أداء التسليم عبر شركات النقل.
CAPTCHAs في الخدمات اللوجستية
| نوع الناقل | اختبار CAPTCHA | الصفحات المحمية | حالة الاستخدام |
|---|---|---|---|
| ناقلات الطرود (UPS، FedEx) | reCAPTCHA v2 | حاسبة معدل، وتتبع | مقارنة الأسعار |
| وسطاء الشحن | Cloudflare Turnstile | طلبات الاقتباس | التسوق بسعر الشحن |
| ناقلات المحيط | صورة التحقق | تتبع السفن | تتبع الحاويات |
| البوابات الجمركية | reCAPTCHA v2 | الآلات الحاسبة واجب | تقدير الواجب |
| تسليم الميل الأخير | reCAPTCHA v2 | صفحات التتبع | مراقبة التسليم |
| الخدمات البريدية | صورة التحقق | الآلات الحاسبة معدل | الأسعار الدولية |
مكشطة معدل الناقلات المتعددة
import requests
import time
import re
import base64
from bs4 import BeautifulSoup
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")
class ShippingRateScraper:
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_rate(self, carrier, shipment):
"""Get shipping rate from a single carrier."""
url = carrier["rate_url"]
resp = self.session.get(url, timeout=30)
# Handle CAPTCHA
sitekey = self._extract_sitekey(resp.text)
if sitekey:
if carrier.get("captcha_type") == "turnstile":
token = solve_turnstile(sitekey, url)
field = "cf-turnstile-response"
else:
token = solve_recaptcha(sitekey, url)
field = "g-recaptcha-response"
resp = self.session.post(url, data={
**shipment,
field: token,
})
else:
resp = self.session.post(url, data=shipment)
if resp.status_code == 200:
return self._parse_rates(resp.text)
return None
def compare_rates(self, carriers, shipment):
"""Compare rates across multiple carriers."""
results = []
for carrier in carriers:
try:
rates = self.get_rate(carrier, shipment)
results.append({
"carrier": carrier["name"],
"status": "success",
"rates": rates,
})
except Exception as e:
results.append({
"carrier": carrier["name"],
"status": "error",
"error": str(e),
})
time.sleep(3)
# Sort by cheapest
successful = [r for r in results if r["rates"]]
if successful:
successful.sort(
key=lambda x: float(
re.sub(r'[^\d.]', '', x["rates"][0].get("price", "9999"))
)
)
return {
"shipment": shipment,
"results": results,
"cheapest": successful[0] if successful else None,
}
def _extract_sitekey(self, html):
match = re.search(r'data-sitekey="([^"]+)"', html)
return match.group(1) if match else None
def _parse_rates(self, html):
soup = BeautifulSoup(html, "html.parser")
rates = []
for row in soup.select(".rate-option, .shipping-option, tr.rate"):
service = row.select_one(".service-name, td:first-child")
price = row.select_one(".price, .rate-amount, td:nth-child(2)")
eta = row.select_one(".delivery-time, .eta, td:nth-child(3)")
if service:
rates.append({
"service": service.get_text(strip=True),
"price": price.get_text(strip=True) if price else "",
"eta": eta.get_text(strip=True) if eta else "",
})
return rates
# Usage
scraper = ShippingRateScraper(
proxy="http://user:pass@residential.proxy.com:5000"
)
carriers = [
{"name": "Carrier A", "rate_url": "https://carrier-a.example.com/rates", "captcha_type": "recaptcha"},
{"name": "Carrier B", "rate_url": "https://carrier-b.example.com/rates", "captcha_type": "turnstile"},
{"name": "Carrier C", "rate_url": "https://carrier-c.example.com/rates", "captcha_type": "recaptcha"},
]
shipment = {
"origin_zip": "10001",
"dest_zip": "90210",
"weight": "10",
"length": "12",
"width": "8",
"height": "6",
}
comparison = scraper.compare_rates(carriers, shipment)
print(f"Cheapest: {comparison['cheapest']}")
مراقبة التتبع بالجملة
class ShipmentTracker:
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 track(self, carrier_url, tracking_number, sitekey=None):
"""Track a single shipment."""
resp = self.session.get(carrier_url, timeout=30)
data = {"tracking_number": tracking_number}
if sitekey:
token = solve_recaptcha(sitekey, carrier_url)
data["g-recaptcha-response"] = token
resp = self.session.post(carrier_url, data=data)
if resp.status_code == 200:
soup = BeautifulSoup(resp.text, "html.parser")
return {
"tracking": tracking_number,
"status": self._text(soup, ".status, .tracking-status"),
"location": self._text(soup, ".location, .current-location"),
"eta": self._text(soup, ".eta, .estimated-delivery"),
"events": self._parse_events(soup),
}
return None
def bulk_track(self, carrier_url, tracking_numbers, sitekey=None):
"""Track multiple shipments."""
results = []
for tn in tracking_numbers:
try:
info = self.track(carrier_url, tn, sitekey)
results.append(info or {"tracking": tn, "status": "not found"})
except Exception as e:
results.append({"tracking": tn, "error": str(e)})
time.sleep(3)
return results
def _text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
def _parse_events(self, soup):
events = []
for event in soup.select(".tracking-event, .event-row"):
events.append({
"date": self._text(event, ".date, .event-date"),
"description": self._text(event, ".desc, .event-desc"),
"location": self._text(event, ".loc, .event-location"),
})
return events
جدول مراقبة الأسعار
| نوع البيانات | التردد | الحجم |
|---|---|---|
| أسعار الطرود المحلية | أسبوعيا | 50-100 زوج حارة |
| الأسعار الدولية | شهريا | 20-50 زوجًا من البلدان |
| الشحن LTL | يوميا | 10-30 زوجًا من الممرات |
| الشحن البحري | أسبوعيا | 10-20 زوجًا من المنافذ |
| تتبع الشحنة | كل 4 ساعات | لكل شحنة نشطة |
استكشاف الأخطاء وإصلاحها
| المشكلة | السبب | الإجراء |
|---|---|---|
| حاسبة الأسعار تعود فارغة | لم يتم حل اختبار CAPTCHA قبل الإرسال | قم بحل اختبار CAPTCHA أولاً، ثم أرسل النموذج |
| يظهر التتبع "لم يتم العثور عليه" | ناقل خاطئ أو فحص متأخر | التحقق من تنسيق رقم التتبع |
| سعر مختلف عن الموقع | الرسوم الإضافية مفقودة/fees | تحقق من وجود حقول رسوم الوقود الإضافية |
| مهلة الجلسة في نموذج السعر | استغرق تدفق المعدل متعدد الخطوات وقتًا طويلاً | استخدم الوكيل اللزج، وحل بشكل أسرع |
| IP محظور بواسطة الناقل | طلبات الأسعار كثيرة جدًا | الحد الأقصى للسعر هو 20-30 اقتباس/hour |
الأسئلة الشائعة
كم مرة يجب أن أتحقق من أسعار الشحن؟
أسبوعيا لمراقبة المعدل العام. يوميًا لاتخاذ قرارات الشحن الحساسة للوقت. تؤدي عمليات التحقق المتكررة إلى تشغيل اختبارات CAPTCHA بشكل أسرع.
هل يمكنني مقارنة الأسعار تلقائيًا؟
نعم. استخدم نهج المقارنة بين شركات النقل المتعددة أعلاه. أرسل نفس تفاصيل الشحنة إلى كل شركة نقل وقارن الردود.
ما هي شركات النقل التي لديها أصعب اختبارات CAPTCHA؟
تستخدم UPS وFedEx reCAPTCHA v2 في حاسبات الأسعار. يتطلب وسطاء الشحن الذين يقفون وراء Cloudflare حل Turnstile. غالبًا ما تستخدم شركات النقل في المحيطات صور CAPTCHA أبسط.
أدلة ذات صلة
- تناوب الوكلاء السكنيين: أفضل الممارسات لحل اختبار CAPTCHA
- البدء السريع مع CaptchaAI: حلّ أول كابتشا في 5 دقائق
مقارنة أسعار الشحن عبر شركات النقل –احصل على مفتاح CaptchaAI الخاص بكوأتمتة جمع البيانات اللوجستية.