عند استخراج البيانات من مواقع تعتمد حماية قوية، تظهر مشكلتان معًا: حظر عنوان IP وظهور اختبار CAPTCHA. الحل عمليًا هو فصلهما إلى طبقتين مستقلتين. تتكفّل شبكة Bright Data — التي تضم أكثر من 72 مليون عنوان IP سكني في 195 دولة — بطبقة التصفح عبر عناوين موثوقة تقلّل احتمال ظهور التحدي من الأساس. ويتكفّل CaptchaAI بطبقة الحل: حين يظهر تحدٍّ رغم كل شيء، يعيد إليك رمزًا صالحًا لـ reCAPTCHA v2 أو Cloudflare Turnstile أو Cloudflare Challenge. هذا الدليل يربط الطبقتين بأمثلة جاهزة في Python وNode.js.
البنية: طبقتان تحلّان مشكلتين مختلفتين
Your Script ──▶ Bright Data Proxy ──▶ Target Site
│
CAPTCHA appears
│
CaptchaAI API ──▶ Solved token
│
Inject token ◀─┘
النقطة الجوهرية التي يخطئ فيها الكثيرون: لا يمرّ CaptchaAI عبر الوكيل الخاص بك، بل يحل التحدي من جانب الخادم عبر بنيته التحتية المستقلّة. الوكيل مسؤول عن تحميل الصفحة فقط، بينما يتولّى CaptchaAI معالجة اختبار CAPTCHA وإعادة الرمز إليك لحقنه في النموذج. فصل المسؤوليتين هكذا يجعل كل طبقة قابلة للضبط والتوسّع على حدة، ويتوزّع الدور بينهما كالآتي:
- طبقة التصفح (Bright Data): تحمّل الصفحة عبر عنوان IP موثوق، وتتحكّم في الموقع الجغرافي وثبات الجلسة لتقليل ظهور التحدي من الأساس.
- طبقة الحل (CaptchaAI): تستقبل مفتاح الموقع وعنوان الصفحة، ثم تعيد رمزًا صالحًا تحقنه في النموذج قبل الإرسال.
متى تختار كل نوع من وكلاء Bright Data
اختيار نوع الوكيل هو أول عامل يحدّد كم مرة سترى اختبار CAPTCHA أصلاً. القاعدة العامة: كلما زادت «الثقة» في عنوان IP، انخفض معدل ظهور التحدي، وارتفعت التكلفة في المقابل.
| النوع | عناوين IP | السرعة | التكلفة | معدل CAPTCHA |
|---|---|---|---|---|
| مركز البيانات | 770 ألف+ | سريع | منخفض | أعلى |
| سكني | 72 مليون+ | متوسط | متوسط | أقل |
| مزود خدمة الإنترنت (ISP) | 700 ألف+ | سريع | عالية | أدنى |
| الجوال | 7 مليون+ | بطيء | عالية | منخفض جدًا |
بالنسبة لمعظم مهام الاستخراج المتوسطة، الوكيل السكني هو نقطة التوازن الأنسب بين التكلفة ومعدل التحدي. أما وكلاء ISP فيمنحونك سرعة مركز البيانات مع ثقة قريبة من السكني، وهو خيار مناسب للمواقع شديدة الحساسية.
دمج CaptchaAI مع Bright Data في Python
الطريقة الأولى: عبر مكتبة requests
هذا النمط مناسب حين تتعامل مباشرة مع طلبات HTTP دون متصفح كامل. تُحمّل الصفحة عبر وكيل Bright Data، ثم يُرسَل مفتاح الموقع وعنوان الصفحة إلى CaptchaAI للحصول على الرمز:
import requests
import time
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
# Bright Data proxy credentials
BRIGHT_DATA_PROXY = {
"http": "http://brd-customer-CUSTOMER_ID-zone-ZONE:PASSWORD@brd.superproxy.io:22225",
"https": "http://brd-customer-CUSTOMER_ID-zone-ZONE:PASSWORD@brd.superproxy.io:22225",
}
def fetch_with_proxy(url):
"""Fetch a page through Bright Data proxy."""
resp = requests.get(
url,
proxies=BRIGHT_DATA_PROXY,
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/126.0.0.0 Safari/537.36"
},
timeout=30,
)
return resp
def solve_recaptcha(site_url, sitekey):
"""Solve reCAPTCHA v2 via CaptchaAI."""
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": site_url,
"json": 1,
})
data = resp.json()
if data["status"] != 1:
raise Exception(f"Submit: {data['request']}")
task_id = data["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
data = resp.json()
if data["request"] == "CAPCHA_NOT_READY":
continue
if data["status"] == 1:
return data["request"]
raise Exception(f"Solve: {data['request']}")
raise TimeoutError("Solve timeout")
def solve_turnstile(site_url, sitekey):
"""Solve Cloudflare Turnstile via CaptchaAI."""
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "turnstile",
"sitekey": sitekey,
"pageurl": site_url,
"json": 1,
})
data = resp.json()
task_id = data["request"]
for _ in range(60):
time.sleep(5)
resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY,
"action": "get",
"id": task_id,
"json": 1,
})
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("Solve timeout")
لاحظ أن دالة الاستطلاع الدوري تنتظر خمس ثوانٍ بين كل محاولة وأخرى حتى تصل حالة status == 1، وهو النمط القياسي في التعامل مع نقطتَي النهاية in.php وres.php.
الطريقة الثانية: التحكم بالمتصفح عبر Selenium
حين يعتمد الموقع على JavaScript ثقيل أو يحتاج التحدي إلى تحميل فعلي في المتصفح، استخدم Selenium خلف الوكيل نفسه. بعد استخراج مفتاح الموقع تلقائيًا، يُحقن الرمز المُعاد في الحقل المخفي g-recaptcha-response ثم يُستدعى الـ Callback المناسب:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
BRIGHT_DATA_HOST = "brd.superproxy.io"
BRIGHT_DATA_PORT = 22225
BRIGHT_DATA_USER = "brd-customer-CUSTOMER_ID-zone-residential"
BRIGHT_DATA_PASS = "PASSWORD"
def create_driver_with_proxy():
options = webdriver.ChromeOptions()
options.add_argument(
f"--proxy-server=http://{BRIGHT_DATA_HOST}:{BRIGHT_DATA_PORT}"
)
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=options)
return driver
def scrape_with_captcha_solving(url, sitekey=None):
driver = create_driver_with_proxy()
try:
driver.get(url)
time.sleep(3)
# Auto-detect sitekey if not provided
if not sitekey:
sitekey = driver.execute_script(
"return document.querySelector('[data-sitekey]')"
"?.getAttribute('data-sitekey')"
)
if sitekey:
token = solve_recaptcha(url, sitekey)
driver.execute_script(f"""
document.querySelector('#g-recaptcha-response').value = '{token}';
document.querySelectorAll('[name="g-recaptcha-response"]')
.forEach(el => {{ el.value = '{token}'; }});
""")
# Trigger callback
driver.execute_script("""
if (typeof ___grecaptcha_cfg !== 'undefined') {
const clients = ___grecaptcha_cfg.clients;
for (const key in clients) {
for (const prop in clients[key]) {
const val = clients[key][prop];
if (val && typeof val === 'object') {
for (const p in val) {
if (typeof val[p]?.callback === 'function') {
val[p].callback(arguments[0]);
}
}
}
}
}
}
""")
return driver.page_source
finally:
driver.quit()
استهداف الدولة والمدينة لخفض معدل CAPTCHA
تدعم Bright Data الاستهداف على مستوى الدولة والولاية والمدينة. مطابقة موقع الوكيل مع الموقع الجغرافي للموقع المستهدف تقلّل التناقض بين عنوان IP والمحتوى، وهو أحد أكثر أسباب ظهور اختبار CAPTCHA شيوعًا:
# Country targeting
proxy_us = "http://brd-customer-ID-zone-residential-country-us:PASS@brd.superproxy.io:22225"
proxy_uk = "http://brd-customer-ID-zone-residential-country-gb:PASS@brd.superproxy.io:22225"
proxy_de = "http://brd-customer-ID-zone-residential-country-de:PASS@brd.superproxy.io:22225"
# City targeting
proxy_nyc = "http://brd-customer-ID-zone-residential-country-us-city-newyork:PASS@brd.superproxy.io:22225"
# Use the geo-matched proxy for lower CAPTCHA rates
def scrape_localized(url, country="us"):
proxy = f"http://brd-customer-ID-zone-residential-country-{country}:PASS@brd.superproxy.io:22225"
resp = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
return resp
مثال من السوق الإقليمي: لنفترض أنك تبني أداة لمقارنة الأسعار عبر متاجر تجزئة في السعودية والإمارات. عند استخراج بيانات موقع سعودي، فإن الوصول عبر عنوان IP أوروبي أو أمريكي يرفع احتمال ظهور التحدي أو حجب المحتوى الإقليمي. بنفس النمط الظاهر أعلاه، تستبدل رمز الدولة ليطابق السوق المستهدف — فتحصل على محتوى مطابق للمنطقة ومعدل تحدٍّ أقل. وحين يظهر reCAPTCHA رغم ذلك، يتولّى CaptchaAI حلّه دون أن يتغيّر منطق الاستخراج لديك.
إدارة الجلسات: ثابتة أم دوّارة؟
# Sticky session (same IP for entire session)
proxy_sticky = (
"http://brd-customer-ID-zone-residential"
"-session-abc123:PASS@brd.superproxy.io:22225"
)
# Rotating (new IP each request)
proxy_rotating = (
"http://brd-customer-ID-zone-residential:PASS@brd.superproxy.io:22225"
)
القاعدة الحاسمة لسير عمل CAPTCHA: استخدم الجلسات الثابتة (Sticky). يرتبط رمز CAPTCHA بعنوان IP الذي حمّل الصفحة؛ فإذا تغيّر العنوان بين لحظة التحميل ولحظة إرسال النموذج، سيُرفض الرمز حتى لو كان صحيحًا. الجلسات الدوّارة مفيدة للتصفح العام، لكنها تكسر أي مسار يعتمد على رمز مرتبط بعنوان محدّد.
الدمج في Node.js
نفس المنطق ينطبق على بيئة JavaScript عبر Axios ووكيل https-proxy-agent:
const axios = require("axios");
const https = require("https");
const CAPTCHAAI_KEY = "YOUR_API_KEY";
const CAPTCHAAI_URL = "https://ocr.captchaai.com";
const proxyAgent = new (require("https-proxy-agent"))(
"http://brd-customer-ID-zone-residential:PASS@brd.superproxy.io:22225"
);
async function fetchWithProxy(url) {
return axios.get(url, {
httpsAgent: proxyAgent,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0",
},
});
}
async function solveCaptcha(siteUrl, sitekey) {
const submit = await axios.post(`${CAPTCHAAI_URL}/in.php`, null, {
params: {
key: CAPTCHAAI_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: siteUrl,
json: 1,
},
});
const taskId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const result = await axios.get(`${CAPTCHAAI_URL}/res.php`, {
params: {
key: CAPTCHAAI_KEY,
action: "get",
id: taskId,
json: 1,
},
});
if (result.data.request === "CAPCHA_NOT_READY") continue;
if (result.data.status === 1) return result.data.request;
}
throw new Error("Timeout");
}
الإعداد الموصى به لمنطقة Bright Data
| إعداد المنطقة | الموصى به لاختبار CAPTCHA | لماذا |
|---|---|---|
| نوع الوكيل | سكني | أقل معدل لتشغيل اختبار CAPTCHA |
| استهداف البلد | مطابقة موقع الموقع المستهدف | اتساق عنوان IP مع المحتوى |
| نوع الجلسة | ثابتة (Sticky) | يجب أن يطابق الرمز عنوان IP الأصلي |
| مرشّح جودة IP | جودة عالية | تجنّب العناوين المُعلَّمة سابقًا |
| أقصى عدد للطلبات المتزامنة | 100+ | تشغيل مسارات CAPTCHA بالتوازي |
عند تشغيل عشرات أو مئات عمليات الحل بالتوازي، تذكّر أن CaptchaAI يحاسبك على أساس عدد الـ Threads المتزامنة لا على أساس كل عملية حل، مع حلول غير محدودة داخل كل Thread. لتشغيل يقارب 100 طلب متزامن، اختر خطة يتناسب عدد خيوطها مع الحجم — مثل ADVANCE ($90 شهريًا، 50 Thread) أو PREMIUM ($170 شهريًا، 100 Thread) وفق كثافة عملك.
حل المشكلات الشائعة
| المشكلة | السبب | الإجراء |
|---|---|---|
| خطأ 407 من الوكيل | بيانات اعتماد خاطئة | تحقّق من معرّف العميل والمنطقة وكلمة المرور |
| ظهور CAPTCHA في كل طلب | اكتشاف وكيل مركز البيانات | انتقل إلى المنطقة السكنية |
| رفض الرمز بعد الحل | تغيّر عنوان IP بين الحل والإرسال | استخدم الجلسات الثابتة |
| استجابة بطيئة | ازدحام عقدة الخروج | استهدف دولة/مدينة أقل ازدحامًا |
| رفض الاتصال | بلوغ حدّ النطاق الترددي | راجع لوحة تحكم Bright Data |
أسئلة يطرحها المطوّرون
لماذا يظهر اختبار CAPTCHA أكثر مع وكلاء مركز البيانات؟
لأن عناوين مراكز البيانات معروفة ومصنّفة على نطاق واسع كحركة آلية، فتُعلَّم بسهولة. العناوين السكنية تعود لمشتركي إنترنت حقيقيين، لذا تحظى بثقة أعلى ومعدل تحدٍّ أقل. إن كان الموقع المستهدف حسّاسًا، انتقل إلى المنطقة السكنية أو ISP.
هل يؤثر اختيار دولة الوكيل في معدل ظهور التحدي؟
نعم. عندما يتطابق موقع عنوان IP مع الموقع الجغرافي المتوقّع للموقع، يقلّ التناقض الذي تعتمد عليه أنظمة الحماية في إطلاق التحدي. مطابقة الدولة — بل المدينة أحيانًا — تخفض معدل ظهور CAPTCHA وتضمن محتوى مطابقًا للمنطقة.
كم عدد الـ Threads الذي أحتاجه لتشغيل 100 طلب متوازٍ؟
عدد الـ Threads في خطتك يحدّد كم عملية حل يمكن تنفيذها في آنٍ واحد. لتشغيل قرابة 100 حل متزامن، تحتاج خطة بعدد خيوط مماثل مثل PREMIUM ($170 شهريًا، 100 Thread). لأحجام أصغر تكفي ADVANCE ($90 شهريًا، 50 Thread). الحلول داخل كل Thread غير محدودة.
ماذا أفعل عندما يُرفض الرمز رغم أنه حُلّ بنجاح؟
غالبًا يكون السبب تغيّر عنوان IP بين تحميل الصفحة وإرسال النموذج. ثبّت الجلسة (Sticky) بحيث يبقى العنوان نفسه طوال الدورة. تأكّد أيضًا من أنك تحقن الرمز في الحقل الصحيح وتستدعي الـ Callback المناسب قبل الإرسال.
هل يمكنني تمرير الوكيل الخاص بي إلى CaptchaAI؟
نعم. تقبل واجهة CaptchaAI مُعامل proxy، فيحل التحدي من عنوان IP نفسه الذي حمّلت الصفحة منه. هذا مفيد للتحديات المرتبطة بعنوان محدّد التي تتطلّب تطابق العنوان بين التحميل والحل.
مقالات ذات صلة
اجمع بين شبكة وكلاء Bright Data وحلّ اختبار CAPTCHA الآلي — أنشئ مفتاح CaptchaAI الخاص بك ووسّع نطاق الأتمتة لديك.