أرسل "شكرًا" لموقع بايثونات عبر مكتبة سيلينيوم

أرسل “شكرًا” لموقع بايثونات عبر مكتبة سيلينيوم

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

ما هي مكتبة سيلينيوم؟

هي مكتبة مختصة باختبار (Testing) صفحات الويب، ولكن هذا الاستخدام لا يتوقف عند هدف الاختبار فقط، بل يتعداه ليشمل عمليات محاكاة استخدام الويب،

وأتمتة (automation) العمليات التي تُنفذ على صفحات المواقع وأنظمة الويب، بالإضافة لتجريف الويب وجمع البيانات. نستطيع القول إنها سائق-المتصفح browser driver التي تستطيع قيادة المتصفح نحو أهداف مُعينة نحتاج تحقيقها بشكل آلي.

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

لا تحتوي سيلينيوم على متصفح خاص بها، ولكي تعمل، يلزم لذلك وجود متصفح خاص مثل Firefox أو Chrome، وإذا كنت ترغب بأن يعمل برنامجك في الخلفية، فمن الممكن أن تستخدم متصفح PhantomJS (يدعى بـ headless browser)، حيث يقوم بتحميل الموقع في الذاكرة، ويُمَكِنُك من تنفيذ كافة العمليات المتاحة بالمتصفحات العادية ولكن دون إظهار أي رسومات للمستخدم.

أهمية مكتبة سيلينيوم

تتجلى أهمية مكتبة سيلينيوم في عدة جوانب، فمن خلال استخدامها في اختبار وفحص الويب، فإنك على الأغلب ستكتب شيفرة برمجية قليلة لاختبار نظام كبير وفق مفهوم blackbox automating testing أو BAT، وعلى النقيض من أشكال الاختبار الأخرى، التي قد تحتاج فيها لكتابة شيفرة برمجية كبيرة لفحص خصائص صغيرة في النظام، وهذا يعني أننا قللنا من الوقت والجهد اللازمين لإجراء blackbox testing.

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

تنبع أهمية سيلينيوم أيضًا في أنها تحاكي سلوك المستخدم الحقيقي للموقع، فبعض أطر التشغيل الآلي تقوم بحقن المتصفح بشيفرات برمجية لمحاكاة عمليات المستخدم مثل الضغط على زر مُعين. بالإضافة لذلك، تدعم سيلينيوم شريحة واسعة من أشهر المتصفحات على بيئات تشغيل مختلفة مثل Linux و Windows.

نستطيع تلخيص أهمية مكتبة سيلينيوم فيما يلي:

  • توفير الوقت والجهد.
  • سهولة الاستخدام.
  • التوافق مع متصفحات مختلفة.
  • العمل في بيئات تشغيل عديدة.
  • تُستخدم في الفحص، التشغيل الآلي ومحاكاة سلوك المستخدم.

         اقرأ أيضًا: التسجيل Logging في البايثون – الدليل البسيط

Drivers

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

إن عدم وجود هذا المتصفح يؤدي لظهور خطأ من نوع selenium.common.exceptions.WebDriverException الذي يُفيد بعدم توفر المتصفح المطلوب.

الجدول التالي يحتوي على الروابط اللازمة لتنزيل المتصفحات حسب نوعها (المصدر):

BrowserURL
Chromehttps://sites.google.com/a/chromium.org/chromedriver/downloads
Edgehttps://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
Firefoxhttps://github.com/mozilla/geckodriver/releases
Safarihttps://webkit.org/blog/6900/webdriver-support-in-safari-10/

مثال بسيط

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

from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(30)
driver.maximize_window()
driver.get("https://www.google.ps")
search_box = driver.find_element_by_name('q')

search_box.clear()

search_box.send_keys("بايثونات")

search_btn = driver.find_element_by_name('btnK')

search_btn.click()
driver.quit()

قبل تشغيل المثال، يجب تثبيت المتصفح الخاص بـ chrome من الرابط الموجود في الجدول بالأعلى، ووضعه في نفس مسار ملف المثال، أو في مسار يراه مُفسر البايثون المُستخدم.

في البداية نقوم باستيراد الوحدة webdriver التي تحتوي على كافة الدوال والأصناف (classes) التي تُمثل أغلب المتصفحات.  للحصول على نُسخة (instance) من متصفح chrome نستدعي الدالة البانية لهذا المتصفح باستخدام webdriver.Chrome ومن ثم نضبط بعض خصائص هذه النسخة مثل تحديد implicit wait للمتصفح وضبط خاصية maximize window. خاصية implicit wait تعني أنه في حال لم يظهر العنصر الذي نبحث عنه في الصفحة، فيجب على المتصفح الانتظار المدة المحددة، وفي حالة انقضاء هذه المدة يُطلق الاستثناء، ElementNotVisibleException، يُمكنك الاطلاع على المرجع رقم 3 والمرجع رقم 4 لمعرفة المزيد.

للذهاب لصفحة محرك البحث جوجل نستخدم الدالة get ونُمرر لها عنوان المحرك كاملًا. للحصول على نُسخة تُمثل مربع البحث الذي نكتب فيه ما نريد البحث عنه نستخدم الدالة find_element_by_name ونُمرر لها اسم مربع البحث والذي هو ‘q’ (حصلنا عليه من شيفرة html للصفحة بواسطة الضغط على الزر اليمين للفأرة ومن ثم inspect على مربع البحث).

تُستخدم الدالة clear لمسح أية بيانات مُدخلة سابقًا في مربع البحث. لكتابة وإدخال النص للمربع نستخدم الدالة send_keys ونُمرر لها كلمة “بايثونات” التي نريد البحث عنها. بعد أن أدخلنا الكلمة، يتبقى علينا الضغط على زر البحث، وهنا نحتاج الحصول على نسخة تُمثله من خلال الدالة find_element_by_name ومن ثم الضغط عليه باستخدام الدالة click. سينتقل المتصفح بنا بعد الضغط على زر البحث الى الصفحة التالية التي تُظهر نتائج البحث.

في نهاية الأمر، نقوم بالخروج من المتصفح واغلاقه بواسطة الدالة quit.

إيجاد عناصر الصفحة باستخدام مكتبة سيلينيوم

عندما نطلب صفحة ما باستخدام أحد المتصفحات، فإن المتصفح يُرسل طلب request الى الخادم server ويقوم الخادم بإرسال رد يحتوي على مكونات الصفحة. يحتوي الرد على مستند html وجميع ما يتعلق من شيفرات CSS و JavaScript وصور.

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

من دواعي السرور أن نجد أغلب المتصفحات تحتوي على ميزات تُساعدك في قراءة html الصفحة وتفتيش عناصرها والبحث خلالها. سنعتمد في هذه المقالة على متصفح كروم الذي يُقدم أدوات المطور DevTools التي ستساعدنا في هدفنا المنشود في التعرف على مكونات الصفحة.

لمزيد من المعلومات عن DevTools يمكنك الذهاب للرابط التالي:

https://developers.google.com/web/tools/chrome-devtools/

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

افتح متصفح كروم واذهب للصفحة الرئيسية لمدونة بايثونات، وباستخدام الزر اليمين من الفأرة اضغط على “تواصل معي” في أعلى الصفحة، واختر inspect كما هو موضح في الصورة التالية:

inspect html component

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

chrome devtools

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

مكونات الصفحة التي سنتعامل معها هي كالتالي:

  • زر “تواصل معي” في الصفحة الرئيسية وهو عبارة عن عنصر في قائمة ويمتلك خاصية id=”menu-item-262″.
  • خانة الاسم في صفحة تواصل معي وهي عبارة عن عنصر إدخال ويمتلك خاصية id=”g260″ وخاصية name=”g260″ أيضًا.
  • خانة البريد الإلكتروني في صفحة تواصل معي وهي عبارة عن عنصر إدخال ويمتلك خاصية id=”g260-1″ وخاصية name=”g260-1″ أيضًا.
  • خانة الرسالة في صفحة تواصل معي وهي عبارة عن عنصر إدخال ويمتلك خاصية name=”g260-3″.
  • زر أرسل في صفحة تواصل معي ويندرج تحت صنف class=”pushbutton-wide”.
  • رسالة “تم ارسال الرسالة (الرجوع للخلف)” والتي ستظهر بعد ادخال البيانات والضغط على زر ارسال، ولكن هذه الرسالة ليس لديها أي خاصية يمكن الاستناد عليها للوصول لها.

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

  • تشغيل المتصفح.
  • الذهاب للصفحة الرئيسية لمدونة بايثونات.
  • الضغط على زر تواصل معي.
  • ادخال اسم المُرسل في خانة الاسم.
  • ادخال البريد الالكتروني.
  • ادخال الرسالة المُراد ارسالها لصاحب المدونة.
  • الضغط على زر ارسال.
  • فحص وجود رسالة “تم ارسال الرسالة” في الصفحة الحالية.
  • الخروج من المتصفح.

إيجاد عناصر الصفحة باستخدام مكتبة سيلينيوم

يُوجد العديد من الدوال المُساعدة في مكتبة سيلينيوم والتي تُمكنك من إيجاد عناصر الصفحة بأكثر من طريقة. الطرق التالية تُوضح خيارات الوصول وإيجاد عناصر الصفحة:

  • إيجاد العنصر بواسطة مُعرف id.
  • إيجاد العنصر بواسطة اسم العنصر name.
  • إيجاد العنصر بواسطة مسار xpath.
  • إيجاد العنصر بواسطة link text أو جزء منه.
  • إيجاد العنصر بواسطة اسم الوسم tag name.
  • إيجاد العنصر بواسطة اسم الفئة/الصنف class name.
  • إيجاد العنصر بواسطة مُحدد CSS.

لن نستطيع تغطية كافة الطرق السابقة بالتفصيل في مثالنا، ولكن بمقدورك الذهاب الى الرابط التالي للتعرف أكثر عن هذه الطرق:

http://selenium-python.readthedocs.io/locating-elements.html

إذًا وبعد أن تعرفنا على كيفية إيجاد عناصر الصفحة باستخدام أدوات المطور في كروم، وبعد أن سردنا بشكل سريع الدوال المُستخدمة في سيلينيوم لإجاد عناصر الصفحة، لنبدأ بكتابة مثالنا ونشرح الأجزاء المهمة منه بالتفصيل:

أولًا: استيراد المكتبات والوحدات اللازمة للعمل وإعداد نُسخة/متغير المتصفح

from selenium import webdriver
import time
driver = webdriver.Chrome()
implicitly_wait(5)
maximize_window()

ثانيًا: الذهاب لصفحة بايثونات

get("https://3alakivyblog.wordpress.com")

ثالثًا: إيجاد زر “تواصل معي” والضغط عليه

contact_me = driver.find_element_by_id("menu-item-262")
contact_me.click()

رابعًا: إيجاد خانة “الاسم” وإدخال نص بداخلها

name = driver.find_element_by_id("g260")
clear()
send_keys("مكتبة سيلينيوم")

خامسًا: إيجاد خانة “البريد الإلكتروني” وإدخال بريد الكتروني بداخلها

email = driver.find_element_by_id("g260-1")
clear()
send_keys("[email protected]")

سادسًا: إيجاد خانة “الرسالة” وإدخال رسالة بداخلها

message = driver.find_element_by_name("g260-3")
clear()
send_keys("شكرًا لك على هذا المقال استمر في قيادة متصفحك")

لاحظ معي أننا هذه المرة لم نبحث عن الخانة باستخدام خاصية id لعدم وجودها للعنصر، واستخدمنا خاصية name للوصول للعنصر.

سابعًا: إيجاد زر “أرسل” والضغط عليه

send_msg = driver.find_element_by_class_name("pushbutton-wide")
submit()

هذه المرة لا يوجد لدينا أي خاصية من id او name، واستخدمنا خاصية class للوصول للعنصر.

ثامنًا: فحص وجود رسالة “تم ارسال الرسالة” في الصفحة الحالية

done_msg = driver.find_element_by_xpath('//*[@id="contact-form-260"]/h3')

if done_msg.text == "تم إرسال الرسالة (الرجوع للخلف)":

print("Message has been sent successfully")

else:

print("Error in sending message")

في حال لم يكن للعنصر الذي نبحث عنه خاصية id او name أو class، سنلجأ حينها للوصول إليه بواسطة ما يُسمى xpath والذي هو عبارة عن طريقة للوصول إلى عناصر مستند xml، وبما أننا نتعامل مع html التي تُشبه xml من حيث الهيكلية، فإننا نستخدم xpath هنا للوصول الى عناصر الصفحة.

لمزيد من المعلومات عن xpath تستطيع الذهاب للرابط التالي:

https://www.w3schools.com/xml/xpath_intro.asp

تاسعًا: الخروج من المتصفح

time.sleep(5)
driver.quit()

في نهاية البرنامج نقوم بالخروج من المتصفح (الانتظار 5 ثواني هو من باب إعطاءك فرصة لمشاهدة ما يحدث قبل إغلاق المتصفح).

من الممكن أن نُطور على هذا المثال بحيث نُمرر البيانات المستخدمة وألا تكون ثابتة في الشيفرة البرمجية، ويكون ذلك باستخدام مكتبة argparser المُضمنة في بايثون وهذا تحسينٌ بسيطٌ على المثال. من الممكن أيضًا أن ندمج هذا المثال في بوت آلي يقوم بإرسال رسالة الشكر مع كل مقال جديد يظهر على المدونة (فكرة جميلة).

لا تنسى قبل تشغيل المثال أن تكون سيلينيوم قد ثُبتت على نظامك وأن تكون حَملت المتصفح الخاص لكروم من الرابط الموجود في الجدول أعلى المقال.

المثال كاملا على github:

https://github.com/3alaKivy/selenium_examples

خاتمة

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

مراجع

1https://www.linkedin.com/pulse/why-selenium-webdriver-rakesh-singh
2http://selenium-python.readthedocs.io/
3https://www.guru99.com/implicit-explicit-waits-selenium.html
4https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp
5http://selenium-python.readthedocs.io/locating-elements.html
6https://www.w3schools.com/xml/xpath_intro.asp

 

 

اترك تعليقاً

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