استخلاص HTML الأساسي: الخطوات الأولى

23 فبراير 2025

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

الفصل 1: Chad لاستخلاص HTML

تبدأ رحلتنا بأبسط سيناريو ممكن: استخراج نص من صفحة HTML أساسية. يعرّفك هذا الفصل بالمفاهيم الجوهرية التالية:

  • إجراء طلبات HTTP لجلب صفحات الويب
  • تحميل محتوى HTML إلى محلّل
  • اختيار عناصر DOM الأساسي باستخدام CSS selectors

ورغم أن المثال قد يبدو بسيطًا جدًا (فهو مجرد “hello world” في النهاية!)، فإنه يرسّخ الأساس لكل ما سيأتي لاحقًا.

<!-- Example HTML structure -->
<div class="content">
  <p>Some text we want to extract</p>
</div>

إليك لمحة عمّا سنعمل عليه:

// Basic concepts (not the solution!)
import * as cheerio from 'cheerio';

// Loading HTML content
const $ = cheerio.load(htmlContent);

// Using CSS selectors
const text = $('p').text();  // Selects all <p> tags
const specific = $('.content p').text();  // More specific selection

الفصل 2: البيانات المنظَّمة

تصبح الأمور أكثر تشويقًا عندما نتعمّق في صفحة منتج تجريبية لمتجر إلكتروني. هنا، نواجه عدة عناصر ذات بُنى متشابهة:

<!-- Example product structure (simplified) -->
<div class="product">
  <h2>Product Name</h2>
  <span class="price">$99.99</span>
  <div class="specs">
    <ul>
      <li>Size: M</li>
      <li>Color: Blue</li>
    </ul>
  </div>
</div>

عند التعامل مع بيانات منظَّمة كهذه، من المفيد أن تفكّر في التالي:

// Conceptual approach (not the solution!)
$('.product').each((index, element) => {
  // For each product, we might want to:
  // 1. Extract the basic info
  const name = $(element).find('h2').text();

  // 2. Parse nested data
  const specs = $(element).find('.specs li');

  // 3. Structure the output
  const data = {
    name,
    specs: specs.map(/* ... */),
  };
});

نصيحة احترافية: قبل كتابة أي سطر من الكود، خصّص وقتًا لتحليل بنية HTML. ابحث عن الأنماط في كيفية تنظيم البيانات — هل توجد أسماء class متّسقة؟ وكيف ترتبط العناصر الأب بالعناصر الابنة؟

الفصل 3: الاستخلاص بمساعدة الذكاء الاصطناعي

الآن تبدأ الأمور الممتعة فعلًا! بينما علّمتنا التحديات السابقة تقنيات الاستخلاص التقليدية، يقدّم الفصل 3 نهجًا حديثًا: Web Scraping بمساعدة الذكاء الاصطناعي. نحن هنا أمام سيناريو كابوسي — بُنى HTML غير متّسقة، وأسماء class مبهمة، وأنماط متعددة من الأُطر البرمجية ممزوجة معًا.

لنلقِ نظرة على ما يجعل هذا التحدي مميزًا:

<!-- Traditional product structure -->
<div data-testid="product-container-1" class="_3xj_item">
  <h2 data-qa="name">Red Sneakers</h2>
  <span data-price-current="5999">$59.99</span>
</div>

<!-- React-style component -->
<div class="ProductCard-root-1a2b3c">
  <div class="ProductCard-title-4d5e6f">Pink Walking Shoes</div>
  <div class="ProductCard-pricing-7g8h9i">$84.99</div>
</div>

<!-- Vue-style template -->
<div data-v-abcdef class="product">
  <h2 data-v-abcdef>Navy Boat Shoes</h2>
  <span data-v-abcdef>$79.99</span>
</div>

ستواجه أساليب الاستخلاص التقليدية صعوبة هنا للأسباب التالية:

  • أسماء class عشوائية أو خاصة بإطار عمل معيّن
  • تختلف هياكل البيانات من منتج إلى آخر
  • تستخدم الأُطر المختلفة أنماطًا مختلفة
  • يضيع المعنى الدلالي داخل الـ markup

وهنا يأتي دور الذكاء الاصطناعي. فبدلًا من كتابة selectors هشّة، يمكننا وصف ما نريده بلغة طبيعية وترك مهمة مطابقة الأنماط للذكاء الاصطناعي. وتشمل المفاهيم الأساسية في هذا الفصل ما يلي:

  • Prompt engineering لأغراض Web Scraping
  • استخدام الذكاء الاصطناعي لفهم المعنى الدلالي
  • التعامل مع هياكل البيانات غير المتّسقة
  • التعامل مع markup الخاصة بأُطر العمل المختلفة
  • الحفاظ على اتساق البيانات عبر الأنماط المختلفة

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

ملاحظة حول استخدام الذكاء الاصطناعي

تذكّر أن الاستعانة بالذكاء الاصطناعي لا تعني حلولًا مؤتمتة بالكامل. أفضل النتائج تأتي من الجمع بين:

  • تعريف واضح للمشكلة
  • prompts منظَّمة جيدًا
  • التحقق من صحة البيانات
  • إشراف بشري

وسيكون تحديك هو صياغة prompts تساعد الذكاء الاصطناعي على فهم كلٍّ من البنية والمقصد لما تحاول استخلاصه.

هل أنت مستعد للجمع بين معرفة Web Scraping التقليدية وقدرات الذكاء الاصطناعي الحديثة؟ لنكتشف كيف يمكن للذكاء الاصطناعي أن يساعد في التعامل حتى مع أكثر صفحات HTML فوضوية!

تلميحات

  1. جرّب CSS selectors مختلفة:
// Different ways to select elements
$('.class')           // By class
$('#id')             // By ID
$('div > p')         // Direct children
$('div p')           // All descendants
$('[data-type="x"]') // By attribute
  1. جرّب تعديل صيغة الإخراج
  2. فكّر في معالجة الأخطاء والحالات الطرفية
  3. فكّر في كيفية توسّع الحل الخاص بك عند التعامل مع مجموعات بيانات أكبر

كل الكود الذي تحتاجه للبدء موجود في مستودع المشروع. انسخه، وأعِد إعداد بيئتك، وابدأ الاستخلاص!

git clone https://github.com/jonaylor89/housefly.git
cd housefly
npm install

شغّل خوادم الفصول محليًا — يعمل كل فصل على منفذه الخاص (3001–3011):

turbo dev

ثم عدّل scraper الخاص بك في exercises/chapter-NN/starter/src/index.ts وتحقّق منه:

npm run validate -- <chapter>

هل تبحث عن تلميحات؟ شغّل npm run hint -- <chapter> للحصول على إرشاد تدريجي. يتوفر HTML المصدر لكل تحدٍّ في الدليل apps/chapter{n}/، بينما توجد الحلول المرجعية في exercises/chapter-NN/solution/src/. ادرس البنية، وخطّط لنهجك، وتذكّر — كل خبير كان يومًا ما مبتدئًا.

تذكّر أن تتعامل مع طلباتك بمسؤولية:

// Basic error handling example
async function fetchPage(url: string) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.text();
  } catch (error) {
    console.error('Failed to fetch page:', error);
    throw error;
  }
}

استخلاصًا سعيدًا!