Based on user input on a search engine, I am trying to scrape data from the search results on a website through multiple layers. The search results of the user may vary so I decided to use the PageObject design pattern to scale my project, but I don't understand the Python Selenium tutorial and how the element.py file and page.py file interact so I can edit them to my liking.
I am following this tutorial: https://selenium-python.readthedocs.io/page-objects.html
What is the BasePageElement? Is this file only apply to the first layer for webscraping? Should I copy the BasePageElement class and edit it for the next layer in my webscraping journey into a website? Is there a better explanation on what the element.py file is actually doing?
Example for page Stackoveflow
But current classes have two problems for me:
BasePageElement
uses only find_element_by_name
and it is useless to search elements different then fields in form.
BasePageElement
search on single element so it is useless to get all results on search page.
It would need other classes to make it more useful.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException, TimeoutException
# --- original classes ---
class BasePage(object):
"""Base class to initialize the base page that will be called from all pages"""
def __init__(self, driver):
self.driver = driver
class BasePageElement(object):
"""Base page class that is initialized on every page object class."""
def __set__(self, obj, value):
"""Sets the text to the value supplied"""
driver = obj.driver
WebDriverWait(driver, 100).until(
lambda driver: driver.find_element_by_name(self.locator))
driver.find_element_by_name(self.locator).clear()
driver.find_element_by_name(self.locator).send_keys(value)
#driver.find_element_by_name(self.locator).send_keys(Keys.Return)
def __get__(self, obj, owner):
"""Gets the text of the specified object"""
driver = obj.driver
WebDriverWait(driver, 100).until(
lambda driver: driver.find_element_by_name(self.locator))
element = driver.find_element_by_name(self.locator)
return element.get_attribute("value")
# --- my classes ---
class SearchTextElement(BasePageElement):
locator = 'q'
class MainPage(BasePage):
# element has to be defined here
# (not as `self.field` because it will not work as expected)
search_text_element = SearchTextElement()
def search(self, query):
self.search_text_element = [query, Keys.RETURN]
# ----
class ResultElement(BasePageElement):
locator = 'q' # there is no other `name` on Stackoveflow
class ResultPage(BasePage):
# element has to be defined here
# (not as `self.field` because it will not work as expected)
result_element = ResultElement()
def get_result(self):
return self.result_element
# --- main ---
#driver = webdriver.Firefox()
driver = webdriver.Chrome()
driver.get('https://stackoverflow.com')
main_page = MainPage(driver)
main_page.search('selenium')
result_page = ResultPage(driver)
result = result_page.get_result()
print('result:', result)