تعمل قواعد بيانات الرواتب ولوحات الوظائف وبوابات العمل الحكومية على حماية بيانات التعويضات باستخدام Cloudflare Turnstile وreCAPTCHA. يتم تشغيل اختبار CAPTCHA عند الاستعلام عن نطاقات الرواتب حسب الدور أو الموقع أو الصناعة - خاصة أثناء جمع البيانات المجمعة عبر العديد من المسميات الوظيفية. وإليك كيفية التعامل معها.
أنماط CAPTCHA على بوابات الرواتب
نوع المصدر
اختبار CAPTCHA
المحفّز
مواقع مقارنة الرواتب
Cloudflare Turnstile
استعلامات البحث المتكررة
مرشحات رواتب مجلس العمل
reCAPTCHA v2
عمليات بحث متعددة عن الراتب
إحصاءات العمل الحكومية
صورة التحقق
طلبات تنزيل البيانات
صفحات رواتب الشركات
Cloudflare Challenge
مشاهدات الصفحة بالجملة
منصات مسح الموارد البشرية
reCAPTCHA v3
تقديمات النموذج
جامع بيانات الراتب
import requests
import time
import re
from dataclasses import dataclass
@dataclass
class SalaryRecord:
title: str
location: str
min_salary: float
max_salary: float
median_salary: float
sample_size: int
source: str
class SalaryCollector:
def __init__(self, api_key):
self.api_key = api_key
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
def collect_salary_data(self, portal_url, job_title, location):
"""Search for salary data, solving CAPTCHAs as needed."""
response = self.session.get(portal_url, params={
"title": job_title,
"location": location
})
if self._is_turnstile_challenge(response):
response = self._solve_turnstile_and_retry(response, portal_url)
return self._parse_salary_data(response.text, portal_url)
def collect_bulk(self, portal_url, job_titles, locations):
"""Collect salary data for multiple job title + location combos."""
results = []
for title in job_titles:
for location in locations:
try:
data = self.collect_salary_data(
portal_url, title, location
)
results.extend(data)
# Respectful delay between requests
time.sleep(2)
except Exception as e:
print(f"Failed for {title} in {location}: {e}")
return results
def _is_turnstile_challenge(self, response):
return (
response.status_code == 403 or
"cf-turnstile" in response.text or
"challenges.cloudflare.com" in response.text
)
def _solve_turnstile_and_retry(self, response, url):
match = re.search(r'data-sitekey="(0x[^"]+)"', response.text)
if not match:
raise ValueError("Turnstile sitekey not found")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": self.api_key,
"method": "turnstile",
"sitekey": match.group(1),
"pageurl": url,
"json": 1
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(3)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": self.api_key,
"action": "get",
"id": task_id,
"json": 1
})
data = result.json()
if data["status"] == 1:
return self.session.post(url, data={
"cf-turnstile-response": data["request"]
})
raise TimeoutError("Turnstile solve timed out")
def _parse_salary_data(self, html, source):
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
records = []
def text_or_empty(node):
return node.text.strip() if node and node.text else ""
for row in soup.select(".salary-row, .compensation-entry, tr[data-salary]"):
try:
records.append(SalaryRecord(
title=text_or_empty(row.select_one(".job-title, .title")),
location=text_or_empty(row.select_one(".location")),
min_salary=self._parse_amount(
text_or_empty(row.select_one(".min-salary, .low"))
),
max_salary=self._parse_amount(
text_or_empty(row.select_one(".max-salary, .high"))
),
median_salary=self._parse_amount(
text_or_empty(row.select_one(".median, .mid"))
),
sample_size=int(
text_or_empty(row.select_one(".count, .sample")).replace(",", "") or 0
),
source=source
))
except (AttributeError, ValueError):
continue
return records
def _parse_amount(self, text):
if not text:
return 0.0
cleaned = re.sub(r'[^\d.]', '', text)
return float(cleaned) if cleaned else 0.0
# Usage
collector = SalaryCollector("YOUR_API_KEY")
data = collector.collect_bulk(
"https://salary.example.com/search",
job_titles=["Software Engineer", "Data Analyst", "Product Manager"],
locations=["San Francisco", "New York", "Austin"]
)
for record in data:
print(f"{record.title} in {record.location}: "
f"${record.min_salary:,.0f}–${record.max_salary:,.0f} "
f"(median: ${record.median_salary:,.0f})")
دليل عملي لأتمتة إرسال النماذج المحمية بـ CAPTCHA عبر Selenium: اكتشف نوع الاختبار، حلّه بـ Captcha AI، ثم احقن الرمز قبل الإرسال مع أمثلة Python جاهزة.
ابنِ فاحصًا آليًا لتدفق التسجيل يحلّ re CAPTCHA v 2 وCloudflare Turnstile عبر Captcha AI، ويغطّي البريد المكرر...
May 03, 2026
حالات الاستخدام
راقب أسعار تذاكر الطيران آليًا على مواقع محمية بـ CAPTCHA؛ اكتشف اختبارات re CAPTCHA v 2 وCloudflare Turnstile وحلّها عبر Captcha AI بسكربت Python واحد.
راقب أسعار تذاكر الطيران آليًا على مواقع محمية بـ CAPTCHA؛ اكتشف اختبارات re CAPTCHA v 2 وCloudflare Turnstile...
Apr 16, 2026
التكاملات
يشرح هذا الدليل كيفية دمج عزل ملفات تعريف المتصفح مع Captcha AI في بيئات الاختبار والأتمتة المصرّح بها: فصل الجلسات، والحفاظ على ملفات تعريف الارتباط، وحل re CA...
يشرح هذا الدليل كيفية دمج عزل ملفات تعريف المتصفح مع Captcha AI في بيئات الاختبار والأتمتة المصرّح بها: فصل ال...
Apr 27, 2026
الدروس التطبيقية
تعلّم بناء مسار موحّد يستقبل طلبات الحل من عدة عملاء ويرسلها إلى Captcha AI ويعيد الرموز المحلولة، مع إدارة قائمة الانتظار والتزامن في Python وNode.js.
تعلّم بناء مسار موحّد يستقبل طلبات الحل من عدة عملاء ويرسلها إلى Captcha AI ويعيد الرموز المحلولة، مع إدارة قا...
Apr 30, 2026
التكاملات
اربط وكلاء Bright Data السكنية ومراكز البيانات بـ Captcha AI لحل re CAPTCHA v 2 وCloudflare Turnstile على نطاق واسع، مع أمثلة Python وNode.js وضبط للجلسات.