المحتوى المُعرَض باستخدام JavaScript

8 مارس 2025

نادرًا ما تُرسِل تطبيقات الويب الحديثة HTML كاملًا؛ وبدلًا من ذلك، يُحمَّل المحتوى ويُعرَض ديناميكيًا عبر JavaScript. وهذا يطرح تحديات خاصة في كشط الويب سنتعامل معها في هذين الفصلين.

الفصل 4: موجز أخبار ديناميكي

يتضمن أول تحدٍّ لدينا كشط موجز أخبار حيث تُحمَّل المقالات ديناميكيًا عبر JavaScript. ويُقدِّم هذا عدة مفاهيم أساسية:

  • أتمتة المتصفح باستخدام Playwright
  • انتظار تحميل المحتوى الديناميكي
  • التعامل مع عناصر DOM التي تُعرَض عبر JavaScript

تبدو بنية الصفحة على نحوٍ مماثل لما يلي:

<div class="news-feed">
  <article class="news-item">
    <h2>Breaking News Title</h2>
    <p>Article content...</p>
    <div class="meta">
      <span>By Author Name</span>
      <time datetime="2024-03-08T12:00:00Z">March 8, 2024</time>
    </div>
  </article>
  <!-- More articles load dynamically -->
</div>

الاختلافات الأساسية مقارنةً بكشط HTML الثابت:

// Instead of cheerio.load(), we use Playwright
const browser = await chromium.launch();
const page = await browser.newPage();

// Wait for content to render
await page.waitForSelector('.news-item');

// Extract data from the live DOM using page.$$eval()
// This runs the callback function in the browser context
// to evaluate all elements matching the selector at once
const items = await page.$$eval('.news-item', elements => {
  // Works like Array.map() on matching elements
  // Returns serializable JavaScript objects
  // Perfect for extracting data from multiple elements
});

الفصل 5: معرض صور بتمرير لا نهائي

استنادًا إلى ما تعلمناه عن المحتوى الديناميكي، ننتقل إلى سيناريو أكثر تعقيدًا: معرض صور بتمرير لا نهائي. ويُقدِّم هذا ما يلي:

  • التعامل مع المحتوى الذي يُحمَّل بطريقة lazy-loaded
  • اكتشاف أحداث التمرير وتحفيزها
  • إدارة حالات التحميل غير المتزامن
  • استخراج البيانات من أنماط واجهة مستخدم معقدة

يكمن التحدي هنا في أن المحتوى يُحمَّل تدريجيًا مع تمرير المستخدم:

<div class="photo-gallery">
  <div class="photo-card">
    <img src="..." alt="Photo title" />
    <h2>Photo Title</h2>
    <p>By Photographer Name</p>
    <div class="flex">
      <span>❤️ 42</span>
    </div>
  </div>
  <!-- More photos load on scroll -->
</div>

المفاهيم الأساسية للتعامل مع التمرير اللانهائي:

// Scroll to bottom until no new content loads
let previousHeight;
while (true) {
  previousHeight = await page.evaluate('document.body.scrollHeight');
  await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
  await page.waitForTimeout(1500); // Wait for content

  const newHeight = await page.evaluate('document.body.scrollHeight');
  if (newHeight === previousHeight) {
    break; // No more content to load
  }
}

اعتبارات مهمة

عند العمل مع المحتوى المعروض عبر JavaScript:

  1. الأداء: يكون كشط المحتوى الديناميكي أبطأ من HTML الثابت
  2. إدارة الموارد: تستهلك أتمتة المتصفح موارد نظام أكثر
  3. الاستقرار: تحتاج إلى التعامل مع حالات التحميل وظروف الشبكة
  4. تحديد المعدل: فكّر في تطبيق فواصل زمنية بين الإجراءات

أفضل الممارسات

  1. استخدم استراتيجيات انتظار مناسبة:
// Wait for specific elements
await page.waitForSelector('.selector');

// Wait for network idle
await page.waitForLoadState('networkidle');

// Custom wait conditions
await page.waitForFunction(() => {
  // Custom JavaScript condition
});
  1. نفّذ معالجة قوية للأخطاء:
try {
  await page.goto(url);
  // ... scraping logic
} catch (error) {
  console.error('Scraping failed:', error);
} finally {
  await browser.close(); // Always clean up
}
  1. فكّر في تنفيذ آليات إعادة المحاولة لتحسين الاعتمادية
  2. راقب استخدام الذاكرة عند التعامل مع مجموعات بيانات كبيرة
  3. تحقّق من صحة البيانات المستخرجة لضمان الاتساق

اختبار الحل الخاص بك

توفّر بيئة الاختبار واجهات API وهمية تحاكي ظروف العالم الحقيقي:

  • أزمنة تحميل متغيرة
  • كمون الشبكة
  • آليات الترقيم إلى صفحات
  • حالات الخطأ

جرّب هذه التنويعات:

  1. عدّل توقيت التمرير
  2. تعامل مع أحجام شاشات مختلفة
  3. اختبر في ظل ظروف شبكة بطيئة
  4. تحقّق من سلامة البيانات

هل أنت مستعد للتعامل مع المحتوى الديناميكي؟ ستجد كود التحدي وبيئات الاختبار في المستودع.

اطّلع على الحلول المرجعية في exercises/chapter-04/solution/src/ و exercises/chapter-05/solution/src/ للاطلاع على تطبيقات عاملة. وتذكّر: إن كشط الويب الحديث يتمحور حول فهم كلٍّ من بنية HTML وسلوك التطبيق.

كشطًا موفقًا!