0Pricing
AI Agents · درس

التعامل مع ترقيم الصفحات والمحتوى الديناميكي

اتباع روابط الصفحة التالية واستخدام Playwright للصفحات المُنشأة بواسطة JavaScript

التعامل مع ترقيم الصفحات والمحتوى الديناميكي درس مجاني في AI Agents على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Agents، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Agents 4 دروس في المجموع.

مشكلة ترقيم الصفحات

معظم مواقع الويب الحقيقية لا تعرض جميع بياناتها في صفحة واحدة. تُقسَّم النتائج على عدة صفحات لتقليل الحمل. يجب على الوكيل اكتشاف ترقيم الصفحات واتباعه لجمع مجموعات البيانات كاملة.

هناك نمطان شائعان لترقيم الصفحات: روابط الصفحة التالية وأنماط عناوين URL لأرقام الصفحات.

اكتشاف روابط الصفحة التالية

تحتوي مواقع كثيرة على زر «التالي» أو رابط على شكل سهم. اعثروا على وسم الرابط الذي يحتوي على rel='next' أو على نص مثل «التالي»، واستخرجوا قيمة href منه، ثم اتبعوه داخل حلقة حتى لا يعود موجودًا.

from bs4 import BeautifulSoup
import httpx

def scrape_all_pages(start_url: str) -> list:
    results = []
    url = start_url

    while url:
        response = httpx.get(url, timeout=10.0)
        soup = BeautifulSoup(response.text, 'html.parser')

        # Collect data from this page
        for item in soup.select('.result-item'):
            results.append(item.text.strip())

        # Find the next page link
        next_link = soup.find('a', rel='next') or soup.find('a', string='Next')
        url = next_link.get('href') if next_link else None

    return results

أنماط عناوين URL لأرقام الصفحات

تستخدم كثير من واجهات API والمواقع أنماطًا متوقعة لعناوين URL: /results?page=1 و/results?page=2 وغير ذلك. يمكن للوكيل التكرار عليها مباشرةً من دون تحليل DOM للبحث عن رابط الصفحة التالية.

import httpx

def scrape_paginated_api(base_url: str, max_pages: int = 10) -> list:
    all_items = []

    for page in range(1, max_pages + 1):
        response = httpx.get(
            base_url,
            params={'page': page, 'per_page': 50},
            timeout=10.0
        )
        response.raise_for_status()
        data = response.json()

        items = data.get('results', [])
        if not items:
            break  # No more data

        all_items.extend(items)
        print(f'Page {page}: fetched {len(items)} items')

    return all_items

ترقيم الصفحات القائم على المؤشر

تستخدم واجهات API الحديثة مثل GitHub وSlack وTwitter ترقيم الصفحات القائم على المؤشر. تتضمن كل استجابة رمز مؤشر للصفحة التالية. مرّروا المؤشر في الطلب التالي حتى يغيب أو تصبح قيمته null.

import httpx

def fetch_with_cursor(url: str, headers: dict) -> list:
    all_data = []
    cursor = None

    while True:
        params = {'cursor': cursor} if cursor else {}
        response = httpx.get(url, headers=headers, params=params, timeout=10.0)
        response.raise_for_status()
        data = response.json()

        all_data.extend(data.get('items', []))

        cursor = data.get('next_cursor')  # None when done
        if not cursor:
            break

    return all_data

المحتوى الثابت مقابل الديناميكي

تُحمّل بعض الصفحات المحتوى باستخدام JavaScript بعد تسليم HTML الأولي. لا يتلقى عميل HTTP العادي سوى القشرة الفارغة، إذ تُحقن البيانات الفعلية بواسطة JS في المتصفح.

بالنسبة إلى هذه الصفحات، تشغّل أدوات مثل Playwright محرك متصفح حقيقي وتنتظر تنفيذ JavaScript قبل استخراج المحتوى.

تثبيت Playwright واستيراده

ثبّتوا Playwright باستخدام pip install playwright، ثم شغّلوا playwright install chromium لتنزيل المتصفح. استخدموا async_playwright() في مسارات عمل الوكلاء غير المتزامنة.

# Installation (run in terminal):
# pip install playwright
# playwright install chromium

from playwright.async_api import async_playwright
import asyncio

async def fetch_dynamic(url: str) -> str:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(url)
        html = await page.content()  # Full rendered HTML
        await browser.close()
    return html

# html = asyncio.run(fetch_dynamic('https://example.com'))

انتظار تحميل المحتوى الديناميكي

غالبًا ما تحمّل صفحات JavaScript البيانات بشكل غير متزامن. اطلبوا من Playwright الانتظار حتى يظهر عنصر محدد قبل استخراج المحتوى، لضمان وجود البيانات التي تحتاجون إليها فعلًا في DOM.

from playwright.async_api import async_playwright

async def scrape_dynamic_table(url: str) -> list:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(url)

        # Wait for the table to appear in the DOM
        await page.wait_for_selector('table.results', timeout=10000)

        html = await page.content()
        await browser.close()

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'html.parser')
    return [td.text for td in soup.select('table.results td')]

النقر والتفاعل مع الصفحات

يمكن لـPlaywright محاكاة تفاعلات المستخدم، مثل النقر وملء النماذج والتمرير وإدخال لوحة المفاتيح. يتيح ذلك للوكيل التنقل عبر عمليات تسجيل الدخول والقوائم المنسدلة وصفحات التمرير اللانهائي.

from playwright.async_api import async_playwright

async def click_load_more(url: str) -> str:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(url)

        # Click the 'Load More' button
        load_more = page.locator('button:text("Load More")')
        if await load_more.count() > 0:
            await load_more.click()
            await page.wait_for_timeout(2000)  # wait 2s for content

        html = await page.content()
        await browser.close()
    return html

التعامل مع التمرير اللانهائي

تحمّل بعض المواقع مزيدًا من المحتوى أثناء التمرير إلى الأسفل. يمكن لـPlaywright محاكاة التمرير لتحفيز عمليات التحميل هذه. كرّروا التمرير وتحققوا في كل مرة مما إذا كان محتوى جديد قد ظهر.

from playwright.async_api import async_playwright

async def scrape_infinite_scroll(url: str, scroll_count: int = 5) -> str:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(url)

        for _ in range(scroll_count):
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
            await page.wait_for_timeout(1500)  # wait for new content

        html = await page.content()
        await browser.close()
    return html

الجمع بين Playwright وBeautifulSoup

بعد أن يعرض Playwright الصفحة ويعيد HTML الكامل، مرّروه إلى BeautifulSoup لتسهيل استخراج البيانات. يجمع ذلك بين نقاط قوة المكتبتين.

from playwright.async_api import async_playwright
from bs4 import BeautifulSoup

async def extract_js_rendered_data(url: str) -> list:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(url)
        await page.wait_for_selector('.product-card')
        html = await page.content()
        await browser.close()

    soup = BeautifulSoup(html, 'html.parser')
    products = []
    for card in soup.select('.product-card'):
        products.append({
            'name': card.select_one('.name').text.strip(),
            'price': card.select_one('.price').text.strip()
        })
    return products

اختيار الأداة المناسبة

لا تحتاج كل صفحة إلى Playwright. استخدموا أبسط نهج ينجح:

  • HTML ثابت: httpx + BeautifulSoup (سريع، ومن دون تكلفة تشغيل متصفح)
  • واجهة JSON برمجية مع ترقيم الصفحات: httpx مع معاملات الصفحة/المؤشر
  • محتوى معروض بواسطة JS: Playwright async (أبطأ، لكنه أكثر قوة)

ابدؤوا دائمًا بالنهج الثابت، ولا تلجؤوا إلى Playwright إلا عند الحاجة.

اختبار المعرفة: ترقيم الصفحات والمحتوى الديناميكي

اختبروا فهمكم للتعامل مع ترقيم الصفحات والمحتوى الديناميكي.

مراجعة: ترقيم الصفحات والمحتوى الديناميكي

أصبح بإمكان وكلائكم الآن التعامل مع مختلف أشكال محتوى الويب:

  • اتباع روابط الصفحة التالية أو التكرار عبر معاملات الصفحة في عناوين URL
  • استخدام رموز المؤشر لترقيم الصفحات في واجهات API الحديثة
  • استخدام async_playwright() للصفحات المعروضة بواسطة JavaScript
  • انتظار العناصر باستخدام page.wait_for_selector()
  • الجمع بين Playwright وBeautifulSoup لتسهيل استخراج البيانات

ابدؤوا دائمًا بأبسط نهج، وانتقلوا إلى Playwright فقط عندما لا يكفي النهج الثابت.

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

هل درس «التعامل مع ترقيم الصفحات والمحتوى الديناميكي» مجاني؟

نعم — نص درس «التعامل مع ترقيم الصفحات والمحتوى الديناميكي» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Agents، انتقل إلى CoddyKit PRO. تتضمن دورة AI Agents 4 دروس في المجموع.

ماذا ستتعلم في «التعامل مع ترقيم الصفحات والمحتوى الديناميكي»؟

اتباع روابط الصفحة التالية واستخدام Playwright للصفحات المُنشأة بواسطة JavaScript تتمرن على AI Agents مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Agents؟

لا تُشترط خبرة سابقة. AI Agents على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «التعامل مع ترقيم الصفحات والمحتوى الديناميكي»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Agents هذا؟

نعم. كل درس في AI Agents يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. عملاء HTTP للوكلاء: httpx وrequests
  2. تحليل HTML باستخدام BeautifulSoup
  3. التعامل مع ترقيم الصفحات والمحتوى الديناميكي
  4. ممارسات الاستخلاص المسؤولة
← العودة إلى AI Agents