English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تفسير ثلاث طرق الانتظار في selenium python

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

الكثير من الناس يسألون في المجموعات، لا يمكن العثور على هذا القائمة المنسدلة أو ذلك النافذة المنبثقة... لا يمكن العثور على هذا أو ذاك، في معظم الحالات، هناك فقط مشكلتان: 1 هناك إطار، 2 لم يتم إضافة الانتظار. لا يدركون أن سرعة تشغيل شifrتهم هي ما مدى سرعة تحميل وتلوين المتصفح، وكأن الأبطال البديل والشكل المستدير قد اتفقوا على الذهاب لمواجهة الأعداء، ثم يعود الأبطال البديل ويطرح سؤالاً: لماذا لا تزال تلبس حذائك لمغادرة المنزل؟ يجري الأبطال البديل في ذهنه عشرات الأفكار، ويشعر بالتقليل من السرعة، لا يريد أن يلعب معك، ويقوم بتقديم استثناء ويترك المهمة.

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

1. الانتظار القسري

الطريقة الأولى وهي الطريقة الأبسط والأكثر صرامة هي الانتظار القسري sleep(xx)، حيث يجعل الأبطال البديل ينتظرون xx ثانية، بغض النظر عن ما إذا كان الأبطال البديل يمكنهم اللحاق بالسرعة أم لا، أو إذا كانوا قد وصلوا مسبقًا، يجب أن ينتظروا xx ثانية.

أنظر إلى الكود:

# -*- coding: utf-8 -*-
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get('https://huilansame.github.io')
sleep(3) # الانتظار القسري لمدة 3 ثواني قبل تنفيذ الخطوة التالية
print(driver.current_url)
driver.quit()

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

2. الانتظار الخفي

الطريقة الثانية تسمى الانتظار الخفي، implicitly_wait(xx)، معنى الانتظار الخفي هو: بينما كان الأبطال البديل والشكل المستدير قد اتفقوا على أن الأبطال البديل سينتظر xx ثانية، إذا جاء الأبطال البديل في هذا الوقت، فسيذهبون معًا لمواجهة الأعداء، وإذا لم يأت الأبطال البديل في الوقت المحدد، فإن الأبطال البديل سيذهبون وحدهم، وبالتالي سينتظرون الأبطال البديل ليقدموا الاستثناء لك.

أنظر إلى الكود:

# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(30) # الانتظار الخفي، لمدة 30 ثانية
driver.get('https://huilansame.github.io')
print(driver.current_url)
driver.quit()

الانتظار الخفي هو إعداد وقت انتظار أقصى، إذا تم تحميل الصفحة في الوقت المحدد، يتم تنفيذ الخطوة التالية، وإلا يتم الانتظار حتى انتهاء الوقت، ثم تنفيذ الخطوة التالية. يرجى الانتباه إلى أن هناك عيباً هنا، وهو أن البرنامج سينتظر تحميل الصفحة بالكامل، أي عادة ما ترون تلك الدائرة الصغيرة في شريط العناوين في المتصفح تتوقف عن الدوران، قبل تنفيذ الخطوة التالية، ولكن في بعض الأحيان، تكون العناصر التي أريدها قد تم تحميلها بالفعل، ولكن بسبب بعض الأشياء مثل JavaScript التي تكون بطيئة بشكل خاص، يجب أن أنتظر حتى يتم تحميل الصفحة بالكامل قبل تنفيذ الخطوة التالية، ماذا أفعل إذا كنت أريد انتظار ظهور العناصر التي أريدها قبل تنفيذ الخطوة التالية؟ هناك طريقة، وهذا يتطلب النظر في طريقة الانتظار التي يقدمها selenium - الانتظار البديل الموضعي wait.

يحتاج إلى ملاحظة خاصة: يبدأ الإنتظار التلميعي في العمل لكل دورة من driver، لذا يمكن إعداده مرة واحدة فقط، لقد رأيت من قبل أن يتم استخدام الإنتظار التلميعي كـ sleep في كل مكان...

3. الإنتظار الحتمي

الطريقة الثالثة هي الإنتظار الحتمي، WebDriverWait، بالإضافة إلى دالة until() والدالة until_not() من هذه الفئة، يمكنها الإنتظار بشكل مرن بناءً على شرط. إنها تعني بشكل رئيسي: كل xx ثانية يتحقق البرنامج من الشرط، إذا تم استيفاء الشرط، يتم تنفيذ الخطوة التالية، وإلا يستمر في الإنتظار حتى تجاوز المدة المحددة مسبقًا، ثم يُطرح TimeoutException.

لنبدأ بعرض مثال على الشيفرة:

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.implicitly_wait(10) # الإنتظار التلميعي والإنتظار الحتمي يمكن استخدامهم معًا، لكن يجب الانتباه: أطول وقت انتظار هو الأكبر بينهما
driver.get('https://huilansame.github.io')
locator = (By.LINK_TEXT, 'CSDN')
try:
  WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))
  print driver.find_element_by_link_text('CSDN').get_attribute('href')
finally:
  driver.close()

上例中,我们设置了隐性等待和显性等待,在其他操作中,隐性等待起决定性作用,在WebDriverWait..中显性等待起主要作用,但要注意的是:最长的等待时间取决于两者之间的大者,此例中为20,如果隐性等待时间 > 显性等待时间,则该句代码的最长等待时间等于隐性等待时间。

我们主要用到了WebDriverWait类与expected_conditions模块,下面博主带大家细看一下这两个模块:

WebDriverWait

wait模块的WebDriverWait类是显性等待类,先看下它有哪些参数与方法:

selenium.webdriver.support.wait.WebDriverWait(类)
__init__
  driver: 传入WebDriver实例,即我们上例中的driver
  timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)
  poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒
  ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,
      则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。
until
  method: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False
  message: 如果超时,抛出TimeoutException,将message传入异常
until_not 与until相反,until是当某元素出现或什么条件成立则继续执行,
    until_not是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。
  method
  message

看了以上内容基本上很清楚了,调用方法如下:

WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)

这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))  # 错误

هذه هي الطريقة الخاطئة، يجب أن يكون المعامل قابلاً للإدخال، أي يجب أن يكون لديه method __call__، وإلا سيُلقى استثناء:

TypeError: 'xxx' object is not callable

في هذا السياق، يمكنك استخدام جميع الشروط المتاحة في module expected_conditions التي يقدمها selenium، أو استخدام methods is_displayed()،is_enabled()،is_selected() الخاصة بـ WebElement، أو استخدام methods م封装 الخاصة بك، ثم دعنا نرى الشروط التي يقدمها selenium:

expected_conditions

expected_conditions هو module من selenium، ويحتوي على مجموعة من الشروط التي يمكن استخدامها للتحقق:
selenium.webdriver.support.expected_conditions (المodule)
هذه الشروط تحقق من عنوان الصفحة، ويُتحقق من ما إذا كان المعامل المقدم عنوانًا يتطابق أو يحتوي على عنوان driver.title
title_is
title_contains
هذه الشروط تتحقق من ما إذا كان العنصر موجودًا، ويُدخل جميع المعلمات كـ tuple نوع locator، مثل (By.ID, 'kw')
كما يُقال، الأولى تُمرر إذا تم تحميل عنصر واحد يتوافق مع الشروط؛ والأخرى تتطلب تحميل جميع العناصر التي تتوافق مع الشروط
presence_of_element_located
presence_of_all_elements_located
هذه الشروط تتحقق من ما إذا كان العنصر مرئيًا، الأوليان تُدخل كـ tuple نوع locator، والثالثة تُدخل كـ WebElement
الأولى والثالثة لها نفس الجوهر
visibility_of_element_located
invisibility_of_element_located
visibility_of
هذه الشروط تحدد ما إذا كان نص معين موجودًا في عنصر معين، واحدة تقوم بتحديد نص العنصر، والأخرى تقوم بتحديد قيمة العنصر
text_to_be_present_in_element
text_to_be_present_in_element_value
هذه الشروط تحدد ما إذا كان يمكن الدخول إلى frame أم لا، يمكن إدخال tuple المحدد أو إدخال طريقة التحقق مباشرة: id،name،index أو WebElement
frame_to_be_available_and_switch_to_it
هذه الحالة تقييم ما إذا كان هناك alert
alert_is_present
هذه الحالة تقييم ما إذا كان العنصر قابلاً للنقر، يتم إدخال locator
element_to_be_clickable
هذه الأربعة حالات تقييم تحدد ما إذا كان العنصر قد تم اختياره، حيث يتم إدخال WebElement في الحالة الأولى، وlocator في الحالة الثانية
الثالث يتم إدخال WebElement والوضع، إذا كانت متساوية فسيتم إرجاع True، وإلا سيتم إرجاع False
الخامس يتم إدخال locator والوضع، إذا كانت متساوية فسيتم إرجاع True، وإلا سيتم إرجاع False
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
تقييم آخر يحدد ما إذا كان العنصر لا يزال موجودًا في DOM، يتم إدخال WebElement، يمكن التحقق مما إذا كان الصفحة قد تم تحديثها
staleness_of

هذه هي جميع 17 حالة condition، بالإضافة إلى until و until_not يمكن تنفيذ العديد من الحالات، إذا كنت تستطيع التعبئة بسهولة، فإن هذا سيزيد من استقرار السكربت بشكل كبير.

هذا هو المحتوى الذي تم تقديمه اليوم، إذا كان لديك أي أسئلة، يمكنك ترك تعليق لي للتفاعل، آمل أن يساعدك هذا على المساعدة في الحاجة. شكراً لكم على دعم هذا الموقع!

إعلان: محتوى هذا المقال تم جمعه من الإنترنت، يحق لصاحب الحقوق أن يكون له حقوق ملكية، تم جمع المحتوى من قبل المستخدمين عبر الإنترنت وتم تحميله بشكل تلقائي، هذا الموقع لا يملك حقوق الملكية، لم يتم تعديل المحتوى بشكل يدوي، ولا يتحمل أي مسؤولية قانونية مرتبطة بذلك. إذا كنت قد وجدت محتوى يشتبه في حقوق النسخ، فنرجو منك إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # ب @) لتقديم الشكوى، وتقديم الدليل المتعلق، إذا تم التحقق من ذلك، فإن هذا الموقع سيقوم بإزالة المحتوى المشبوه فوراً.

أنت قد تحب