Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Realizar una prueba técnica

23/24
Recursos

Aportes 42

Preguntas 13

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Para utilizar location, condition y higher_price cambie el código. El mensaje de Selenium fue “Element click intercepted”.

# Anterior 
location.click()
# Nuevo
driver.execute_script("arguments[0].click();", location)

Con eso logre realizar el test.

Este es mi implementación antes de ver el vídeo, mi intención era generalizarlo lo mas posible para cualquier variación como país, búsqueda, filtro, localidad y orden.

mercado_libre_page.py

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

class MercadoLibrePage(object):

  def __init__(self, driver):
    self._driver = driver
    self._url = 'http://mercadolibre.com/'

  @property
  def is_loaded(self):
    WebDriverWait(self._driver, 10).until(
      EC.presence_of_element_located((By.CLASS_NAME, 'ml-site-list'))
      or EC.presence_of_element_located((By.NAME, 'as_word'))
    )
    return True

  @property
  def keyword(self):
    input_field = self._driver.find_element_by_name('as_word')
    return input_field.get_attribute('value')

  def open(self):
    self._driver.get(self._url)

  def type_search(self, keyword):
    input_field = self._driver.find_element_by_name('as_word')
    input_field.send_keys(keyword)

  def click_submit(self):
    input_field = self._driver.find_element_by_name('as_word')
    input_field.submit()

  def search(self, keyword):
    self.type_search(keyword)
    self.click_submit()

  def order_data(self, elements):
    obj = {}
    for element in elements:
      obj[element.text.lower()] = element
    return obj

  def get_contries(self):
    contries = self._driver.find_elements_by_class_name('ml-site-link')
    return self.order_data(contries)

  def choise_contry(self, contry):
    contry_item = self.get_contries()[contry.lower()]
    contry_item.click()

  def get_filters(self):
    filters = WebDriverWait(self._driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, 'ui-search-filter-name')))
    return self.order_data(filters)

  def choise_filter(self, keyword):
    self.get_filters()[keyword.lower()].click()

  def get_orders(self):
    list_buttom = WebDriverWait(self._driver, 5).until(EC.presence_of_element_located((By.CLASS_NAME, 'andes-dropdown__trigger')))
    list_buttom.click()
    orders = self._driver.find_elements_by_class_name('andes-list__item-primary')
    return self.order_data(orders)

  def choise_order_by(self, keyword):
    self.get_orders()[keyword.lower()].click()

  def get_top_5_elements_result(self):
    WebDriverWait(self._driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'ui-search-layout__item')))
    data = [[None, None]] * 5
    for i in range(5):
      data[i][0] = self._driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[1]/a/h2').text
      data[i][1] = self._driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[2]/div/div/span[1]/span[2]').text
    return data

test_mercado_libre.py

import unittest
from selenium import webdriver
from mercado_libre_page import MercadoLibrePage

class CompareProducts(unittest.TestCase):

  @classmethod
  def setUpClass(cls):
    cls.driver = webdriver.Chrome(executable_path = r'./chromedriver.exe')
    cls.driver.maximize_window()

  def test_mercado_libre(self):
    mcl = MercadoLibrePage(self.driver)
    mcl.open()
    self.assertTrue(mcl.is_loaded)
    mcl.choise_contry('colombia')
    mcl.search('playstation 4')
    mcl.choise_filter('nuevo')
    mcl.choise_filter('Bogotá D.C.')
    mcl.choise_order_by('Mayor precio')
    print(mcl.get_top_5_elements_result())

  @classmethod
  def tearDownClass(cls):
    cls.driver.close()

if __name__ == "__main__":
  unittest.main(verbosity=2)

Marzo-2021. Sale este error: Message: Element <span class=“ui-search-filter-name”> is not clickable at point (113,643) because another element <div id=“cookieDisclaimerBanner” class=“nav-cookie-disclaimer”> obscures it.
Parece que usaron alguna cookie para bloquear busquedas automatizadas con Selenium (por ejemplo), F. De todas maneras gran curso

Creo que es mejor usar un diccionario en vez de dos listas

 products = {}

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div[2]/div/h2/a/span').text
            price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div[2]/div/div[1]/div/span[2]').text
            products[article_name] = price

Este es mi códgio por si le sirve a alguien. Luego de unos arreglos que no me funcionaban algunos clicks y encontre la solución en los comentarios.

import unittest
from selenium import webdriver
from time import sleep
 
class TestingMercadoLibre(unittest.TestCase):

	def setUp(self):
		self.driver = webdriver.Chrome(executable_path = r'./chromedriver.exe')
		driver = self.driver
		driver.maximize_window()
		driver.get('https://www.mercadolibre.com')

	def test_search_PS4(self):
		driver = self.driver

		country = driver.find_element_by_id("CO")
		country.click()

		search_field = driver.find_element_by_name("as_word")
		search_field.click()
		search_field.clear()
		search_field.send_keys('playstation 4')
		search_field.submit()
		sleep(3)

		location = driver.find_element_by_xpath("//div/div/aside/section[2]/dl[9]/dd[1]/a")
		driver.execute_script("arguments[0].click();", location)
		sleep(3)

		condition = driver.find_element_by_xpath("//div/div/aside/section[3]/dl[6]/dd[1]/a")
		driver.execute_script("arguments[0].click();", condition)
		sleep(3)

		order_menu = driver.find_element_by_class_name("andes-dropdown__trigger")
		order_menu.click()

		higher_price = driver.find_element_by_xpath("//div/div/aside/section[2]/div[2]/div[1]/div/div/div/ul/li[3]/a")
		driver.execute_script("arguments[0].click();", higher_price)
		sleep(3)

		articles = []
		prices = []

		for i in range(5):
			article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a').text
			articles.append(article_name)
			article_price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]').text
			prices.append(article_price)

		print(articles, prices)


	def tearDown(self):
		self.driver.close()

if __name__ == "__main__":
	unittest.main()

Esta es mi implementacion

test_mercadolibre:

from selenium import webdriver
import unittest
from mercadolibre_page import MercadoLibrePage
from time import sleep

class testMercadoLibre(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path=r'C:/chromedriver.exe')
        cls.driver.maximize_window()

    def test_search(self):
        mercadolibre = MercadoLibrePage(self.driver)
        mercadolibre.open()
        mercadolibre.select_country('Colombia')
        
        self.assertEqual(mercadolibre.current_url, 'https://www.mercadolibre.com.co/#from=homecom')

        mercadolibre.type_search('playstation 4')
        mercadolibre.click_submit()

        self.assertEqual('playstation 4', mercadolibre.keyword)

        mercadolibre.acept_cookies()

        mercadolibre.add_filter('Nuevo')

        self.assertEqual(mercadolibre.last_filter, 'Nuevo')

        mercadolibre.add_filter('Bogotá D.C.')

        self.assertEqual(mercadolibre.last_filter, 'Bogotá D.C.')

        mercadolibre.open_price_filter_window()
        
        mercadolibre.add_price_filter('Menor precio')

        self.assertEqual(mercadolibre.current_order, 'Menor precio')

        mercadolibre.get_information(60)

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)

mercadolibre_page:

from selenium import webdriver
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 
import csv
import time

class MercadoLibrePage(object):

    def __init__(self, driver):
        self._driver = driver
        self._url = 'https://www.mercadolibre.com'
        self._search_locator = 'as_word'
        self._price_filter_locator = '//div[@class="andes-widther"]//button[@class="andes-dropdown__trigger"]'
        self._filters = []

    @property
    def is_loaded(self):
        WebDriverWait(self._driver, 10).until(EC.presence_of_element_located((By.NAME, self._search_locator)))
        return True

    @property
    def keyword(self):
        search_field = self._driver.find_element_by_name(self._search_locator)
        return search_field.get_attribute('value')

    @property
    def current_url(self):
        return self._driver.current_url

    @property
    def last_filter(self):
        return self._filters[len(self._filters)-1 ]
    
    @property
    def current_order(self):
        return WebDriverWait(self._driver, 10).until(EC.element_to_be_clickable((By.XPATH, self._price_filter_locator))).text

    def open(self):
        self._driver.get(self._url)

    def acept_cookies(self):
        try:
            location_window = self._driver.find_element_by_xpath('//div[@class="onboarding-cp"]')
            location_window.find_element_by_class_name('andes-tooltip-button-close').click()
        except NoSuchElementException:
            pass
        try:
            self._driver.find_element_by_id('cookieDisclaimerButton').click()
        except:
            pass

    def select_country(self, country):
        self._driver.find_element_by_link_text(country).click()
    
    def type_search(self, keyword):
        search_field = WebDriverWait(self._driver, 10).until(EC.presence_of_element_located((By.NAME, self._search_locator)))
        search_field.send_keys(keyword)

    def  click_submit(self):
        search_field = self._driver.find_element_by_name(self._search_locator)
        search_field.submit()

    def add_filter(self, filter_keyword):
        WebDriverWait(self._driver, 10).until(EC.element_to_be_clickable((By.XPATH, f'//section[@class="ui-search-filter-groups"]//span[text()="{filter_keyword}"]'))).click()
        self._filters.append(filter_keyword)

    def open_price_filter_window(self):
        WebDriverWait(self._driver, 10).until(EC.element_to_be_clickable((By.XPATH, self._price_filter_locator))).click()

    #the option filter are: [Más relevantes, Menor precio, Mayor precio]
    def add_price_filter(self, filter_keyword):
        self._driver.find_element_by_xpath(f'//ul[@class="andes-list andes-list--size-compact andes-list--dropdown andes-list--selectable"]//div[text()="{filter_keyword}"]').click()

    def get_information(self, product_quantity):
        #get information of all products that you need
        products = self._driver.find_elements_by_class_name('ui-search-layout__item')
        data = [[] for i in range(0, 2)]
        print()

        if products:
            n_products = 0
            i = 0
            while True:
                try:
                    name = products[i].find_element_by_class_name('ui-search-item__title')
                    price = products[i].find_element_by_class_name('price-tag-fraction')
                    data[0].append(name.text)
                    data[1].append(price.text)
                    print(f'name: {name.text} \nprice: {price.text}\n')
                    i += 1
                    n_products += 1
                    if n_products == product_quantity:
                        print(f'Se han encontraron los {n_products} productos.\n')
                        break
                except IndexError:
                    i = 0
                    try:
                        self._driver.find_element_by_xpath('//div[@class="ui-search-pagination"]//li//span[text()="Siguiente"]').click()
                        self._driver.implicitly_wait(10)
                        products = self._driver.find_elements_by_class_name('ui-search-layout__item')
                    except NoSuchElementException:
                        print(f'Solo se encontraron {n_products} productos.\n')
                        break
            self._save_data(data)
        else:
            print('\nNo se encontraron productos\n')


    def _save_data(self, data):
        #save data on csv file
        date = time.strftime('%d_%m_%Y', time.localtime())
        filename = f'products_data_{date}.csv'
        headers = ['name', 'price']

        with open(filename, mode= 'w+', encoding='utf-8', ) as f:
            writer = csv.writer(f)
            writer.writerow(headers)
            
            for i in range(0, len(data[0])):
                row = [data[0][i], data[1][i]]
                writer.writerow(row)

El class_name de la variable Order_menu hoy 26 julio es andes-dropdown__trigger y no ui-dropdown__link buen curso

Me toco modificar algunos click

import unittest
from selenium import webdriver
from api_data_mock import ApiDataMock
from selenium.webdriver.support.ui import Select # Modulo para poder seleccionar del dropdown
from time import sleep
from selenium.webdriver.common.by import By #Hacer referencia a un elemento del sitio web, para interactuar
from selenium.webdriver.support.ui import WebDriverWait # Modulo para  manejo de esperas explicitas
from selenium.webdriver.support import expected_conditions as EC #esperas explicitas




class TestingMercadoLibre(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome(executable_path = r'./chromedriver.exe')
        driver = self.driver
        driver.maximize_window()
        driver.get('**********') # adiconar la pagina


    def test_search_xbox(self):
        driver = self.driver

        country = driver.find_element_by_id('CO')
        country.click()
        sleep(2)
        search_field = driver.find_element_by_name('as_word')
        search_field.clear()
        search_field.send_keys('xbox')
        search_field.submit()
        sleep(2)
        
        location = driver.find_element_by_xpath('/html/body/main/div/div/aside/section[2]/dl[8]/dd[1]/a/span[1]')
        driver.execute_script("arguments[0].click();", location)
        # location.click()
        sleep(2)
        condition = driver.find_element_by_partial_link_text('Nuevo')
        driver.execute_script("arguments[0].click();", condition)
        # condition.click()
        sleep(2)
        order_menu = driver.find_element_by_class_name('andes-dropdown__trigger')
        order_menu.click()
        higher_price = driver.find_element_by_css_selector('li.andes-list__item:nth-child(3) > div:nth-child(1) > div:nth-child(1) > a:nth-child(1)')
        higher_price.click()
        sleep(2)

        articles = []
        prices = []

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a/h2').text
            price_article = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/div/div/span[1]/span[2]').text
            articles.append(article_name)
            prices.append(price_article)
        
        print(articles,prices)

        

    def tearDown(self):
        self.driver.implicitly_wait(5)
        self.driver.close()


if __name__ == '__main__':
    unittest.main(verbosity=2)

Un selector de css más corto li.ui-list__item:nth-child(3) > a:nth-child(1) para la variable higher_price

Excelente profe, aplicar todo y muy util ejemplo.

21/03/22

Dado que hubo ajustes en la pagina realice los siguientes cambios para que fue posible llevar a cabo el código por parte de Héctor.

  1. para location, condition cambie los find_element_by_partial_link_text por find_element_by_css_selector()

  2. para order_menu cambien el find_element_by_class_name() por find_element_by_css_selector()

  3. por utlimo y con el aporte dejado por por @Arnaldo Martinez se hizo el cambio en la opción de .click() en location, condition y higher_price por driver.execute_script(“arguments[0].click();”,location)
    driver.execute_script(“arguments[0].click();”,lcondition)
    driver.execute_script(“arguments[0].click();”,hirgher_price)

Con la ayuda de los comentarios y unas modificaciones más porque el sitio cambia constantemente aquí el código funcional para la fecha 09-10-2021

import unittest
from pyunitreport import HTMLTestRunner
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from time import sleep

class MercadoLibre(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path='/usr/bin/chromedriver')
        driver = cls.driver
        driver.get('https://www.mercadolibre.com/')
        driver.maximize_window()

    def test_search_ps4(self):
        driver = self.driver
        choose_country = driver.find_element_by_id('CO')
        choose_country.click()

        search_bar = driver.find_element_by_class_name('nav-search-input')
        search_bar.click()
        search_bar.clear()
        search_bar.send_keys('playstation 4')
        search_bar.submit()
        driver.implicitly_wait(3)

        pick_news = driver.find_element_by_partial_link_text('Nuevo')
        driver.execute_script("arguments[0].click();", pick_news)
        driver.implicitly_wait(3)

        pick_location = driver.find_element_by_partial_link_text('Bogotá D.C.')
        driver.execute_script("arguments[0].click();", pick_location)
        driver.implicitly_wait(3)

        pick = driver.find_element_by_class_name('andes-dropdown__trigger')
        driver.execute_script("arguments[0].click();", pick)
        driver.implicitly_wait(10)

        pick_expensive_price = driver.find_elements_by_class_name('andes-list__item-primary')
        pick_expensive_price[2].click()

        articles = []
        prices = []

        for i in range(5):
            article_name = driver.find_element_by_css_selector(f'#root-app > div > div > section > ol > li:nth-child({i+1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-item__group.ui-search-item__group--title > a > h2').text
            articles.append(article_name)
            article_price = driver.find_element_by_css_selector(f'#root-app > div > div > section > ol > li:nth-child({i+1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-result__content-columns > div.ui-search-result__content-column.ui-search-result__content-column--left > div.ui-search-item__group.ui-search-item__group--price > a > div > div > span.price-tag.ui-search-price__part > span.price-tag-amount > span.price-tag-fraction').text
            prices.append(article_price)
        for x in range(len(articles)):
            print(prices[x]+' -> '+articles[x])

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()

if __name__ == '__main__':
    unittest.main(verbosity=2, testRunner=HTMLTestRunner(output = 'reportes', report_name = 'ML_report'))

Una actualización al codigo (con ubuntu y chrome92)

import unittest
from selenium import webdriver
from time import sleep
 
class TestingMercadoLibre(unittest.TestCase):

	def setUp(self):
		self.driver = webdriver.Chrome(executable_path = r'./chromedriver92')
		driver = self.driver
		driver.maximize_window()
		driver.get('https://www.mercadolibre.com')

	def test_search_PS4(self):
		driver = self.driver

		country = driver.find_element_by_id("CO")
		country.click()

		search_field = driver.find_element_by_name("as_word")
		search_field.click()
		search_field.clear()
		search_field.send_keys('playstation 4')
		search_field.submit()

		location = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section/dl[18]/dd[1]/a')
		driver.execute_script("arguments[0].click();", location)
		sleep(1)

		condition = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section[2]/dl[16]/dd[1]/a')
		driver.execute_script("arguments[0].click();", condition)
		sleep(1)

		order_menu = driver.find_element_by_class_name("andes-dropdown__trigger")
		order_menu.click()

		higher_price = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul/li[3]/a')
		driver.execute_script("arguments[0].click();", higher_price)
		sleep(1)

		articles = []
		prices = []

		for i in range(5):
			article_name = driver.find_element_by_css_selector(f'#root-app > div > div > section > ol > li:nth-child({i+1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-item__group.ui-search-item__group--title > a > h2').text
			articles.append(article_name)
			article_price = driver.find_element_by_css_selector(f'#root-app > div > div > section > ol > li:nth-child({i+1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-result__content-columns > div.ui-search-result__content-column.ui-search-result__content-column--left > div.ui-search-item__group.ui-search-item__group--price > a > div > div > span.price-tag.ui-search-price__part > span.price-tag-amount > span.price-tag-fraction').text
			prices.append(article_price)
		for x in range(len(articles)):
			print(prices[x]+' ...... '+articles[x])


	def tearDown(self):
		self.driver.close()

if __name__ == "__main__":
	unittest.main()
import unittest
from selenium import webdriver
from time import sleep

class SearchMercadolibre(unittest.TestCase):

    def setUp (self):
        self.driver = webdriver.Chrome(executable_path = r'G:\Augusto\Selenium\chromedriver.exe')
        driver = self.driver
        driver.implicitly_wait(30)
        driver.maximize_window()
        driver.get("http://www.mercadolibre.com")

    def test_search_ps4(self):
        driver = self.driver

        country = driver.find_element_by_id('CO')
        country.click()

        search_field = driver.find_element_by_name('as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)

        locatation = driver.find_element_by_partial_link_text('Bogotá D.C.')
        locatation.click()
        sleep(3)

        condition = driver.find_element_by_partial_link_text('Nuevo')
        condition.click()
        sleep(3)

        order_menu = driver.find_element_by_class_name('ui-dropdown__link')
        order_menu.click()
        
        higher_price = driver.find_element_by_css_selector('#inner-main > aside > section.view-options > dl > div > div > div > div > ul > li.ui-list__item.ui-list__item--selected > span')
        higher_price.click()
        sleep(3)

        articles = []
        prices = []

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div[2]/div/h2/a/span').text
            articles.append(article_name)
            article_price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div[2]/div/div[1]/div/span[2]').text
            prices.append(article_price)

        print(articles, prices)
            

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main(verbosity = 2)```

Me sale el error: selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".ui-dropdown__link"}
  (Session info: chrome=83.0.4103.116)

No se que esta mal, alguien me ayuda pls

Mucho cuidado con el botón de cookies. Como bien es sabido, el chromedriver ejecuta en incógnito. Cuando tú estás revisando mucho ojo, porque cuando exploras, lo haces hasta con tu cuenta ya ingresada, y claro, con las cookies ya guardadas. Pero es muy diferente, cuando ingresas en incógnito, porque allí te pide que o aceptes o rechaces las cookies, por ser la “primera vez” que ingresas.

Para ello, debes poner este código dentro del ejercicio de la clase:

Después de buscar el playstation y antes de hacer el filtro de ubicación:

cookies_in = driver.find_element_by_xpath("/html/body/div[2]/div[1]/div[2]/button[1]")
cookies_in.click()
sleep(3)

Y eso es todo, te funcionará perfecto.

++Consejo: ++ Al hacer un script de automatización y que vayas haciendo la exploración de la página web, realiza la exploración en incógnito, pues así garantizas el comportamiento normal que se tendría con el chromedriver, que es una especie de incógnito.

Espero les sirva…

Me he tomado una buena cantidad de tiempo para hacer el código, para agregarle varias cositas:

  • Busqueda de Productos con cualquier cantidad y filtros
  • Ingresar los productos usando ddt y un archivo .csv
  • Una semi metolodogía de POM, no lo termine de entender bien, pero es cómo un
    obj que nos permite hacer diferentes metodos y tiene propiedades sobre una página para hacer el testing.

Lo que más me costo fue ubicar bien los elementos, ya que me estaba dando algún que otro problema con los xpath que tiene MercadoLibre y en general, tampoco tienen la mejor estructura.

Código:

test_mercado_libre.py

#!/usr/bin/python

import unittest
from csv import reader as csv_reader
from ddt import ddt, data, unpack
from selenium import webdriver
from mercado_libre_page import MercadoLibrePage

def get_csv_data (csv_url):
    rows = []

    with open(csv_url, encoding="UTF-8", mode="r") as csv_file:
        reader = csv_reader(csv_file)
        next(reader, None)

        for row in reader:
            rows.append(row)

    return rows

def convert_filters_to_dict (filters_arr, separator=':'):
    filter_dict = {}

    for value in filters_arr:
        filter_name, filter_value = value.split(separator)

        filter_dict[filter_name] = filter_value

    return filter_dict

@ddt
class MercadoLibreTests (unittest.TestCase):
    @classmethod
    def setUp (cls):
        cls.options = webdriver.ChromeOptions()
        cls.options.binary_location = '/usr/bin/brave'
        cls.driver = webdriver.Chrome(executable_path='/home/bl4ky113/bin/chromedriver', options=cls.options)
        cls.driver.maximize_window()

    @data (*get_csv_data('./product_info.csv'))
    @unpack

    def test_search_elements (self, element, num_elements, *filters):
        mercadolibre = MercadoLibrePage(self.driver)
        filter_dict = convert_filters_to_dict(filters)

        mercadolibre.open_contry_page()
        mercadolibre.search_product(element)
        
        for filter_name, filter_value in filter_dict.items():
            if filter_name == "Orden":
                mercadolibre.filter_by(filter_value)
            else:
                mercadolibre.add_filter(filter_name, filter_value)

        product_list = mercadolibre.get_product_list(int(num_elements))

        print(*product_list)

    @classmethod
    def tearDown (cls):
        cls.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

mercado_libre_page.py

#!/usr/bin/python

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

class MercadoLibrePage (object):
    def __init__ (self, driver):
        self._driver = driver
        self._url = "https://mercadolibre.com/"
        self._country_name = "Colombia"
        self._country_code = "co"
        self.search_locator = 'as_word'

    @property
    def is_in_country_page (self):
        return f".com.{self._country_code}" in self._driver.current_url

    @property
    def _len_special_filters (self):
        if not self.is_in_country_page:
            return None

        WebDriverWait(self._driver, 10).until(
            EC.presence_of_element_located(
                (By.XPATH, '//*[@id="root-app"]/div/div/aside/div[3]/div[1]/ul/li/section')
            )
        )

        len_special_filters = len(self._driver.find_elements_by_xpath(
            '//*[@id="root-app"]/div/div/aside/div[3]/div/ul/li/section'
        ))

        return len_special_filters

    @property
    def _available_filters (self):
        if not self.is_in_country_page:
            return None

        WebDriverWait(self._driver, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, '//*[@id="root-app"]/div/div/aside/div[3]/div[5]/ul/li[1]/form/button')
            )
        )

        filter_titles = self._driver.find_elements_by_xpath(
            '//*[@id="root-app"]/div/div/aside/div[3]/div/div'
        )

        return filter_titles

    def _open_url (self):
        self._driver.get(self._url)

    def _get_filter_options (self, filter_index):
        if not self.is_in_country_page:
            return None

        filter_options_names = self._driver.find_elements_by_xpath(
            f'//*[@id="root-app"]/div/div/aside/div[3]/div[{filter_index}]/ul/li/form/button/span[1]'
        )
        filter_options_btn = self._driver.find_elements_by_xpath(
            f'//*[@id="root-app"]/div/div/aside/div[3]/div[{filter_index}]/ul/li/form/button'
        )

        filter_options = {
            filter_options_names[i].text: filter_options_btn[i]
            for i in range(len(filter_options_names))
        }

        return filter_options

    def _get_order_options (self):
        WebDriverWait(self._driver, 10).until(
            EC.presence_of_element_located(
                (By.XPATH, '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul')
            )
        )

        filter_options_names = self._driver.find_elements_by_xpath(
            '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul/a/div[1]/span'
        )
        filter_options_obj = self._driver.find_elements_by_xpath(
            '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul/a'
        )

        filter_options = {
            filter_options_names[i].text: filter_options_obj[i]
            for i in range(len(filter_options_names))
        }

        return filter_options

    def _open_order_by_dropdown (self):
        if not self.is_in_country_page:
            return None

        filter_by_input = self._driver.find_element_by_xpath(
            '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/button'
        )
        self._js_click(filter_by_input)

    def _get_product_info (self, product, product_index):
        product_info = {}
        product_info["name"] = self._driver.find_element_by_xpath(
            f'//*[@id="root-app"]/div/div/section/ol/li[{product_index}]/div/div/div[2]/div[1]/a[1]/h2'
        ).text
        product_info["value"] = self._driver.find_element_by_xpath(
            f'//*[@id="root-app"]/div/div/section/ol/li[{product_index}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/div/span[1]/span[2]/span[2]'
        ).text

        return product_info

    def _get_products (self, size_of_the_list):
        product_list = []
        product_index = 1

        while len(product_list) <= size_of_the_list:
            product = self._driver.find_element_by_xpath(
                f'//*[@id="root-app"]/div/div/section/ol/li[{product_index}]'
            )
            product_info = self._get_product_info(product, product_index)

            product_list.append(product_info)
            product_index += 1

        return product_list

    def _js_click(self, element):
        self._driver.execute_script('arguments[0].click()', element)

    def open_contry_page (self):
        self._open_url()

        WebDriverWait(self._driver, 10).until(
            EC.presence_of_element_located(
                (By.ID, self._country_code.upper())
            )
        )

        self._driver.find_element_by_id(self._country_code.upper()).click()

        return self.is_in_country_page

    def search_product (self, product_keyword):
        if not self.is_in_country_page:
            return None

        search_input = self._driver.find_element_by_name(self.search_locator)
        search_input.send_keys(product_keyword)
        search_input.submit()

    def add_filter (self, name, value):
        if not self.is_in_country_page:
            return None

        filter_index = 1 + self._len_special_filters
        for filter_ in self._available_filters:
            if filter_.text == name:
                filter_options = self._get_filter_options(filter_index)
                self._js_click(filter_options[value])
                break

            filter_index += 1

    def filter_by (self, order):
        if not self.is_in_country_page:
            return None

        self._open_order_by_dropdown()
        filter_options = self._get_order_options()

        self._js_click(filter_options[order])

    def get_product_list (self, number_of_elements):
        if not self.is_in_country_page:
            return None

        product_list = self._get_products(number_of_elements)

        return product_list

Y el .csv

ProductName,NumberOfProducts,Filers*
xbox one s,5,Condición:Nuevo,Orden:Mayor precio,Ubicación:Bogotá D.C.
playstation 4,5,Condición:Usado,Orden:Menor precio 

El 4to artículo por alguna razón me complicaba el scraping. Tuve que cambiar un poco el código 😓

El código refactorizado (revisar el comentario de abajo) utilizando los cambios que haría. Espero que le sea de utilidad a la hora de crear automatizaciones a alguien más.

Archivo de constantes:

from selenium.webdriver.common.by import By
from string import Template

#Url principal del sitio a accesar.
URL = 'https://www.mercadolibre.com'
#Busqueda a realizar.
SEARCH = 'playstation 4'
#Tiempo de espera por acción.
TIME_FOR_ACTION = 1

#País.
COUNTRY = (By.ID, 'CO')
#Campo de busqueda.
SEARCH_FIELD = (By.NAME, 'as_word')
#Locación.
LOCATION = (By.XPATH, '//button[@aria-label="Bogotá D.C."]')
#Condición: Nuevo, Usado o Reacondicionado. 
CONDITION = (By.XPATH, '//button[@aria-label="Nuevo"]')
#Menu (dropdown) de Ordenar por.
ORDER_MENU = (By.CLASS_NAME, 'andes-dropdown__trigger')
#Opción del menu: Mayor precio.
HIGHER_PRICE = (By.PARTIAL_LINK_TEXT, 'Mayor precio')

#Articulos de compra.
ARTICLES = (By.CLASS_NAME, 'ui-search-item__title')
#Xpath general de los precios.
PRICES_XPATH = Template('//*[@id="root-app"]/div/div/section/ol/li[$num]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/div/span[1]/span[2]/span[2]')
#Precios de los articulos.
PRICES = (By.XPATH, PRICES_XPATH)

#True si se cliquea de forma estandar.
#False si se cliquea mediante Javascript.
CLICKABLE = {
    'country' : True,
    'search_field' : True,
    'location' : False,
    'condition' : False,
    'order_menu' : True,
    'higher_price' : False,
}

Archivo de testing:

#Para los tests.
import unittest
from pyunitreport import HTMLTestRunner

#Paras la automatización.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

#Excepción al no encontrar un elemento Web.
from selenium.common.exceptions import NoSuchElementException

#Para las pausas.
from time import sleep

#Cargamos las constantes.

#Texto.
from merc_constantes import URL, SEARCH, TIME_FOR_ACTION
#Elementos a usar.
from merc_constantes import COUNTRY, SEARCH_FIELD, CONDITION, LOCATION, ORDER_MENU,  HIGHER_PRICE
#Elementos a leer.
from merc_constantes import ARTICLES, PRICES
#Si se cliquea de forma estandar o no.
from merc_constantes import CLICKABLE

service = Service(r'C:\Users\carlo\Desktop\chromedriver_win32\chromedriver.exe')

class TestingMercadoLibre(unittest.TestCase):

    def setUp(self):
        driver = self.driver = webdriver.Chrome(service=service)
        driver.get(URL)
        driver.maximize_window()

    #Cuando no funciona el click mediante Webdriver, usamos javascript.
    #https://www.selenium.dev/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script
    def click_javascript(self, web_element):
        self.driver.execute_script("arguments[0].click();", web_element)

    #Metodo para definir el tipo de clickeo en el elemento web.
    def click_WD(self, web_element, clickable):
        if clickable:
            web_element.click()
        else:
            self.click_javascript(web_element)

    #Metodo para reducir la acción de seleccionar
    # y clickear a una sola función.
    def select_and_click(self, terms, clickable):
        web_element = self.driver.find_element(*terms)
        self.click_WD(web_element, clickable)
        return web_element

    def test_search_ps4(self):
        driver = self.driver
        s_c = self.select_and_click

        #Seleccionamos Colombia.
        s_c(COUNTRY, CLICKABLE['country'])

        #Seleccionamos el buscador, limpiamos, escribimos y buscamos.
        search_field = s_c(SEARCH_FIELD, CLICKABLE['search_field'])
        search_field.clear()
        search_field.send_keys(SEARCH)
        search_field.submit()
        sleep(TIME_FOR_ACTION)

        #Filtramos por locación: Bogotá.
        s_c(LOCATION, CLICKABLE['location'])
        sleep(TIME_FOR_ACTION)

        #Filtramos por antiguedad: Nuevo.
        s_c(CONDITION, CLICKABLE['condition'])
        sleep(TIME_FOR_ACTION)

        #Cliqueamos el dropdown de Ordenar por.
        s_c(ORDER_MENU, CLICKABLE['order_menu'])

        #Ordenamos por: Mayor precio.
        s_c(HIGHER_PRICE, CLICKABLE['higher_price'])
        sleep(TIME_FOR_ACTION)
        
        #Creamos un diccionario con los articulos de la pagina actual
        #como llaves por poseer una clase en común.
        articles_prices = {i.text:None for i in driver.find_elements(*ARTICLES)}

        #Buscamos el precio correspondiente a cada articulo.
        #Como tanto los precios, como las cuotas poseen 
        #las mismas clases, los precios deben o filtrarse,
        #o como en el caso actual usar el Xpath.
        for i, article in enumerate(articles_prices.keys()):
            #Existen articulos sin el precio explicito.            
            try:
                p_method = PRICES[0]
                p_key = PRICES[1].substitute(num=i + 1)
                price = driver.find_element(p_method, p_key).text
            except NoSuchElementException:
                price = 'No disponible'

            #Almacenamos el precio perteneciente al articulo actual.
            articles_prices[article] = price

        #Mostramos los primeros 5 articulos en pantalla.
        #Pero podemos mostrarlos todos si queremos.
        articles_to_show = 5
        for article, price in list(articles_prices.items())[:articles_to_show]:
            print(article, ' : ', price)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity = 2, testRunner = HTMLTestRunner(output = 'reports', report_name = 'ml-report'))

Aportó el código comentado para el 17/3/2022

**Hice algunos cambios:
**

  • Cree un nuevo método que contiene el cliqueo mediante javascript, que es el método que ya han comentado si no funciona elemento.click()
  • Para la Locación y la Antigüedad uso el Xpath, con el atributo aria-label. Me pareció el método más corto y fácil de adaptar.
  • La clase del Dropdown cambio.
  • Para el ‘Mayor precio’, use partial_link_text, es más corto que el selector de css.
  • Use un diccionario como recomendó otro usuario, para artículos y precios. Y los guarda todos por defecto.
  • Para los artículos use una clase que poseían en común.
  • Para los precios no pude hacer esto, así que use el Xpath y un for.
  • Como algunos elementos no tenían precio disponible, use una try-except para integrarlos en el diccionario.
  • Hay una variable con la cantidad de artículos y precios a visualizar.

**Cambios que haría si fuera un script de uso frecuente: **

  • En un archivo anexo guardar las siguiente constantes:
  1. Método de búsqueda (Clase, ID, Xpath, etc), la clave para dicha búsqueda. [Así si un método falla o una clave es cambiada, se puede reemplazar con facilidad]. En una tupla, luego se desempaqueta en find_element.
  2. ¿Click “estándar” o Click Javascript? Así como los elementos cambian de método y clave. También pueden dejar de ser cliqueables por el método estándar. Por lo que puede generarse otro método de clase al cual se le pasaría como argumento el “elemento a cliquear” y un booleano de “click estandar sí o no”, de ese paso en particular. Así podrían alternarse los clicks, volver uno de javascript al estandar y viceversa. Estas variables booleanas serian las que se almacenarían como constantes (Otra alternativa sería pasar todos los Clicks Estandar a Click Javascript, si no se tienen problemas con esto, aunque no lo prefiero por eficiencia y limpieza de código).
  3. La cantidad de artículos y precios a mostrar.

Con esto para pequeños cambios debería seguir funcionando en el tiempo y las modificaciones serían pequeñas y fáciles de aplicar.

#Para los tests.
import unittest
from pyunitreport import HTMLTestRunner

#Paras la automatización.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

#Excepción al no encontrar un elemento Web.
from selenium.common.exceptions import NoSuchElementException

#Para las pausas.
from time import sleep

service = Service(r'C:\Users\carlo\Desktop\chromedriver_win32\chromedriver.exe')

class TestingMercadoLibre(unittest.TestCase):

    def setUp(self):
        driver = self.driver = webdriver.Chrome(service=service)
        driver.get('https://www.mercadolibre.com')
        driver.maximize_window()

    #Cuando no funciona el click mediante Webdriver, usamos javascript.
    #https://www.selenium.dev/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script
    def click_javascript(self, web_element):
        self.driver.execute_script("arguments[0].click();", web_element)

    def test_search_ps4(self):
        driver = self.driver

        #Seleccionamos Colombia.
        country = driver.find_element(By.ID, 'CO')
        country.click()

        #Seleccionamos el buscador, limpiamos, escribimos y buscamos.
        search_field = driver.find_element(By.NAME, 'as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)

        #Filtramos por locación: Bogotá.
        xpath_l = '//button[@aria-label="Bogotá D.C."]'
        location = driver.find_element(By.XPATH, xpath_l)
        #location.click()
        self.click_javascript(location)
        sleep(3)

        #Filtramos por antiguedad: Nuevo.
        xpath_c = '//button[@aria-label="Nuevo"]'
        condition = driver.find_element(By.XPATH, xpath_c)
        #condition.click()
        self.click_javascript(condition)
        sleep(3)

        #Cliqueamos el dropdown de Ordenar por.
        order_menu = driver.find_element(By.CLASS_NAME, 'andes-dropdown__trigger')
        order_menu.click()

        #Ordenamos por: Mayor precio.
        higher_price = driver.find_element(By.PARTIAL_LINK_TEXT, 'Mayor precio')
        #higher_price.click()
        self.click_javascript(higher_price)
        sleep(3)
        
        #Creamos un diccionario con los articulos de la pagina actual
        #como llaves por poseer una clase en común.
        articles_prices = {i.text:None for i in driver.find_elements(By.CLASS_NAME, 'ui-search-item__title')}

        #Buscamos el precio correspondiente a cada articulo.
        #Como tanto los precios, como las cuotas poseen 
        #las mismas clases, los precios deben o filtrarse,
        #o como en el caso actual usar el Xpath.
        for i, article in enumerate(articles_prices.keys()):
            xpath_ap = f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/div/span[1]/span[2]/span[2]'

            #Existen articulos sin el precio explicito.            
            try:
                price = driver.find_element(By.XPATH, xpath_ap).text
            except NoSuchElementException:
                price = 'No disponible'

            #Almacenamos el precio perteneciente al articulo actual.
            articles_prices[article] = price

        #Mostramos los primeros 5 articulos en pantalla.
        #Pero podemos mostrarlos todos si queremos.
        articles_to_show = 5
        for article, price in list(articles_prices.items())[:articles_to_show]:
            print(article, ' : ', price)

    def tearDown(self):
        self.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity = 2, testRunner = HTMLTestRunner(output = 'reports', report_name = 'ml-report'))

No pude obtener los textos de la tabla desde el xpath

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

class MercadoLibreTest(unittest.TestCase):
    
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=r'C:/Users/Usuario/Documents/platzi/python/Clases del Curso de Introducción a Selenium con Python/chromedriver.exe')
        driver = self.driver
        driver.get('https://mercadolibre.com')
        driver.maximize_window()
    
    def test_seach_ps4(self):
        driver = self.driver

        #Paso 1
        driver.find_element(By.ID, 'CO').click()

        #Paso 2
        field_search = driver.find_element(By.NAME, 'as_word')
        field_search.click()
        field_search.clear()
        field_search.send_keys('playstation 4')
        field_search.submit()
        sleep(3)

        #Paso 3
        location = driver.find_element(By.PARTIAL_LINK_TEXT, 'Bogotá D.C.')
        driver.execute_script("arguments[0].click();", location)
        sleep(3)

        #Paso 4
        condition = driver.find_element(By.PARTIAL_LINK_TEXT, 'Nuevo')
        driver.execute_script("arguments[0].click();", condition)
        sleep(3)

        #Paso 5
        order_menu = driver.find_element(By.CLASS_NAME, 'andes-dropdown__trigger')
        order_menu.click()
        higher_price = driver.find_element(By.CSS_SELECTOR, '#root-app > div > div > section > div.ui-search-view-options__container > div > div > div > div.ui-search-sort-filter > div > div > div > ul > a:nth-child(3) > div.andes-list__item-first-column > div.andes-list__item-text > div')
        higher_price.click()
        sleep(3)

        #Paso 6
        articles = []
        prices = []

        # for i in range(5):
        #     article_name = driver.find_element(By.XPATH, f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/a/h2').text
        #     articles.append(article_name)
        #     article_price = driver.find_element(By.XPATH, f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[3]/div[1]/div[1]/div/div/div/span[1]/span[2]/span[2]').text
        #     prices.append(article_price)

        # print(articles, prices)

        table_elements_li = driver.find_elements(By.CSS_SELECTOR, '#root-app > div > div > section > ol > li')

        count_find_items = len(table_elements_li)

        item = 1
        while ((count_find_items > 5 and item <= 5) or (count_find_items <= 5 and item != count_find_items)):
            table_title_element = table_elements_li[item - 1].find_element(By.CLASS_NAME, 'ui-search-item__title').text
            table_simbol_price_element = table_elements_li[item - 1].find_element(By.CLASS_NAME, 'price-tag-symbol').text
            table_price_element = table_elements_li[item - 1].find_element(By.CLASS_NAME, 'price-tag-fraction').text
            articles.append(table_title_element)
            prices.append(table_simbol_price_element + ' ' + table_price_element)
            item += 1

        print(articles, prices)
        sleep(3)


    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

Comparto mi codigo!. Muchas gracias

import unittest
from selenium import webdriver
from time import sleep

class MercadoLibre(unittest.TestCase):
    

    def setUp(self):
        self.driver = webdriver.Chrome("D:\webdriver-chrome/chromedriver.exe")
        driver = self.driver
        driver.implicitly_wait(15)
        driver.maximize_window()
        driver.get('https://mercadolibre.com')
        
    def test_search_ps4(self):
        driver = self.driver
        country = driver.find_element_by_id('CO')
        country.click()
        sleep(3)

        search_field = driver.find_element_by_name('as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)


        location = driver.find_element_by_partial_link_text('Bogotá D.C.')
        driver.execute_script("arguments[0].click();", location)
        sleep(3)

        condition = driver.find_element_by_partial_link_text('Nuevo')
        driver.execute_script("arguments[0].click();", condition)
        sleep(3)

        order_menu = driver.find_element_by_class_name('andes-dropdown__trigger')
        order_menu.click()
        higher_price = driver.find_element_by_css_selector('#root-app > div > div > section > div.ui-search-view-options__container > div > div > div > div.ui-search-sort-filter > div > div > div > ul > a:nth-child(3) > div.andes-list__item-first-column > div.andes-list__item-text > div')
        higher_price.click()
        sleep(3)

        articles = []
        prices = []

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[1]/a/h2').text
            articles.append(article_name)
            article_price = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]/span[2]').text
            prices.append(article_price)

        print(articles,prices)

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main(verbosity = 2)

El TestCase es el siguiente

import unittest
from selenium import webdriver
from mercado_page import MercadoPage


class MercadoTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.driver = webdriver.Chrome(executable_path=r'./chromedriver.exe')
        cls.driver.maximize_window()
    
    def test_search(self):
        mercado = MercadoPage(self.driver)
        mercado.open()
        mercado.select_country('Colombia')
        mercado.type_search('playstation 4')
        mercado.click_submit()
        mercado.acepted_politcal()
        mercado.select_filter('Nuevo')
        mercado.select_filter('Bogotá D.C.')
        mercado.order_by()
        mercado.get_five_productos()

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

Para el page use

from selenium.webdriver.common.by import By


class MercadoPage(object):

    def __init__(self, driver):
        self.driver = driver
        self.url = 'https://www.mercadolibre.com'
        self.search_locator = 'as_word'
    
    def open(self):
        self.driver.get(self.url)
        self.driver.maximize_window()

    def select_country(self, country):
        country = self.driver.find_element(By.LINK_TEXT, country)
        country.click()

    def type_search(self, keywords):
        text_field = self.driver.find_element(By.NAME, self.search_locator)
        text_field.send_keys(keywords)

    def click_submit(self):
        text_field = self.driver.find_element(By.NAME, self.search_locator)
        text_field.submit()
    
    def acepted_politcal(self):
        acepted = self.driver.find_element(By.ID, 'newCookieDisclaimerButton')
        acepted.click()
        close = self.driver.find_element(By.CLASS_NAME, 'andes-tooltip-button-close')
        close.click()
    def select_filter(self, filter):
        column_filter = self.driver.find_element(By.CSS_SELECTOR, '#root-app > div > div > aside')
        filter_select = column_filter.find_element(By.PARTIAL_LINK_TEXT, filter)
        filter_select.click()
    
    def order_by(self):
        button_order = self.driver.find_element(By.XPATH, '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/button')
        button_order.click()
        field_order = self.driver.find_element(By.XPATH, '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul/a[2]')
        field_order.click()
    
    def get_five_productos(self):
        products = self.driver.find_elements(By.CLASS_NAME, 'ui-search-layout__item')
        for i in range(5):
            product = products[i].find_element(By.CLASS_NAME, 'price-tag-fraction')
            print(product.text)

El mejor curso que he visto, que crack Héctor

Aquí mi código! Usando try y except en caso de que te salga un artículo recomendado (cambian sus nodos en la estructura de HTML), usando un diccionarios en lugar de solo listas, etc.

import unittest
from selenium import webdriver
from time import sleep
from selenium.common.exceptions import NoSuchElementException

class TestingMercadoLibre(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome(executable_path='./chromedriver')
        driver = self.driver
        driver.get('https://mercadolibre.com/')
        driver.maximize_window()
    
    def test_search_ps4(self):
        driver = self.driver

        country = driver.find_element_by_id('CO')
        country.click()

        search_field = driver.find_element_by_name('as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)

        location = driver.find_element_by_partial_link_text('Bogotá D.C.')
        # location.click()
        driver.execute_script("arguments[0].click();", location)
        sleep(3)

        condition = driver.find_element_by_partial_link_text('Nuevo')
        # condition.click()
        driver.execute_script("arguments[0].click();", condition)
        sleep(3)

        order_menu = driver.find_element_by_class_name(
            'andes-dropdown__trigger'
            )
        order_menu.click()
        higher_price = driver.find_element_by_xpath(
            '//*[@id="root-app"]/div/div/section/div[1]/div/div/div/div[2]/div/div/div/ul/a[2]/div[2]/div[2]/div'
            )
        higher_price.click()
        sleep(3)

        articles = []
        
        for i in range(5):
            try:
                article_name = driver.find_element_by_xpath(
                    f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a/h2'
                    ).text 
                article_price = driver.find_element_by_xpath(
                    f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/a/div/div/span[1]/span[2]/span[2]'
                    ).text
            except NoSuchElementException:
                article_name = driver.find_element_by_xpath(
                    f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/a/h2'
                    ).text
                article_price = driver.find_element_by_xpath(
                    f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[3]/div[1]/div[1]/a/div/div/span[1]/span[2]/span[2]'
                    ).text
            
            article = {'name': article_name, 'price': article_price}
            articles.append(article)
        print(articles)

    
    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2) 

Un poco diferente, evitando los xPaths:

import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By


class TestMercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path=r'chromedriver')
        driver = self.driver
        driver.implicitly_wait(10)
        driver.maximize_window()
        driver.get("https://www.mercadolibre.com/")

    def test_search_in_mercadolibre(self):
        self.driver.find_element(By.ID, "CO").click()
        driver = self.driver
        driver.implicitly_wait(5)
        search_field = driver.find_element(By.NAME, "as_word")
        search_field.click()
        search_field.clear()
        search_field.send_keys("playstation 4")
        search_field.submit()
        city = driver.find_element(By.PARTIAL_LINK_TEXT, "Bogotá D.C.")
        driver.execute_script("arguments[0].click();", city)
        state = driver.find_element(By.PARTIAL_LINK_TEXT, "Nuevo")
        driver.execute_script("arguments[0].click();", state)
        articles = driver.find_elements(By.CLASS_NAME, "ui-search-item__title")
        prices = driver.find_elements(By.CLASS_NAME, "price-tag-fraction")
        for i in range(5):
            print(f'Artículo {i+1}:{articles[i].text}, {prices[i].text}')
        print(results)

    def tearDown(self):
        self.driver.close()


if __name__ == "__main__":
    unittest.main(verbosity=2)

Me tomo tiempo, pero aquí está mi código.

import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class MercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(service=Service('./chromedriver'))
        driver = self.driver
        driver.implicitly_wait(30)
        driver.maximize_window()
        # 1 go to ML
        driver.get('https://mercadolibre.com/')

    def test_tecnique(self):
        driver = self.driver
        country = driver.find_element(By.ID, 'MX')
        country.click()
        # 2 select country is MX
        self.assertTrue('mx' in self.driver.current_url)

        search_field = driver.find_element(By.NAME, 'as_word')
        search_field.clear()
        search_field.send_keys('Playstation 4')
        search_field.submit()
        # 3 search playstation 4
        # self.asserTrue()

        condition_new = driver.find_element(By.PARTIAL_LINK_TEXT, 'Nuevo')
        driver.execute_script("arguments[0].click();", condition_new)       
        # 4 filter by condition Nuevos
        
        # 5 filter by location Nuevo León 
        location_state = driver.find_element(By.PARTIAL_LINK_TEXT, 'Nuevo León')
        driver.execute_script("arguments[0].click();", location_state)       

        menu_order = driver.find_element(By.XPATH, '//*[@id="root-app"]/div/div[1]/section/div[1]/div/div/div/div[2]')
        menu_order.click()
        higher_price = driver.find_element(By.XPATH,'//*[@id="root-app"]/div/div[1]/section/div[1]/div/div/div/div[2]/div/div/div/ul/a[2]')
        higher_price.click()
        # 6 sort by mayor to menor precio

        articles = []
        prices = []

        for i in range(5):
            if i == 0:
                article_name = driver.find_element(By.XPATH,f'/html/body/main/div/div[1]/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/a/h2').text
                articles.append(article_name)
            elif i < 4 and i > 0:
                article_name = driver.find_element(By.XPATH,f'/html/body/main/div/div[1]/section/ol/li[{i + 2}]/div/div/div[2]/div[1]/a/h2').text
                articles.append(article_name)
            else:
                article_name = driver.find_element(By.XPATH,f'/html/body/main/div/div[1]/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a[1]/h2').text
                articles.append(article_name)

        for j in range(5):
            if j == 0:
                article_price = driver.find_element(By.XPATH,f'/html/body/main/div/div[1]/section/ol/li[{j + 1}]/div/div/div[2]/div[3]/div[1]/div[1]/a/div/div/span[1]/span[2]/span[2]').text
                prices.append(article_price)
            elif j > 0 and j < 3:
                article_price = driver.find_element(By.XPATH, f'/html/body/main/div/div[1]/section/ol/li[{j + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/a/div/div/span[1]/span[2]/span[2]').text
                prices.append(article_price)
            else:
                article_price = driver.find_element(By.XPATH, f'/html/body/main/div/div[1]/section/ol/li[{j + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]/span[2]').text
                prices.append(article_price)
        print(articles, prices)
        # 7 get name and price of first 5


    def tearDown(self):
        self.driver.implicitly_wait(3)
        self.driver.close()

if __name__ == '__main__':
    unittest.main(verbosity = 2)

Yo lo hice en wallapop (es como el OLX de España)
También agregue aceptar cookies, enviar ENTER en vez de submit() y por ultimo una lista llamada products que contiene tuplas donde tiene estructurada la información de la siguiente manera: (item, precio)

import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep

class WallaTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path=r'./chromedriver.exe')
        driver = cls.driver
        driver.implicitly_wait(20)
        driver.maximize_window()
        driver.get('https://es.wallapop.com/')

    def test_walla(self):
        driver = self.driver

        accept_cks = driver.find_element_by_id('didomi-notice-agree-button')
        accept_cks.click()

        search_field = driver.find_element_by_name('searchKeyword')
        search_field.click()
        search_field.clear()
        search_field.send_keys('Nintendo Switch')
        search_field.send_keys(Keys.ENTER)

        location = driver.find_element_by_css_selector('body > tsl-root > tsl-public > tsl-search > div > div > tsl-filters-wrapper > div > div > tsl-filter-group > div > div:nth-child(4) > tsl-filter-host > div > tsl-location-filter > tsl-filter-template > div > tsl-bubble > div > div > div')
        location.click()
        search_loc =driver.find_element_by_xpath('/html/body/tsl-root/tsl-public/tsl-search/div/div/tsl-filters-wrapper/div/div[2]/tsl-filter-group/div/div[4]/tsl-filter-host/div/tsl-location-filter/tsl-filter-template/div/div/div[2]/div/tsl-drawer-placeholder-template/div/div/div[1]/input')
        search_loc.click()
        search_loc.clear()
        search_loc.send_keys('Tarragona')
        sleep(2)
        apply_loc = driver.find_element_by_css_selector('body > tsl-root > tsl-public > tsl-search > div > div > tsl-filters-wrapper > div > div.FiltersWrapper__bar.d-flex.pl-3.py-2.FiltersWrapper__bar--opened > tsl-filter-group > div > div:nth-child(4) > tsl-filter-host > div > tsl-location-filter > tsl-filter-template > div > div > div.FilterTemplate__actions.px-4.d-flex.align-items-center.justify-content-end > tsl-button:nth-child(2) > button')
        apply_loc.click()
        sleep(2)

        products = []

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'/html/body/tsl-root/tsl-public/tsl-search/div/tsl-search-layout/div/div[2]/div/tsl-public-item-card-list/div/a[{i+1}]/tsl-public-item-card/div/div[2]/div[2]/p[1]').text
            price = driver.find_element_by_xpath(f'/html/body/tsl-root/tsl-public/tsl-search/div/tsl-search-layout/div/div[2]/div/tsl-public-item-card-list/div/a[{i+1}]/tsl-public-item-card/div/div[2]/div[1]/span').text
            product = (article_name, price)
            products.append(product)

        print(products)
    

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ =='__main__':
    unittest.main(verbosity=2) 

Práctica a la fecha 17-10-2021

import unittest

from time import sleep
from selenium import webdriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.by import By

from common import SERVICE
from common import CHROME_OPTIONS

class MercadoLibreTestCase(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        cls.driver = webdriver.Chrome(
            service=SERVICE,
            options=CHROME_OPTIONS,
        )
        cls.driver.get('https://mercadolibre.com/')
        cls.driver.maximize_window()
        cls.driver.implicitly_wait(1)

    def test_search_ps4(self):
        country: WebElement
        country = self.driver.find_element(By.ID, 'CO')
        country.click()

        sleep(1)

        search_field: WebElement
        search_field = self.driver.find_element(By.NAME, 'as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        
        sleep(1)

        location: WebElement
        location = self.driver.find_element(By.PARTIAL_LINK_TEXT, 'Bogotá D.C.')
        self.driver.execute_script("arguments[0].click();", location)

        sleep(1)

        condition: WebElement
        condition = self.driver.find_element(By.PARTIAL_LINK_TEXT, 'Nuevo')
        self.driver.execute_script("arguments[0].click();", condition)

        sleep(1)

        order_menu: WebElement
        order_menu = self.driver.find_element(By.CLASS_NAME, 'andes-dropdown__trigger')
        order_menu.click()

        higher_price_sort: WebElement
        higher_price_sort = self.driver.find_element(By.CSS_SELECTOR, '#root-app > div > div > section > div.ui-search-view-options__container > div > div > div > div.ui-search-sort-filter > div > div > div > ul > a:nth-child(3)')
        higher_price_sort.click()

        sleep(1)

        items = []

        for i in range(5):
            item_title = self.driver.find_element(By.CSS_SELECTOR, f'#root-app > div > div > section > ol > li:nth-child({i + 1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-item__group.ui-search-item__group--title > a > h2').text
            item_price = self.driver.find_element(By.CSS_SELECTOR, f'#root-app > div > div > section > ol > li:nth-child({i + 1}) > div > div > div.ui-search-result__content-wrapper > div.ui-search-result__content-columns > div.ui-search-result__content-column.ui-search-result__content-column--left > div.ui-search-item__group.ui-search-item__group--price > a > div > div > span.price-tag.ui-search-price__part > span.price-tag-amount > span.price-tag-fraction').text

            items.append((item_title, item_price))

        print(items)

    @classmethod
    def tearDownClass(cls) -> None:
        cls.driver.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)

[Solucion] Element click intercepted

webdriver.ActionChains(driver).move_to_element(location).click(location).perform()

También estuve revisando y si damos click en el aviso de privacidad, Realiza el click de forma correcta utilizando unicamente location.click()

Resolví así la prueba:

import unittest
from selenium import webdriver
from time import sleep

# Requerimientos
# Ir a mercado libre
# Filtrar por CL
# Buscar PS4
# Filtro RM, Nuevo
# Menor precio

class MercadoLibre(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome("./chromedriver")
        driver = self.driver
        driver.implicitly_wait(30)
        driver.maximize_window()
        driver.get("https://www.mercadolibre.com/")

    def clickMeWithJS(self, clickAble):
        self.driver.execute_script("arguments[0].click();", clickAble)

    def test_search_ps4(self):
        driver = self.driver
        country = driver.find_element_by_css_selector("#CL")
        country.click()

        search_field = driver.find_element_by_css_selector("body > header > div > form > input")
        search_field.click()
        search_field.clear()
        search_field.send_keys("ps4")
        search_field.submit()
        sleep(3)

        location = driver.find_element_by_partial_link_text('RM (Metropolitana)')
        #location.click()
        self.clickMeWithJS(location)
        sleep(3)

        condition = driver.find_element_by_partial_link_text('Nuevo')
        self.clickMeWithJS(condition)
        #condition.click()
        sleep(3)

        buttonDropDown = driver.find_element_by_css_selector('#root-app > div > div > section > div.ui-search-view-options__container > div > div > div > div.ui-search-sort-filter > div > div > button')
        buttonDropDown.click()
        sleep(3)

        ascPrice = driver.find_element_by_css_selector('#root-app > div > div > section > div.ui-search-view-options__container > div > div > div > div.ui-search-sort-filter > div > div > div > ul > li:nth-child(2) > a')
        ascPrice.click()
        sleep(3)

        objectsNames = driver.find_elements_by_class_name('ui-search-item__title')
        #objectsPrices = driver.find_elements_by_class_name('price-tag-fraction')
        size = len(objectsNames)
        res = dict()
        for i in range(size):
            x = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[1]/a/h2')
            y = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[2]/div[1]/div/div/div/span[1]/span[2]/span[2]')
            res[i] = {"name": x.text, "price": y.text}

        print(res)

        sleep(3)

    def tearDown(self):
        self.driver.close()

if __name__ == '__main__':
    unittest.main(verbosity=2)

La salida es la siguiente:

Quede bastante contento (Y), WEN PROFE

Si que tomó más tiempo esto. Pareciera que en la página de mercado libre la hacen excesivamente redundante y con divs vacíos para que sea difícil hacer esto. Aquí va mi versión antes de ver la solución y con ayuda de uno de los comentarios porque no podía hacer click en los filtros:

import unittest
from time import sleep
from pyunitreport import HTMLTestRunner
from selenium import webdriver
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 selenium.webdriver.support.select import Select

class AccessModals(unittest.TestCase):

    @classmethod
    def setUp(cls):
        options = Options()
        options.binary_location = '/snap/brave/119/opt/brave.com/brave/brave'
        cls.driver = webdriver.Chrome(options = options, executable_path="./chromedriver")
        driver = cls.driver
        driver.get("https://www.mercadolibre.com/")
        driver.maximize_window()
    
    def test_account_link(self):
        driver = self.driver
        driver.find_element(By.LINK_TEXT,"México").click()
        search_bar = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME,"as_word")))
        search_bar.clear()
        search_bar.send_keys("playstation 4")
        search_bar.submit()
        ln = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#root-app > div > div.ui-search-main > aside > section > dl:nth-child(19) > dd:nth-child(2) > a > span.ui-search-filter-name")))
        driver.execute_script("arguments[0].click();", ln)
        ll = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT,"Distrito Federal")))
        driver.execute_script("arguments[0].click();", ll)

        obtn = driver.find_element(By.CSS_SELECTOR,"#root-app > div > div.ui-search-main > section > div.ui-search-view-options__container > div > div > div.ui-search-view-options__group > div.ui-search-sort-filter > div > div > button")
        driver.execute_script("arguments[0].click();", obtn)
        lp = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT,"Menor precio")))
        driver.execute_script("arguments[0].click();", lp)
        WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.XPATH,'//*[@id="root-app"]/div/div[1]/section/div[1]/div/div/div[2]/div[1]/div/div/button'),"Menor precio"))

        products = driver.find_elements(By.CSS_SELECTOR,"ol.ui-search-layout.ui-search-layout--stack li")
        for i in range(5):
            product = products[i]
            title = product.find_element(By.TAG_NAME,"h2").text
            price = product.find_element(By.CSS_SELECTOR,"div.ui-search-item__group.ui-search-item__group--price a").text
            price = price.split(" ")[0]
            print((title, price))

    @classmethod
    def tearDown(cls):
        cls.driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2, testRunner=HTMLTestRunner(output="reportes", report_name="automatic_search"))

Para el tercer resultado de la búsqueda, el código XPath falla con “no such element: Unable to locate element” y me tocó hacer un caso especial:

for contador in range(5):
    if contador == 2:
        article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{contador + 1}]/div/div/div[2]/div[2]/a/h2').text
        articles.append(article_name)
        article_price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{contador + 1}]/div/div/div[2]/div[3]/div[1]/div[1]/div/div/span[1]/span[2]').text
        prices.append(article_price)
    else:
        article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{contador + 1}]/div/div/div[2]/div[1]/a/h2').text
        articles.append(article_name)
        article_price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{contador + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]').text
        prices.append(article_price)

yo lo hice usando lo POM, y me quedo asi:

esta sera la clase MercadoLibre.

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


class MercadoLibre(object):
    def __init__(self, driver):
        self._driver = driver
        self._url = 'https://www.mercadolibre.com/'
        self._country_list = 'ml-site-list'
        self.search_locator = 'q'
        
    @property
    def is_loaded(self):
        WebDriverWait(self._driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'ml-site-list')))
        return True
    
    # @property
    # def keyword(self):
    #     input_field = self._driver.find_element_by_name('q')
    #     return input_field.get_attribute('value')
    
    def open(self):
        self._driver.get(self._url)
        self._driver.maximize_window()
        self._driver.implicitly_wait(30)
        
    def typo_search(self, keyword):
        input_field = self._driver.find_element_by_xpath('//input[@class="nav-search-input"]')
        input_field.send_keys(keyword)
    
    def select_filter(self, filter_condition):
        filter_list= self._driver.find_elements_by_xpath('//span[@class="ui-search-filter-name"]')
        filter_by = list(filter(lambda span: span.text== filter_condition, filter_list))
        print(filter_by[0].text)
        filter_by[0].click()

    def click_submit(self):
        input_field = self._driver.find_element_by_xpath('//input[@class="nav-search-input"]')
        input_field.submit()
        
    def search(self, keyword, location, condition):
        self.typo_search(keyword)
        self.click_submit()
        self.select_filter(location)
        self.select_filter(condition)
    
    def order_by(self, condition):
        self._driver.find_element_by_class_name('ui-search-sort-filter').click()
        self._driver.find_element_by_xpath(f'//li[@value="{condition}"]').click()
    
    def extrac_first_articles(self):
        list_articles_card = self._driver.find_elements_by_class_name('ui-search-result__content-wrapper')
        top_5_articles = list_articles_card[0:4]
        articles_info=[]
        for article in top_5_articles:
            dict_article = {'article_name': '',
                            'price': ''}
            article_name = top_5_articles[0].find_element_by_class_name('ui-search-item__title').text
            price = top_5_articles[0].find_element_by_class_name('price-tag-fraction').text
            dict_article['article_name']=article_name
            dict_article['price']=price
            articles_info.append(dict_article)
        return articles_info
    
    def accept_cookies(self):
        cookies_button = self._driver.find_element_by_id('cookieDisclaimerButton')
        cookies_button.click()
    
    def select_country(self, country_name):
        country_list = self._driver.find_element_by_class_name('ml-site-list')
        country_list = country_list.find_elements_by_tag_name('a')
        country = list(filter(lambda a: a.text== country_name, country_list))
        country = country[0]
        country.click()

y este seri el archivo de test.

import unittest
from selenium import webdriver
from mercadolibre_page import MercadoLibre
from time import sleep

class GoogleTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path = './chromedriver')
        
    def test_search(self):
        mercadolibre = MercadoLibre(self.driver)
        mercadolibre.open()
        mercadolibre.select_country('Colombia')
        sleep(3)
        mercadolibre.accept_cookies()
        mercadolibre.search('playstation 4', 'Bogotá D.C.', 'Nuevo')
        mercadolibre.order_by('price_desc')
        top_5_articles = mercadolibre.extrac_first_articles()
        print(top_5_articles)
        

    @classmethod
    def tearDownClass(cls):
	    cls.driver.implicitly_wait(3)
	    cls.driver.close()

if __name__ == "__main__":
	unittest.main(verbosity = 2)

de esta manera si quieremos cambiar los parametros de busqueda solo debemos modificar el statement del metodo search, tambiejn se podra usar otro tipo de orden por ejemplo ‘price_asc’ para ordenar los productos de menor a mayor precio, por ultimo cree un metodo para la extraccion de la informacion de los articulos el cual los retorna en un diccionario

Les comparto mi codigo

# unittest
import unittest

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


class TestingMercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(r'C:\Users\santi\Downloads\Descargas Basura\chromedriver.exe')
        driver = self.driver
        driver.get('https://mercadolibre.com')
        driver.maximize_window()

    def test_search_ps5(self):
        driver = self.driver
        driver.find_element_by_id('CO').click()
        search_field = driver.find_element_by_name('as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('Playstation 5')
        search_field.submit()
        driver.implicitly_wait(3)

        # Ubicación
        location = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section/dl[18]/dd[1]/a')
        driver.execute_script("arguments[0].click();", location)
        driver.implicitly_wait(3)

        # Condición
        condition = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section/dl[17]/dd[1]/a')
        driver.execute_script("arguments[0].click();", condition)
        driver.implicitly_wait(3)

        # Ordenar
        driver.find_element_by_class_name('andes-dropdown__trigger').click()
        higher_price = WebDriverWait(self.driver, 10).until(
            EC.visibility_of_element_located((By.XPATH, '//*/div[1]/div/div/div[2]/div[1]/div/div/div/ul/li[3]/a'))
        )
        higher_price.click()
        driver.implicitly_wait(3)

        articles = []
        prices = []

        for i in range(5):
            article_name = driver.find_element_by_xpath(
                f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a/h2'
            )
            articles.append(article_name.text)
            article_price = driver.find_element_by_xpath(
                f'//ol/li[{i + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]'
            )
            prices.append(article_price.text)
        print(articles, prices)

    def tearDown(self):
        self.driver.close()


if __name__ == '__main__':
    unittest.main()

Hubo algunos cambios con respecto al menú desplegable, sin embargo, aquí está el código:

import unittest
from selenium import webdriver
from time import sleep
class TestingMercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path='/home/yanina/Downloads/chromedriver')
        driver= self.driver
        driver.get('https://www.mercadolibre.com')
        driver.maximize_window()

    def test_search_ps4(self):
        driver= self.driver
        country=driver.find_element_by_id('CO')
        country.click()

        search_field= driver.find_element_by_name('as_word')
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)

        location= driver.find_element_by_partial_link_text('Bogotá D.C.')
        location.click()
        sleep(3)

        condition= driver.find_element_by_partial_link_text('Nuevo')
        condition.click()
        sleep(3)

        order_menu= driver.find_element_by_class_name('andes-dropdown__trigger')
        order_menu.click()
        higher_pric= driver.find_element_by_css_selector('li.andes-list__item:nth-child(3)')
        higher_pric.click()
        sleep(3)

        articles= []
        prices= []
        for i in range(5):
            article_name= driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[1]/a/h2').text
            articles.append(article_name)
            article_price= driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[2]/div/div/span[1]/span[2]').text
            prices.append(article_price)

        print(articles, prices)
    def tearDown(self):
        self.driver.close()
if __name__== "__main__":
    unittest.main(verbosity=2)```

Para el uso correcto de las esperas, podemos encontrar hasta 3 tipos diferentes de esperas:
Esperas implícitas: Indicarle al Driver que espere durante un cierto período de tiempo cuando intente encontrar un elemento o elementos.
Esperas explícitas: Ayuda a pasar por alto la espera implícita para algunos elementos específicos.
Espera fluida: A diferencia de la espera implícita y explícita, la espera fluida utiliza dos parámetros. Tiempo de espera y frecuencia de sondeo.

Fuente y ejemplos: https://riptutorial.com/es/selenium-webdriver/example/15495/tipos-de-espera-en-selenium-webdriver

import unittest
from selenium import webdriver
from time import sleep

class MercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path='./chromedriver')
        driver = self.driver
        driver.implicitly_wait(5)
        driver.get("https://www.mercadolibre.com")
        
    def test_ps4_search(self):
        driver = self.driver
        articles = []
        prices = []
        driver.find_element_by_link_text('Colombia').click()

        search_field = driver.find_element_by_xpath('/html/body/header/div/form/input')
        search_field.send_keys('playstation 4')
        search_field.submit()

        driver.find_element_by_xpath('/html/body/main/div/div/aside/section[2]/dl[7]/dd[1]/a').click()
        
        driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section[3]/dl[7]/dd[1]/a').click()
        price = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section[2]/div[2]/div[1]/div/div/button').click()
        driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section[2]/div[2]/div[1]/div/div/div/ul/li[3]/div/div/a').click()

        for i in range(5):
            article_name = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[1]/a/h2').text
            articles.append(article_name)
            articles_price = driver.find_element_by_xpath(f'//*[@id="root-app"]/div/div/section/ol/li[{i+1}]/div/div/div[2]/div[2]/div/div/span[1]/span[2]').text
            prices.append(articles_price)
        print("")
        for i in range(5):
            print(articles[i] + " : " + prices[i])


    def tearDown(self):
        driver = self.driver
        sleep(5)
        driver.quit()

if __name__ == "__main__":
    unittest.main(verbosity=2)

ahora de automatizar una encuesta que se hace todos los días en la empresa.

mi pregunta es ¡¿ cómo hago para que ese script se ejecute a una determinada hora?

Saludos chicos les dejo mi codigo l hice unas pequeñas mejoras y explico con comentarios sus funciones

import unittest
from selenium import webdriver
from time import sleep

class TestingMercadoLibre(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox(executable_path= r'./geckodriver.exe')
        driver = self.driver
        driver.get("https://mercadolibre.com")
        driver.maximize_window()

    def test_search_nintendo_switch(self):
        driver = self.driver

        #Identificar pais
        country = driver.find_element_by_id('VE')
        country.click()

        #Identificar cuadro de busqueda
        search_field = driver.find_element_by_name('as_word')
        search_field.click()#Ubicar el cursor aqui
        search_field.clear()#Limpiar strings
        search_field.send_keys('Nintendo Switch')
        sleep(3)

        #Boton de envio
        button_submit = driver.find_element_by_xpath('/html/body/header/div/form/button/div')
        button_submit.click()

        #Filtro de ubicacion
        location = driver.find_element_by_partial_link_text('Distrito Capital')
        driver.execute_script("arguments[0].click();", location)
        sleep(3)

        #Condicion
        condition = driver.find_element_by_partial_link_text('Nuevo')
        driver.execute_script("arguments[0].click();", condition)
        sleep(3)

        #Ordenar publicaciones
        dropdown = driver.find_element_by_xpath('/html/body/main/div/div/section/div[1]/div/div/div[2]/div[1]/div/div/button')
        dropdown.click()
        sleep(3)

        #Eleccion de ordenamiento
        price = driver.find_element_by_xpath('/html/body/main/div/div/section/div[1]/div/div/div[2]/div[1]/div/div/div/ul/li[3]/a/div/div')
        price.click()
        sleep(3)

        #Listas para almacenar la informacion
        articles = []
        prices = []

        #Titulo
        for i in range(5):
            article_name = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a/h2').text
            articles.append(article_name)

        #Precio
        for k in range(5):
            article_price = driver.find_element_by_xpath(f'/html/body/main/div/div/section/ol/li[{k + 1}]/div/div/div[2]/div[2]/div[1]/div/div/div/span[1]/span[2]').text
            prices.append(article_price)

        #Impresion
        print(articles, prices)

    def tearDown(self):
        self.driver.close()

if __name__ == '__main__':
    unittest.main()```

tuve el problema de uqe no pude dar click por el nombre del xpath en las condiciones y lo solucione asi

element = driver.find_element_by_xpath('//*[@id="root-app"]/div/div/aside/section/dl[15]/dd[1]/a/span[1]')
        driver.execute_script("arguments[0].click();", element) #este codigo hace que se ejecute un script de 
                                                                #javascript en python, element es tomado como
                                                                #  "argument[0]" y luego se ordena dar click() en
                                                                #  este elemento

Yo tuve problemas con encontrar el filtro de precio, entonces lo busqué por partial_link_text y funcionó.

import unittest
from time import sleep

from pyunitreport import HTMLTestRunner
from selenium import webdriver


class TestingMercadoLibre(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(executable_path='../chromedriver')
        driver = self.driver
        driver.get('https://www.mercadolibre.com')
        driver.maximize_window()

    def test_search_ps4(self):
        driver = self.driver
        country = driver.find_element_by_id('CO')
        country.click()
        search_field = driver.find_element_by_name('as_word')
        search_field.click()
        search_field.clear()
        search_field.send_keys('playstation 4')
        search_field.submit()
        sleep(3)
        driver.find_element_by_xpath('//*[@id="cookieDisclaimerButton"]').click()
        location = driver.find_element_by_partial_link_text('Bogotá D.C')
        location.click()
        sleep(3)

        condition = driver.find_element_by_partial_link_text('Nuevo')
        condition.click()
        sleep(3)
        order_menu = driver.find_element_by_class_name('andes-dropdown__trigger')
        order_menu.click()
        sleep(3)

        higher_price = driver.find_element_by_partial_link_text('Mayor precio')
        driver.execute_script("arguments[0].click();", higher_price)
        sleep(3)

        articles = []

        # //*[@id="root-app"]/div/div/section/ol/li[1]/div/div/div[2]/div[1]/a/h2

        for i in range(5):
            article_name = driver.find_element_by_xpath(
                f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[1]/a/h2').text
            article_price = driver.find_element_by_xpath(
                f'//*[@id="root-app"]/div/div/section/ol/li[{i + 1}]/div/div/div[2]/div[2]/div[1]/div[1]/div/div/span[1]/span[2]').text
            articles.append((article_name, article_price))

        print(articles)

    def tearDown(self) -> None:
        self.driver.close()


if __name__ == "__main__":

    unittest.main(verbosity=2, testRunner=HTMLTestRunner(
        output='.',
        report_name=__file__))