Reference

استمرارية جلسة المتصفح لسير عمل اختبار CAPTCHA

تبدأ كل جلسة متصفح جديدة من الصفر - بدون ملفات تعريف الارتباط، ولا حالة محفوظة، ولا سجل تشغيل معروف. في التطبيقات المملوكة قد يؤدي ذلك إلى اختلاف سلوك CAPTCHA بين تشغيل وآخر. تساعد الجلسات المستمرة بين عمليات التشغيل على إعادة إنتاج نفس الحالة الوظيفية وتقليل التفاوت غير المقصود بين اختبارات QA.


لماذا يؤدي استمرار الجلسة إلى تقليل اختبارات CAPTCHA

حالة الجلسة تردد الكابتشا لماذا
جلسة جديدة (بدون ملفات تعريف الارتباط) عالية لا توجد حالة تطبيق محفوظة بعد
جلسة سابقة داخل التطبيق نفسه متوسطة يمكن إعادة استخدام بيانات الاعتماد والحالة الوظيفية
جلسة مهيأة داخل صفحات مملوكة أقل تكون عناصر التطبيق والخطوات المسبقة قد اكتملت
ملف شخصي مستمر لعمر اختباري معروف أقل نسبيًا يسهل إعادة إنتاج نفس الحالة بين التشغيلات

ثبات ملفات تعريف الارتباط (السيلينيوم/Python)

حفظ واستعادة ملفات تعريف الارتباط

import json
import os
import time
from selenium import webdriver


class PersistentSession:
    def __init__(self, profile_name="default", cookie_dir="./sessions"):
        self.profile_name = profile_name
        self.cookie_dir = cookie_dir
        self.cookie_file = os.path.join(cookie_dir, f"{profile_name}_cookies.json")
        os.makedirs(cookie_dir, exist_ok=True)

    def create_driver(self):
        options = webdriver.ChromeOptions()
        options.add_argument("--window-size=1920,1080")
        return webdriver.Chrome(options=options)

    def save_cookies(self, driver):
        """Save all cookies to disk."""
        cookies = driver.get_cookies()
        with open(self.cookie_file, "w") as f:
            json.dump(cookies, f, indent=2)
        print(f"Saved {len(cookies)} cookies to {self.cookie_file}")

    def load_cookies(self, driver, domain=None):
        """Restore cookies from disk."""
        if not os.path.exists(self.cookie_file):
            print("No saved cookies found")
            return False

        with open(self.cookie_file) as f:
            cookies = json.load(f)

        loaded = 0
        for cookie in cookies:
            # Filter by domain if specified
            if domain and domain not in cookie.get("domain", ""):
                continue

            # Remove problematic fields
            cookie.pop("sameSite", None)
            cookie.pop("storeId", None)

            try:
                driver.add_cookie(cookie)
                loaded += 1
            except Exception as e:
                print(f"Skip cookie {cookie.get('name')}: {e}")

        print(f"Loaded {loaded}/{len(cookies)} cookies")
        return loaded > 0

    def run_with_session(self, url, callback):
        """Run a task with persistent session."""
        driver = self.create_driver()

        try:
            # Navigate to domain first (required for cookie loading)
            driver.get(url)
            time.sleep(1)

            # Load saved cookies
            self.load_cookies(driver)

            # Refresh to apply cookies
            driver.get(url)
            time.sleep(2)

            # Execute task
            result = callback(driver)

            # Save updated cookies
            self.save_cookies(driver)

            return result

        finally:
            driver.quit()


# Usage
session = PersistentSession("target-site")

def my_task(driver):
    # Check if already logged in
    if "dashboard" in driver.current_url:
        print("Session restored — no login needed")
        return driver.page_source
    else:
        print("Need to login + solve CAPTCHA")
        # Solve CAPTCHA with CaptchaAI...
        return None

result = session.run_with_session("https://example.com", my_task)

دليل بيانات مستخدم Chrome (استمرارية الملف الشخصي بالكامل)

الثبات الأكثر اكتمالًا - يحفظ ملفات تعريف الارتباط والتخزين المحلي وذاكرة التخزين المؤقت والسجل وحالة المتصفح:

import os
from selenium import webdriver

PROFILE_DIR = os.path.abspath("./chrome-profiles/profile-1")


def create_persistent_driver():
    options = webdriver.ChromeOptions()
    options.add_argument(f"--user-data-dir={PROFILE_DIR}")
    options.add_argument("--profile-directory=Default")
    options.add_argument("--no-sandbox")
    return webdriver.Chrome(options=options)


# First run: builds fresh profile
driver = create_persistent_driver()
driver.get("https://example.com")
# ... solve CAPTCHA, login, etc.
driver.quit()

# Second run: same profile, cookies and state preserved
driver = create_persistent_driver()
driver.get("https://example.com")
# Often skips CAPTCHA because session is recognized
driver.quit()

فوائد دليل بيانات المستخدم

ما تم حفظه التأثير على اختبارات CAPTCHA
ملفات تعريف الارتباط رموز الجلسة والتفضيلات الصادرة من تطبيقك
localStorage رموز الثقة الخاصة بالموقع
مفهرسةDB reCAPTCHA الحالة الداخلية
ذاكرة التخزين المؤقت تحميل أسرع للصفحة
التاريخ إشارات نمط التصفح
عمال الخدمة الشيكات الخلفية CAPTCHA

Puppeteer السياق المستمر

const puppeteer = require("puppeteer");
const path = require("path");

const USER_DATA_DIR = path.resolve("./chrome-profiles/profile-1");

async function runWithPersistentProfile() {
  const browser = await puppeteer.launch({
    headless: false,
    userDataDir: USER_DATA_DIR,
    args: [
      "--no-sandbox",
      "--window-size=1920,1080",
    ],
  });

  const page = await browser.newPage();
  await page.goto("https://example.com", { waitUntil: "networkidle0" });

  // Check if session is active
  const isLoggedIn = await page.evaluate(() =>
    document.querySelector(".user-menu") !== null
  );

  if (isLoggedIn) {
    console.log("Session active — no CAPTCHA needed");
  } else {
    console.log("Session expired — solving CAPTCHA");
    // Solve with CaptchaAI...
  }

  await browser.close();
}

التخزين المحلي وتخزين الجلسة

def save_storage(driver, filepath):
    """Save localStorage and sessionStorage."""
    storage = driver.execute_script("""
        return {
            localStorage: Object.fromEntries(
                Object.entries(localStorage)
            ),
            sessionStorage: Object.fromEntries(
                Object.entries(sessionStorage)
            ),
        };
    """)

    with open(filepath, "w") as f:
        json.dump(storage, f, indent=2)


def restore_storage(driver, filepath):
    """Restore localStorage and sessionStorage."""
    if not os.path.exists(filepath):
        return

    with open(filepath) as f:
        storage = json.load(f)

    for key, value in storage.get("localStorage", {}).items():
        driver.execute_script(
            f"localStorage.setItem('{key}', '{value}')"
        )

    for key, value in storage.get("sessionStorage", {}).items():
        driver.execute_script(
            f"sessionStorage.setItem('{key}', '{value}')"
        )

تهيئة جلسة الاختبار داخل التطبيق المملوك

بدل استخدام صفحات خارجية أو محاكاة سلوك غير مرتبط بالموقع، جهّز الجلسة عبر خطوات تملكها أنت، مثل صفحة الصحة، وصفحة تسجيل الدخول الاختبارية، وصفحة المساعدة الداخلية. هذا يمنح الفريق حالة تشغيل معروفة وقابلة للتكرار.

import time


def prime_session(driver, owned_urls=None):
    """Load owned application pages to establish a known QA session state."""
    default_urls = [
        "https://staging.example.com/health",
        "https://staging.example.com/help",
        "https://staging.example.com/login",
    ]

    urls = owned_urls or default_urls

    for url in urls:
        driver.get(url)
        time.sleep(2)

    print(f"Prepared QA session with {len(urls)} owned pages")


driver = create_persistent_driver()
prime_session(driver)
driver.get("https://staging.example.com/form")

مدير جلسة متعدد الملفات الشخصية

import os
import json
import time
from datetime import datetime


class SessionManager:
    """Manage multiple persistent browser profiles."""

    def __init__(self, base_dir="./sessions"):
        self.base_dir = base_dir
        self.meta_file = os.path.join(base_dir, "profiles.json")
        os.makedirs(base_dir, exist_ok=True)

        if os.path.exists(self.meta_file):
            with open(self.meta_file) as f:
                self.profiles = json.load(f)
        else:
            self.profiles = {}

    def _save_meta(self):
        with open(self.meta_file, "w") as f:
            json.dump(self.profiles, f, indent=2)

    def get_profile_dir(self, name):
        return os.path.join(self.base_dir, f"profile-{name}")

    def create_profile(self, name, network_label=None):
        """Create a new browser profile."""
        profile_dir = self.get_profile_dir(name)
        os.makedirs(profile_dir, exist_ok=True)

        self.profiles[name] = {
            "created": datetime.now().isoformat(),
            "last_used": None,
            "use_count": 0,
            "network_label": network_label,
            "captcha_solves": 0,
        }
        self._save_meta()
        return profile_dir

    def get_least_used_profile(self):
        """Get the profile used least recently."""
        if not self.profiles:
            return None

        return min(
            self.profiles.items(),
            key=lambda x: x[1].get("last_used") or ""
        )[0]

    def record_use(self, name, solved_captcha=False):
        """Record profile usage."""
        if name in self.profiles:
            self.profiles[name]["last_used"] = datetime.now().isoformat()
            self.profiles[name]["use_count"] += 1
            if solved_captcha:
                self.profiles[name]["captcha_solves"] += 1
            self._save_meta()

    def get_stats(self):
        """Print profile statistics."""
        for name, meta in self.profiles.items():
            print(f"Profile: {name}")
            print(f"  Uses: {meta['use_count']}")
            print(f"  CAPTCHAs: {meta['captcha_solves']}")
            print(f"  Last used: {meta.get('last_used', 'never')}")
            print()


# Usage
manager = SessionManager()

# Create 5 rotating profiles
for i in range(5):
    manager.create_profile(f"worker-{i}")

# Get next profile to use
profile_name = manager.get_least_used_profile()
profile_dir = manager.get_profile_dir(profile_name)

# Use with Selenium
options = webdriver.ChromeOptions()
options.add_argument(f"--user-data-dir={os.path.abspath(profile_dir)}")
driver = webdriver.Chrome(options=options)

# After task
manager.record_use(profile_name, solved_captcha=True)
manager.get_stats()

دوران ملفات تعريف الارتباط وانتهاء الصلاحية

from datetime import datetime, timezone


def clean_expired_cookies(cookie_file):
    """Remove expired cookies from saved file."""
    if not os.path.exists(cookie_file):
        return

    with open(cookie_file) as f:
        cookies = json.load(f)

    now = datetime.now(timezone.utc).timestamp()
    valid = [c for c in cookies if c.get("expiry", float("inf")) > now]

    removed = len(cookies) - len(valid)
    if removed > 0:
        with open(cookie_file, "w") as f:
            json.dump(valid, f, indent=2)
        print(f"Removed {removed} expired cookies")


def merge_cookies(existing_file, new_cookies):
    """Merge new cookies with existing, preferring newer values."""
    existing = []
    if os.path.exists(existing_file):
        with open(existing_file) as f:
            existing = json.load(f)

    # Index by (name, domain)
    cookie_map = {}
    for c in existing:
        key = (c["name"], c.get("domain", ""))
        cookie_map[key] = c

    for c in new_cookies:
        key = (c["name"], c.get("domain", ""))
        cookie_map[key] = c  # Newer overwrites

    merged = list(cookie_map.values())
    with open(existing_file, "w") as f:
        json.dump(merged, f, indent=2)

    return len(merged)

استكشاف الأخطاء وإصلاحها

المشكلة السبب الإجراء
لا يتم تحميل ملفات تعريف الارتباط لم تنتقل إلى المجال أولاً اتصل بـ driver.get(url) قبل add_cookie
خطأ في قفل الملف الشخصي لم يتم إغلاق Chrome السابق قم بإنهاء عمليات Chrome، وإزالة SingletonLock
لا تزال الجلسة منتهية الصلاحية ملف تعريف الارتباط sameSite غير متطابق قم بإزالة sameSite قبل التحميل
تم حظر التخزين سياق CORS/security قم بتحميل التخزين بعد الانتقال إلى الأصل الصحيح
معدل CAPTCHA أعلى مع مرور الوقت تغيّر في بيئة الشبكة أو الجلسة راجع فصل الشبكة بين سيناريوهات QA وسجل تغييرات البيئة

الأسئلة الشائعة

ما المدة التي تستغرقها جلسات المتصفح في تقليل تكرار اختبار CAPTCHA؟

لا توجد مدة ثابتة تصلح لكل تطبيق. المقياس الصحيح هو عمر الجلسة داخل نظامك نفسه ومدة صلاحية ملفات تعريف الارتباط أو الرموز التي يصدرها تطبيقك أو بوابة الحماية التي تملكها.

هل يمكنني مشاركة الجلسات بين الأجهزة؟

نعم، إذا كان ذلك جزءًا من بنية الاختبار لديك. عند النقل بين الأجهزة، طابق إصدار المتصفح وإعدادات التطبيق والبيئة الزمنية حتى يبقى السيناريو قابلًا للمقارنة.

هل يعمل استمرار الجلسة مع Chrome مقطوعة الرأس؟

نعم. تعمل أدلة بيانات المستخدم وملفات تعريف الارتباط بشكل مماثل في وضع مقطوعة الرأس، لكن يجب اختبار ذلك داخل بيئتك لأن سلوك الصفحة قد يختلف حسب إطار التشغيل.

كم عدد الملفات الشخصية التي يجب أن أحتفظ بها؟

احتفظ بعدد محدود من الملفات الشخصية لكل سيناريو QA تحتاج إلى إعادة إنتاجه. ابدأ بعدد صغير، ثم زد فقط عندما يظهر احتياج تشخيصي واضح.

هل يستفيد CaptchaAI من ثبات الجلسة؟

بشكل غير مباشر — يؤدي استمرار الجلسة إلى تقليل تكرار اختبار CAPTCHA، مما يقلل عدد مكالمات CaptchaAI المطلوبة (توفير التكلفة). عندما تظهر اختبارات CAPTCHA، يقوم CaptchaAI بحلها كالمعتاد.


أدلة ذات صلة


إنشاء جلسات متصفح مستمرة تقلل من تحديات اختبار CAPTCHA —احصل على مفتاح CaptchaAI الخاص بكعندما لا تزال التحديات تظهر.

التعليقات غير مفعّلة لهذا المقال.

مقالات ذات صلة

Use Cases جمع البيانات البحثية الأكاديمية من المواقع المحمية بـ CAPTCHA
دليل عملي حول جمع البيانات البحثية الأكاديمية من المواقع المحمية بـ CAPTCHA يشرح السيناريوهات الواقعية ونمط التشغيل الآمن والخطوات التي تجعل هذا المسار قابلاً ل...

دليل عملي حول جمع البيانات البحثية الأكاديمية من المواقع المحمية بـ CAPTCHA يشرح السيناريوهات الواقعية ونمط ال...

Apr 16, 2026
Integrations عزل ملف تعريف المتصفح + تكامل CaptchaAI
عزل ملفات تعريف المتصفح عند دمج Captcha AI: فصل الجلسات، الحفاظ على ملفات تعريف الارتباط، وإدارة الحسابات المملوكة بصورة مستقرة داخل بيئات الاختبار والتشغيل الآ...

عزل ملفات تعريف المتصفح عند دمج Captcha AI: فصل الجلسات، الحفاظ على ملفات تعريف الارتباط، وإدارة الحسابات المم...

Apr 27, 2026
API Tutorials Bash + cURL + CaptchaAI: أتمتة CAPTCHA من سطر الأوامر
شرح خطوة بخطوة لـ Bash + c URL + Captcha AI: أتمتة CAPTCHA من سطر الأوامر مع أمثلة مباشرة قابلة لإعادة الاستخدام ومسار واضح لتطبيقه باستخدام Captcha AI.

شرح خطوة بخطوة لـ Bash + c URL + Captcha AI: أتمتة CAPTCHA من سطر الأوامر مع أمثلة مباشرة قابلة لإعادة الاستخد...

Apr 21, 2026