أتمتة تصفح الويب باستخدام Selenium وPython: دليل شامل

Amine
03/12/2024

أتمتة تصفح الويب باستخدام Selenium و بايثون

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

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

المتطلبات الأساسية

قبل البدء، نحتاج إلى تجهيز بيئة العمل بتثبيت المكتبات اللازمة. سنستخدم مكتبة Selenium الأساسية للتحكم بالمتصفح، ومكتبة webdriver-manager التي تساعدنا في إدارة وتحديث متصفح Chrome driver تلقائياً، مما يوفر علينا عناء التحديث اليدوي كلما صدر إصدار جديد من المتصفح.

pip install selenium
pip install webdriver-manager

إعداد Selenium

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

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager

def setup_driver():
    # إعداد خيارات المتصفح
    chrome_options = Options()
    chrome_options.add_argument("--start-maximized")
    
    # تثبيت وإعداد المتصفح
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service, options=chrome_options)
    return driver

دعونا نشرح كل جزء من الكود السابق:

نبدأ باستيراد المكتبات الضرورية: webdriver للتحكم بالمتصفح، Service و Options لإعداد المتصفح، By للعثور على العناصر في الصفحة، WebDriverWait و expected_conditions للانتظار الذكي، وأخيراً ChromeDriverManager لإدارة متصفح Chrome.

في دالة setup_driver، نقوم أولاً بإنشاء كائن Options ونضيف خيار “–start-maximized” الذي يجعل نافذة المتصفح تفتح بالحجم الكامل. ثم نستخدم ChromeDriverManager().install() للحصول على أحدث نسخة متوافقة من Chrome driver وإعداد service به. أخيراً، ننشئ متصفح Chrome مع الإعدادات المحددة ونعيده من الدالة.

مثال 1: تسجيل الدخول إلى موقع

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

def login_to_website(driver, username, password):
    try:
        # فتح صفحة تسجيل الدخول
        driver.get("https://example.com/login")
        
        # انتظار ظهور حقل اسم المستخدم
        username_field = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "username"))
        )
        
        # إدخال بيانات تسجيل الدخول
        username_field.send_keys(username)
        driver.find_element(By.ID, "password").send_keys(password)
        
        # النقر على زر تسجيل الدخول
        driver.find_element(By.ID, "login-button").click()
        
        # التحقق من نجاح تسجيل الدخول
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "dashboard"))
        )
        print("تم تسجيل الدخول بنجاح!")
        
    except Exception as e:
        print(f"حدث خطأ: {str(e)}")

لنشرح كيف يعمل هذا الكود خطوة بخطوة:

1. نبدأ بفتح صفحة تسجيل الدخول باستخدام driver.get(). هذا يشبه كتابة عنوان URL في المتصفح.

2. نستخدم WebDriverWait للانتظار حتى 10 ثوانٍ لظهور حقل اسم المستخدم. نبحث عن العنصر باستخدام معرف ID وهو “username”. هذا أفضل من استخدام time.sleep لأنه ينتظر فقط الوقت اللازم.

3. بمجرد العثور على حقل اسم المستخدم، نستخدم send_keys() لإدخال اسم المستخدم. ثم نكرر العملية مع حقل كلمة المرور.

4. نقوم بالنقر على زر تسجيل الدخول باستخدام click().

5. للتأكد من نجاح عملية تسجيل الدخول، ننتظر ظهور عنصر بclass يسمى “dashboard”. هذا يؤكد أننا وصلنا إلى لوحة التحكم بعد تسجيل الدخول.

6. نستخدم try/except للتعامل مع أي أخطاء قد تحدث خلال العملية، مثل عدم وجود العناصر أو انتهاء مهلة الانتظار.

مثال 2: جمع البيانات من موقع

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

def scrape_products(driver, url):
    products = []
    try:
        driver.get(url)
        
        # انتظار تحميل المنتجات
        WebDriverWait(driver, 10).until(
            EC.presence_of_all_elements_located((By.CLASS_NAME, "product-card"))
        )
        
        # استخراج بيانات كل منتج
        product_cards = driver.find_elements(By.CLASS_NAME, "product-card")
        
        for card in product_cards:
            product = {
                'name': card.find_element(By.CLASS_NAME, "product-name").text,
                'price': card.find_element(By.CLASS_NAME, "product-price").text,
                'rating': card.find_element(By.CLASS_NAME, "product-rating").text
            }
            products.append(product)
            
        return products
        
    except Exception as e:
        print(f"حدث خطأ: {str(e)}")
        return []

لنفهم كيف يعمل هذا الكود:

1. نبدأ بإنشاء قائمة فارغة products لتخزين بيانات المنتجات التي سنجمعها.

2. نفتح الصفحة المطلوبة باستخدام driver.get(url).

3. نستخدم presence_of_all_elements_located للانتظار حتى تظهر جميع بطاقات المنتجات (product-cards) في الصفحة. هذا مهم لضمان تحميل جميع المنتجات قبل محاولة قراءة بياناتها.

4. نجمع كل بطاقات المنتجات في الصفحة باستخدام find_elements. لاحظ استخدام الصيغة الجمع (elements) لأننا نتوقع العثور على عدة عناصر.

5. نمر على كل بطاقة منتج ونستخرج منها الاسم والسعر والتقييم باستخدام find_element والخاصية text.

6. نخزن بيانات كل منتج في قاموس (dictionary) ونضيفه إلى قائمة المنتجات.

7. في حالة حدوث أي خطأ، نطبع رسالة الخطأ ونعيد قائمة فارغة.

مثال 3: ملء النماذج تلقائياً

ملء النماذج هو مهمة متكررة يمكن أتمتتها بسهولة باستخدام Selenium. في هذا المثال، سنقوم بإنشاء دالة مرنة تستطيع ملء أي نموذج باستخدام قاموس من البيانات.

def fill_form(driver, form_data):
    try:
        # فتح صفحة النموذج
        driver.get("https://example.com/form")
        
        # ملء حقول النموذج
        for field_id, value in form_data.items():
            element = WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.ID, field_id))
            )
            element.clear()
            element.send_keys(value)
        
        # تقديم النموذج
        submit_button = driver.find_element(By.ID, "submit-form")
        submit_button.click()
        
        # التحقق من نجاح العملية
        success_message = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "success-message"))
        )
        print("تم تقديم النموذج بنجاح!")
        
    except Exception as e:
        print(f"حدث خطأ: {str(e)}")

# مثال على استخدام الدالة
form_data = {
    "first-name": "أحمد",
    "last-name": "محمد",
    "email": "ahmed@example.com",
    "phone": "0123456789"
}

دعونا نشرح كيف تعمل هذه الدالة:

1. تأخذ الدالة معاملين: driver للتحكم بالمتصفح، و form_data وهو قاموس يحتوي على معرفات الحقول وقيمها.

2. نفتح صفحة النموذج باستخدام driver.get().

3. نستخدم حلقة for للمرور على كل زوج من معرف الحقل وقيمته في form_data.

4. لكل حقل، ننتظر ظهوره في الصفحة باستخدام WebDriverWait.

5. نستخدم clear() لمسح أي قيمة موجودة في الحقل، ثم send_keys() لإدخال القيمة الجديدة.

6. بعد ملء جميع الحقول، نبحث عن زر التقديم ونضغط عليه.

7. ننتظر ظهور رسالة النجاح للتأكد من اكتمال العملية.

8. في النهاية، نوضح مثالاً على كيفية تحضير البيانات في قاموس form_data.

أفضل الممارسات وحلول المشاكل الشائعة

عند العمل مع Selenium، هناك عدة ممارسات مهمة تساعد في تحسين موثوقية وأداء السكريبت. أولاً، من المهم دائماً استخدام WebDriverWait بدلاً من التأخير الثابت (time.sleep)، لأنه يضمن انتظار العناصر بشكل ذكي ويحسن أداء السكريبت. كما يجب التعامل مع الأخطاء بشكل مناسب باستخدام try/except لتجنب توقف السكريبت بشكل غير متوقع.

من المهم أيضاً إغلاق المتصفح بشكل صحيح بعد الانتهاء من العمليات باستخدام driver.quit(). يمكن استخدام سياق with للتأكد من إغلاق المتصفح تلقائياً حتى في حالة حدوث أخطاء. عند اختيار العناصر في الصفحة، يفضل استخدام معرفات ID أو CSS Selectors لأنها أكثر استقراراً من XPath.

نصائح متقدمة للأداء والأمان

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

عند جمع البيانات من المواقع، من المهم تجنب الحظر بإضافة تأخيرات عشوائية بين الطلبات واحترام ملف robots.txt. في بعض الحالات، قد تحتاج إلى استخدام خوادم Proxy لتجنب القيود على معدل الطلبات أو للوصول إلى محتوى مقيد جغرافياً.

مثال كامل: برنامج لمراقبة الأسعار

import time
import random
import json

def price_monitor():
    driver = setup_driver()
    
    try:
        # قراءة قائمة المنتجات من ملف
        with open('products.json', 'r') as f:
            products = json.load(f)
        
        while True:
            for product in products:
                # فحص سعر كل منتج
                current_price = check_product_price(driver, product['url'])
                
                # مقارنة السعر مع السعر المستهدف
                if current_price <= product['target_price']:
                    send_notification(product, current_price)
                
                # تأخير عشوائي
                time.sleep(random.uniform(2, 5))
            
            # انتظار قبل الدورة التالية
            time.sleep(3600)  # انتظار ساعة
            
    except Exception as e:
        print(f"حدث خطأ: {str(e)}")
    
    finally:
        driver.quit()

التعليقات

اترك تعليقاً