تظهر BLS CAPTCHA على هيئة شبكة من تسع صور مصحوبة برمز رقمي، وحلّها آلياً يمرّ بأربع خطوات واضحة: التقط الصور التسع، اقرأ رمز التعليمات، أرسل كل ذلك إلى CaptchaAI، ثم انقر على الخلايا التي تعيدها الاستجابة. هذا النوع من شبكات الصور شائع في بوّابات حجز المواعيد والخدمات التي يتعامل معها كثير من المستخدمين في المنطقة العربية، ولهذا يحتاج مطوّرو الأتمتة إلى طريقة مستقرة للتعامل معه دون تدخّل يدوي في كل مرة.
يشرح هذا الدليل كل خطوة بأمثلة عملية بلغتَي Python وJavaScript يمكنك تشغيلها كما هي، مع توضيح كيفية قراءة رمز التعليمات وتحويل الاستجابة إلى نقرات على الخلايا الصحيحة. يحل CaptchaAI شبكات BLS بمعدل نجاح مرتفع، ويتولّى نيابةً عنك الجزء الأصعب: مطابقة الصور برمز التعليمات.
ما هي BLS CAPTCHA وكيف تُقرأ رموز تعليماتها
تتكوّن BLS CAPTCHA من ثلاثة عناصر أساسية تحتاج إلى فهمها قبل كتابة أي سكربت للأتمتة:
- شبكة 3×3 تحتوي على 9 خلايا صور مرتّبة في ثلاثة صفوف وثلاثة أعمدة
- رمز تعليمات رقمي (على سبيل المثال 664 أو 123 أو 546) يحدّد النمط الذي يجب البحث عنه داخل الصور
- ترقيم ثابت للخلايا يبدأ من اليسار إلى اليمين ومن الأعلى إلى الأسفل:
1 2 3
4 5 6
7 8 9
الفكرة المحورية أن رمز التعليمات ليس رقماً عشوائياً، بل مفتاح يربط بين ما هو معروض في الشبكة وبين الخلايا التي يُتوقّع من المستخدم اختيارها. الاستجابة التي تحصل عليها من CaptchaAI هي مصفوفة من أرقام الخلايا (من 1 إلى 9) التي تطابق هذا الرمز، مثل [1, 4, 7, 8]. لست بحاجة إلى تفسير الرمز يدوياً أو بناء نموذج تعرّف على الصور؛ فمهمّتك تنحصر في تجهيز المدخلات بشكل صحيح ثم ترجمة المصفوفة الناتجة إلى نقرات.
هذا التقسيم الواضح للمسؤوليات هو ما يجعل الأتمتة الموثوقة ممكنة: طبقة المتصفّح تلتقط الصور، وطبقة الـ API تتولّى المطابقة، وطبقتك أنت تنفّذ النقر. في الأقسام التالية سنبني كل طبقة على حدة ثم نجمعها في دالة واحدة.
الخطوة 1: التقاط صور الشبكة وقراءة رمز التعليمات
الخطوة الأولى تجري كلها داخل المتصفّح: نقرأ عناصر img التسعة من حاوية الشبكة، ونحوّل كل صورة إلى صيغة base64 حتى نتمكّن من إرسالها لاحقاً، ثم نستخرج رمز التعليمات من عنصر النص المجاور. تعبير \d{3,} يلتقط الرمز الرقمي حتى لو جاء مضمّناً داخل جملة مثل "اختر كل المربّعات التي تحمل الرقم 664".
Python مع Selenium
import base64
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com/bls-protected-page")
# Find the grid container
grid_cells = driver.find_elements(By.CSS_SELECTOR, ".captcha-grid img")
images = []
for cell in grid_cells:
src = cell.get_attribute("src")
if src.startswith("data:image"):
images.append(src)
else:
# Download and convert to base64
import requests
img_data = requests.get(src).content
b64 = base64.b64encode(img_data).decode()
images.append(f"data:image/png;base64,{b64}")
# Extract the instruction code
instruction_el = driver.find_element(By.CSS_SELECTOR, ".captcha-instruction")
instruction_code = instruction_el.text.strip()
# e.g., "664" or parsed from "Select all boxes with number 664"
import re
code_match = re.search(r'(\d{3,})', instruction_code)
instruction = code_match.group(1) if code_match else instruction_code
print(f"Instruction: {instruction}")
print(f"Images extracted: {len(images)}")
JavaScript مع Puppeteer
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com/bls-protected-page');
// Extract grid images as base64
const images = await page.evaluate(() => {
const cells = document.querySelectorAll('.captcha-grid img');
return Array.from(cells).map(img => {
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
canvas.getContext('2d').drawImage(img, 0, 0);
return canvas.toDataURL('image/png');
});
});
// Extract instruction code
const instruction = await page.evaluate(() => {
const el = document.querySelector('.captcha-instruction');
const match = el.textContent.match(/(\d{3,})/);
return match ? match[1] : el.textContent.trim();
});
console.log(`Instruction: ${instruction}, Images: ${images.length}`);
الخطوة 2: إرسال الشبكة إلى CaptchaAI
بعد جمع الصور والرمز، ترسل طلباً واحداً إلى نقطة النهاية in.php يحمل ثلاثة عناصر إلزامية: method=bls لتحديد نوع الحل، ورمز instructions، والصور التسع في الحقول من image_base64_1 حتى image_base64_9. يعيد الطلب معرّف مهمة (task_id)، ثم تستطلع نقطة النهاية res.php دورياً حتى تجهز النتيجة. هذا النمط القائم على الإرسال ثم الاستطلاع الدوري هو نفسه المستخدم مع بقية أنواع CAPTCHA في CaptchaAI، ما يسهّل توحيد الكود عبر مشروعك.
يعتمد تسعير CaptchaAI على عدد الـ Threads المتزامنة وليس على عدد عمليات الحل، مع حلول غير محدودة لكل Thread ضمن الاشتراك الشهري. تبدأ الخطط من BASIC بسعر $15 شهرياً و5 خيوط معالجة (Threads)، وترتفع إلى STANDARD بسعر $30 و15 خيطاً، فـ ADVANCE بسعر $90 و50 خيطاً، وصولاً إلى الخطط المؤسسية الأعلى. وهو نموذج مناسب لإرسال شبكات BLS متعددة بالتوازي دون رسوم على كل عملية.
Python
import requests
import time
import json
API_KEY = "YOUR_API_KEY"
# Prepare submission data
data = {
"key": API_KEY,
"method": "bls",
"instructions": instruction,
"json": "1",
}
# Add all 9 images
files = {}
for i, img in enumerate(images):
files[f"image_base64_{i+1}"] = (None, img)
# Submit
resp = requests.post(
"https://ocr.captchaai.com/in.php",
data=data,
files=files
).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
print(f"Task ID: {task_id}")
# Poll for result
for _ in range(20):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
solution = json.loads(result["request"])
print(f"Selected cells: {solution}") # e.g., [1, 4, 7, 8]
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
const axios = require('axios');
const FormData = require('form-data');
const form = new FormData();
form.append('key', 'YOUR_API_KEY');
form.append('method', 'bls');
form.append('instructions', instruction);
form.append('json', '1');
images.forEach((img, i) => {
form.append(`image_base64_${i + 1}`, img);
});
const submit = await axios.post('https://ocr.captchaai.com/in.php', form, {
headers: form.getHeaders(),
});
const taskId = submit.data.request;
// Poll
let solution = null;
for (let i = 0; i < 20; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
});
if (poll.data.status === 1) {
solution = JSON.parse(poll.data.request);
break;
}
}
console.log('Selected cells:', solution); // e.g., [2, 4, 7]
الخطوة 3: النقر على الخلايا التي أعادها الحل
الآن تحوّل المصفوفة الناتجة إلى تفاعل فعلي على الصفحة. تذكّر أن أرقام الخلايا تبدأ من 1 بينما تبدأ فهارس القوائم في الكود من 0، لذا نطرح 1 من كل رقم قبل النقر. بعد اختيار جميع الخلايا المطلوبة نرسل النموذج لإتمام العملية:
# Selenium — click the cells returned by CaptchaAI
grid_cells = driver.find_elements(By.CSS_SELECTOR, ".captcha-grid .cell")
for cell_index in solution:
# cell_index is 1-based
grid_cells[cell_index - 1].click()
# Submit the form
submit_btn = driver.find_element(By.CSS_SELECTOR, ".captcha-submit")
submit_btn.click()
// Puppeteer
const cells = await page.$$('.captcha-grid .cell');
for (const idx of solution) {
await cells[idx - 1].click();
}
await page.click('.captcha-submit');
الدالة الكاملة: من الالتقاط حتى النقر
تجمع الدالة التالية الخطوات الثلاث في وحدة واحدة قابلة لإعادة الاستخدام داخل أي سكربت أتمتة. تستقبل كائن driver ومفتاح الـ API، ثم تنفّذ الالتقاط والإرسال والاستطلاع والنقر بالتسلسل، وتعيد مصفوفة الخلايا المختارة. هذا التغليف يسهّل استدعاء الحل من أي نقطة في مشروعك دون تكرار المنطق:
def solve_bls_captcha(driver, api_key):
"""Extract, solve, and submit a BLS CAPTCHA."""
import base64, requests, time, json, re
# 1. Extract images
grid_cells = driver.find_elements(By.CSS_SELECTOR, ".captcha-grid img")
images = []
for cell in grid_cells:
src = cell.get_attribute("src")
if src.startswith("data:image"):
images.append(src)
else:
img_data = requests.get(src).content
b64 = base64.b64encode(img_data).decode()
images.append(f"data:image/png;base64,{b64}")
# 2. Extract instruction
el = driver.find_element(By.CSS_SELECTOR, ".captcha-instruction")
match = re.search(r'(\d{3,})', el.text)
instruction = match.group(1)
# 3. Submit to CaptchaAI
data = {"key": api_key, "method": "bls", "instructions": instruction, "json": "1"}
files = {f"image_base64_{i+1}": (None, img) for i, img in enumerate(images)}
resp = requests.post("https://ocr.captchaai.com/in.php", data=data, files=files).json()
task_id = resp["request"]
# 4. Poll
for _ in range(20):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
solution = json.loads(result["request"])
break
# 5. Click cells
clickable = driver.find_elements(By.CSS_SELECTOR, ".captcha-grid .cell")
for idx in solution:
clickable[idx - 1].click()
return solution
سيناريو عملي: فريق يبني مراقبة موثوقة لبوّابة خدمات
تخيّل فريق تطوير في القاهرة أو الرياض يبني أداة مراقبة داخلية تتحقق من توفّر الخدمة على بوّابة تعتمد شبكة صور من نوع BLS. تحتاج الأداة إلى تسجيل الدخول واجتياز خطوة التحقق بشكل متكرّر ضمن اختبارات الجودة (QA) لقياس زمن الاستجابة وموثوقية سير العمل. من دون حل آلي، يتوقّف كل تشغيل عند الشبكة وينتظر تدخّلاً بشرياً، ما يجعل المراقبة المستمرة غير عملية.
بإدماج الدالة السابقة، يتحوّل هذا الحاجز إلى استدعاء واحد يعيد الخلايا المطابقة خلال ثوانٍ. يمكن للفريق حينها تشغيل الاختبار كل بضع دقائق على مدار اليوم، وقياس الأداء بموضوعية، وإطلاق تنبيه عند تعطّل الخدمة — كل ذلك ضمن أتمتة معتمدة على أنظمة يملك الفريق صلاحية اختبارها. النموذج القائم على الخيوط يعني أن زيادة وتيرة الفحص لا تفرض رسوماً إضافية لكل عملية، بل تحتاج فقط إلى خيوط كافية للطلبات المتزامنة.
معالجة الأخطاء الشائعة في حل BLS
معظم مشكلات حل BLS تعود إلى مدخلات غير مكتملة أو خطأ في مطابقة أرقام الخلايا، لا إلى الحل نفسه. يلخّص الجدول التالي أكثر الأخطاء تكراراً وطريقة إصلاح كل منها بسرعة:
| مشكلة | السبب | إصلاح |
|---|---|---|
ERROR_BAD_PARAMETERS |
الصور المفقودة أو لا توجد تعليمات | تأكد من أن جميع الصور التسعة هي معرفات URI صالحة لبيانات base64 |
| تم تحديد خلايا خاطئة | تعيين الخلية إلى الفهرس غير صحيح | تحقق من ترقيم الخلايا من 1 إلى 9 من اليسار إلى اليمين، ومن أعلى إلى أسفل |
| لا يتم تحميل الصور | تقييد عبر الأصل | نزّل الصور من جانب الخادم وحوّلها إلى base64 |
| رمز تعليمات فارغ | التعليمات مخفية في الصورة | استخرج نص التعليمات أو طبّق التعرّف الضوئي على الحروف (OCR) على صورة التعليمات |
أسئلة شائعة حول حل BLS CAPTCHA
هل يمكن أتمتة حل BLS CAPTCHA بالكامل عبر API؟
نعم. بمجرد التقاط الصور التسع ورمز التعليمات، يتولّى CaptchaAI المطابقة ويعيد أرقام الخلايا الصحيحة، فتتحوّل العملية بأكملها إلى استدعاء برمجي واحد دون أي تدخّل يدوي. الجزء الوحيد الذي يبقى ضمن كودك هو التقاط المدخلات من الصفحة وتنفيذ النقر على الخلايا الناتجة.
كم تبلغ تكلفة حل BLS CAPTCHA عبر CaptchaAI؟
لا يُحسب السعر لكل عملية حل، بل حسب عدد الخيوط (Threads) المتزامنة في اشتراكك الشهري، مع حلول غير محدودة لكل خيط. تبدأ خطة BASIC من $15 شهرياً بخمسة خيوط، وهو ما يكفي للمشاريع الصغيرة، بينما توفّر الخطط الأعلى مثل ADVANCE بسعر $90 و50 خيطاً طاقة أكبر للطلبات المتوازية.
لماذا يختلف عدد الخلايا في الاستجابة من طلب لآخر؟
لأن كل شبكة BLS تحمل رمز تعليمات مختلفاً، وعدد الخلايا المطابقة يعتمد على هذا الرمز ومحتوى الصور. قد تعيد الاستجابة ثلاث خلايا في حالة وأربعاً في أخرى؛ لذا اجعل كودك يتعامل مع مصفوفة متغيّرة الطول بدل افتراض عدد ثابت.
كيف أتعامل مع رمز تعليمات مضمّن داخل الصورة؟
إن لم يظهر الرمز كنص في عنصر HTML مستقل، فاستخرج صورة التعليمات ومرّرها عبر أداة تعرّف ضوئي على الحروف (OCR) للحصول على الرقم، ثم أرسله في حقل instructions كالمعتاد. تحقّق دائماً من أن القيمة الملتقطة رقمية قبل الإرسال لتفادي خطأ ERROR_BAD_PARAMETERS.
هل يدعم CaptchaAI أنواع CAPTCHA أخرى إلى جانب BLS؟
نعم. إلى جانب BLS، يحل CaptchaAI أنواع reCAPTCHA v2 وv3 وCloudflare Turnstile وCloudflare Challenge وGeeTest v3 والصور والشبكات و OCR، مع دعم تجريبي (beta) لأنواع CaptchaFox وFriendly Captcha وLemin. أما hCaptcha وFunCaptcha فغير مدعومَين حالياً، ودعم GeeTest v4 قادم لاحقاً.
ابدأ حل BLS CAPTCHA مع CaptchaAI
أنشئ مفتاح الـ API الخاص بك على captchaai.com وشغّل الأمثلة أعلاه في مشروعك مباشرة.