استخدام Selenium لبناء بوت Web Scraping احترافي

دقائق القراءة: 8

مقدمة إلى Selenium وأهميته في Web Scraping

تُعد Selenium من أقوى الأدوات المستخدمة في أتمتة المتصفحات، إذ يمكن الاعتماد عليها في اختبار واجهات المستخدم، وتنفيذ مهام التفاعل مع صفحات الويب، وكذلك بناء أدوات Web Scraping القادرة على جمع البيانات من المواقع التي تعتمد على التفاعل الديناميكي. وتبرز فائدتها بشكل خاص عندما لا تكفي المكتبات التقليدية في التعامل مع الصفحات التي تُحمّل محتواها عبر JavaScript.

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

واجهة توضيحية لأداة Selenium المستخدمة في أتمتة المتصفح وبناء بوت Web Scraping بلغة Python

ما الذي يمكن إنجازه باستخدام Selenium؟

تسمح لك Selenium بتنفيذ مجموعة واسعة من المهام داخل المتصفح، مثل:

  • فتح الصفحات والتنقل بينها آلياً.
  • النقر على الأزرار والروابط.
  • ملء النماذج وإرسال البيانات.
  • انتظار ظهور عناصر أو تغيّر نصوص معيّنة.
  • استخراج البيانات من المواقع الديناميكية.
  • اختبار سلوك واجهات المستخدم في المشاريع البرمجية.

ولهذا السبب، تُعد خياراً ممتازاً لمن يريد الجمع بين Automation وWeb Scraping في مشروع واحد.

المتطلبات الأساسية قبل البدء

قبل كتابة أي سطر برمجي، من الضروري التأكد من جاهزية البيئة البرمجية لديك. ستحتاج إلى:

  • تثبيت Python على جهازك.
  • وجود محرر أكواد أو IDE مثل PyCharm أو Sublime Text أو VS Code.
  • مدير الحزم pip لتثبيت المكتبات.
  • تنزيل ChromeDriver المتوافق مع إصدار متصفح Chrome.

تثبيت Selenium في Python

لبدء استخدام المكتبة، يمكنك تثبيتها عبر الأمر التالي:

pip install selenium

بعد التثبيت، يمكنك استيراد WebDriver والبدء بإنشاء جلسة تشغيل للمتصفح.

from selenium import webdriver

تشغيل متصفح Chrome باستخدام Selenium

عند العمل على أتمتة المتصفح، تحتاج إلى استخدام برنامج تشغيل خاص بالمتصفح المستهدف. في حالة Chrome، ستحتاج إلى ChromeDriver، وهو ملف تنفيذي تستخدمه Selenium لتنفيذ الأوامر داخل المتصفح.

driver = webdriver.Chrome()

كما يمكن العمل مع متصفحات أخرى مثل Firefox وEdge، لكن كثيراً من المشاريع التعليمية تبدأ مع Chrome لسهولة انتشاره.

تنزيل ChromeDriver بالطريقة الصحيحة

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

بعد التنزيل، فك ضغط الملف وانقله إلى مجلد واضح داخل جهازك، مثل:

C:\selenium drivers

إضافة ChromeDriver إلى PATH برمجياً

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

import os
os.environ['PATH'] += r"C:\selenium drivers"

بعدها يمكنك تشغيل المتصفح بشكل طبيعي عبر Selenium.

فتح صفحة ويب والبدء بأول عملية أتمتة

أول خطوة عملية هي فتح صفحة ويب باستخدام الدالة get:

driver.get("https://example.com")

بعد ذلك، يمكنك البحث عن عنصر معين في الصفحة، مثل زر، والضغط عليه باستخدام المعرف ID:

my_element = driver.find_element_by_id("downloadButton")
my_element.click()

فهم طرق تحديد العناصر داخل الصفحة

نجاح أي مشروع يعتمد على Selenium يرتبط بشكل مباشر بقدرتك على تحديد العناصر بدقة. ومن أشهر الطرق:

  • ID: الأفضل عندما يكون فريداً.
  • Class Name: مناسب عند وجود فئة واضحة للعناصر.
  • CSS Selector: الأكثر مرونة وقوة.
  • Name: مفيد لبعض الحقول والنماذج.

كل صفحة ويب تمتلك بنية HTML مختلفة، لذلك يجب دائماً فحص العناصر باستخدام أداة Inspect داخل المتصفح قبل كتابة الأوامر البرمجية.

الفرق بين Implicit Wait و Explicit Wait

استخدام Implicit Wait

عند تنفيذ الأوامر بسرعة كبيرة، قد تحاول Selenium الوصول إلى عنصر لم يكتمل تحميله بعد. هنا تظهر أهمية Implicit Wait:

driver.implicitly_wait(3)

هذا الانتظار لا يعني أن البرنامج سيتوقف دائماً 3 ثوانٍ، بل ينتظر فقط حتى يصبح العنصر متاحاً أو تنتهي المدة المحددة.

استخدام Explicit Wait

أما Explicit Wait فهو أكثر دقة، لأنه ينتظر تحقق شرط محدد، مثل تغيّر نص عنصر أو ظهور زر معين:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

WebDriverWait(driver, 30).until(
    EC.text_to_be_present_in_element(
        (By.CLASS_NAME, "progress-label"),
        "Complete!"
    )
)

هذا النوع مناسب جداً عندما تريد أن يتفاعل البرنامج مع حدث واضح، بدلاً من الانتظار العام.

إرسال البيانات إلى النماذج باستخدام send_keys

من الاستخدامات العملية الشائعة لـ Selenium إدخال البيانات داخل النماذج. ويمكن تنفيذ ذلك من خلال send_keys:

sum1 = driver.find_element_by_id("sum1")
sum2 = driver.find_element_by_id("sum2")

sum1.send_keys(15)
sum2.send_keys(15)

بعد إدخال القيم، يمكنك الضغط على زر الإرسال أو الحساب لاستكمال العملية.

التعامل مع مفاتيح لوحة المفاتيح

لا يقتصر send_keys على النصوص فقط، بل يمكنك إرسال مفاتيح من لوحة المفاتيح مثل Enter وShift وCtrl وغيرها:

from selenium.webdriver.common.keys import Keys

sum1.send_keys(Keys.NUMPAD1, Keys.NUMPAD5)

يفيد ذلك في السيناريوهات التي تتطلب محاكاة سلوك المستخدم الحقيقي بصورة أدق.

استخدام CSS Selector بمرونة أكبر

عندما لا يكون ID أو Class Name كافيين، يصبح CSS Selector الخيار الأقوى. فهو يتيح لك تحديد العناصر عبر نوع الوسم أو الخصائص أو حتى أجزاء من القيم.

button = driver.find_element_by_css_selector('button[onclick="return total()"]')
button.click()

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

بناء مشروع بوت عملي لاستخراج العروض

بعد فهم الأساسيات، يمكن الانتقال إلى بناء مشروع منظم لا يعتمد على ملف واحد فقط، بل على هيكل واضح يسهل تطويره لاحقاً.

هيكل المشروع المقترح

  • run.py: نقطة التشغيل الرئيسية.
  • booking/booking.py: الكلاس الأساسي للبوت.
  • booking/constants.py: الثوابت العامة.
  • booking/booking_filtration.py: منطق الفلاتر.
  • booking/booking_report.py: تجهيز التقارير والنتائج.

هذا التقسيم يجعل الكود أوضح وأسهل للصيانة، خاصة عند توسعة المشروع مستقبلاً.

إنشاء كلاس مخصص يرث من WebDriver

يمكنك تصميم كلاس خاص بالمشروع يرث من webdriver.Chrome، وبذلك تحصل على جميع وظائف Selenium مع إمكانية إضافة دوال مخصصة للموقع المستهدف.

from selenium import webdriver
import os

class Booking(webdriver.Chrome):
    def __init__(self, driver_path=r"C:\selenium drivers", teardown=False):
        self.driver_path = driver_path
        self.teardown = teardown
        os.environ['PATH'] += self.driver_path
        super(Booking, self).__init__()
        self.implicitly_wait(15)
        self.maximize_window()

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.teardown:
            self.quit()

هذه البنية تمنحك تحكماً أفضل في دورة حياة المتصفح، وتساعدك على كتابة أوامر أكثر تنظيماً.

التعامل مع الصفحة الرئيسية لموقع الحجز

يمكن للبوت أن يبدأ بزيارة الصفحة الرئيسية لموقع الحجز، ثم تنفيذ سلسلة من الخطوات مثل:

  1. تغيير العملة.
  2. إدخال الوجهة.
  3. اختيار تاريخ الوصول والمغادرة.
  4. تحديد عدد البالغين.
  5. الضغط على زر البحث.

تغيير العملة

يمكن تنفيذ تغيير العملة عبر استهداف زر اختيار العملة ثم اختيار قيمة محددة مثل USD باستخدام CSS Selector يعتمد على خصائص العنصر.

اختيار الوجهة

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

اختيار التواريخ

يمكن الاعتماد على الخاصية data-date لاختيار تاريخ الدخول والخروج بشكل مباشر من التقويم.

تحديد عدد البالغين

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

تنفيذ البحث وتطبيق الفلاتر

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

  • عدد النجوم.
  • الترتيب حسب السعر الأقل.
  • أي معايير إضافية حسب هيكل الصفحة.

من الأفضل عزل هذه المسؤوليات داخل كلاس مستقل مثل BookingFiltration حتى لا يصبح الكلاس الرئيسي مزدحماً بالدوال.

مثال على فلترة عدد النجوم

يمكن قراءة عناصر الفلترة الخاصة بالنجوم، ثم النقر على الخيارات المطابقة مثل 3 أو 4 أو 5 نجوم، حسب ما يحدده المستخدم.

الترتيب حسب أقل سعر

كما يمكن للبوت الضغط على خيار Price (lowest first) للحصول على العروض الأرخص في أعلى النتائج.

تشغيل المشروع من Command Line

في المشاريع العملية، من المفيد جداً تشغيل البوت من Command Line بدلاً من الاعتماد على IDE فقط. لكن قد تظهر مشكلة شائعة تتعلق بعدم تعرف النظام على ChromeDriver.

لهذا يمكن استخدام try/except لطباعة رسالة واضحة للمستخدم عند تشغيل المشروع من الطرفية بدون إعداد PATH بشكل صحيح.

هذا يجعل المشروع أكثر ملاءمة للاستخدام العملي، سواء على جهازك المحلي أو على خادم أو بيئة عمل مختلفة.

استخراج النتائج من صفحة العروض

بعد نجاح البحث وتطبيق الفلاتر، تبدأ مرحلة Web Scraping الحقيقية: قراءة بيانات الفنادق المعروضة واستخراج العناصر المهمة منها.

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

بعد ذلك، يمكن استخراج:

  • اسم الفندق.
  • السعر.
  • التقييم.

تنظيم البيانات داخل كلاس مخصص للتقارير

لتحسين بنية المشروع، يُفضّل إنشاء كلاس مثل BookingReport تكون مهمته قراءة الصناديق واستخراج السمات المهمة من كل نتيجة.

ومن الأفضل تخزين البيانات داخل قائمة منظّمة من القوائم، بحيث يحتوي كل صف على اسم الفندق وسعره وتقييمه.

عرض النتائج داخل جدول مرتب

بدلاً من طباعة النتائج بشكل عشوائي، يمكن استخدام مكتبة PrettyTable لعرض البيانات في جدول واضح وسهل القراءة.

pip install prettytable
from prettytable import PrettyTable

table = PrettyTable(field_names=["Hotel Name", "Price", "Score"])
table.add_rows(collection)
print(table)

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

جعل البوت أكثر ديناميكية عبر input

لزيادة مرونة البرنامج، يمكن استبدال القيم الثابتة مثل المدينة والتواريخ وعدد الأشخاص بمدخلات يكتبها المستخدم عند التشغيل:

place = input("Where do you want to go? ")
check_in = input("What is the check in date? ")
check_out = input("What is the check out date? ")
adults = int(input("How many people? "))

هذا يجعل البوت قابلاً لإعادة الاستخدام دون الحاجة إلى تعديل الكود في كل مرة.

أفضل الممارسات عند بناء بوت Web Scraping باستخدام Selenium

  • لا ترسل عدداً كبيراً من الطلبات أو العمليات المتكررة بسرعة مبالغ فيها.
  • احترم سياسات المواقع المستهدفة وشروط الاستخدام.
  • اعتمد على انتظار ذكي بدلاً من التأخير العشوائي.
  • قسّم المشروع إلى Classes وModules واضحة.
  • فضّل استخدام CSS Selector عندما تكون بنية الصفحة معقدة.
  • اختبر الكود على مراحل صغيرة لتسهيل اكتشاف الأخطاء.

متى يكون Selenium هو الخيار المناسب؟

يكون Selenium مناسباً عندما تحتاج إلى:

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

أما إذا كانت البيانات متاحة مباشرة عبر API أو داخل HTML ثابت، فقد تكون أدوات أخف مثل requests وBeautifulSoup أكثر كفاءة.

الخلاصة التقنية

يُظهر هذا المشروع أن Selenium ليس مجرد أداة لاختبار الواجهات، بل إطار عملي قوي لبناء أنظمة Web Scraping متقدمة تعتمد على التفاعل الحقيقي مع صفحات الويب. ومن الناحية التقنية، فإن الجمع بين WebDriver وExplicit Wait وCSS Selector وتنظيم المشروع بأسلوب Object-Oriented يمنحك أساساً ممتازاً لبناء بوتات قابلة للتطوير والصيانة. وإذا أضفت إلى ذلك طبقة تقارير منظمة مثل PrettyTable، فستحصل على مشروع عملي يجمع بين التعلم والفائدة وقابلية التطبيق الفعلي.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *