CursosEmpresasBlogLiveConfPrecios

Ordenar tablas

Clase 20 de 24 • Curso de Introducción a Selenium con Python

Clase anteriorSiguiente clase

Contenido del curso

Conocer el ecosistema de Selenium
  • 1
    Por qué aprender Selenium y qué verás

    Por qué aprender Selenium y qué verás

    03:15
  • 2
    Historia de Selenium

    Historia de Selenium

    09:05
  • 3
    Otras herramientas de testing y automatización

    Otras herramientas de testing y automatización

    03:40
Preparar entorno de trabajo
  • 4
    Configurar entorno de trabajo

    Configurar entorno de trabajo

    01:43
  • 5

    Compatibilidad con Python 3.9 y aprendiendo a utilizar múltiples versiones

    01:44
  • 6
    ¡Hola, mundo!

    ¡Hola, mundo!

    11:51
Utilizar comandos básicos
  • 7
    Encontrar elementos con find_element

    Encontrar elementos con find_element

    15:23
  • 8
    Preparar assertions y test suites

    Preparar assertions y test suites

    13:50
  • 9

    Entender las clases WebDriver y WebElement

    01:18
Interactuar con elementos
  • 10
    Manejar form, textbox, checkbox y radio button

    Manejar form, textbox, checkbox y radio button

    13:37
  • 11
    Manejar dropdown y listas

    Manejar dropdown y listas

    07:42
  • 12
    Manejar alert y pop-up

    Manejar alert y pop-up

    06:05
  • 13
    Automatizar navegación

    Automatizar navegación

    03:54
Sincronizar pruebas
  • 14
    Demora implícita y explícita

    Demora implícita y explícita

    08:38
  • 15

    Condicionales esperadas

    00:44
Retos
  • 16
    Agregar y eliminar elementos

    Agregar y eliminar elementos

    09:16
  • 17
    Elementos dinámicos

    Elementos dinámicos

    06:46
  • 18
    Controles dinámicos

    Controles dinámicos

    08:01
  • 19
    Typos

    Typos

    05:43
  • 20
    Ordenar tablas

    Ordenar tablas

    07:12
Metodologías de Trabajo
  • 21
    Data Driven Testing (DDT)

    Data Driven Testing (DDT)

    13:35
  • 22
    Page Object Model (POM)

    Page Object Model (POM)

    10:35
Cierre del curso
  • 23
    Realizar una prueba técnica

    Realizar una prueba técnica

    11:33
  • 24
    Conclusiones

    Conclusiones

    01:43
    Steven Moreno

    Steven Moreno

    student•
    hace 5 años

    En la línea 24 hice el siguiente cambio en parametro de la función para xpath

    //*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]

    Cambié j por i. Solo eso.

      Héctor Daniel Vega Quiñones

      Héctor Daniel Vega Quiñones

      teacher•
      hace 5 años

      Totalmente válido ;) Lo importante es llegar a la solución y existen muchos caminos.

      Sebastian Castro Torres

      Sebastian Castro Torres

      student•
      hace 5 años

      El mejor comentario de todos. jajaja

    Víctor H. Torres

    Víctor H. Torres

    student•
    hace 4 años

    El objetivo de la clase era aprender a obtener la información de una tabla y se cumplió. Sin embargo, la información almacenada en la colección, quedó mal estructurada a mi parecer.

    Este es el resultado del ejercicio del docente:

    >>> [['Last Name', 'Smith', 'Frank', 'jdoe@hotmail.com', '$50.00'], ['First Name', 'Smith', 'Frank', 'jdoe@hotmail.com', '$50.00'], ['Email', 'Smith', 'Frank', 'jdoe@hotmail.com', '$50.00'], ['Due', 'Smith', 'Frank', 'jdoe@hotmail.com', '$50.00'], ['Web Site', 'Smith', 'Frank', 'jdoe@hotmail.com', '$50.00']]

    Por cada columna, está guardando la información de toda la fila.

    Esta debería ser el resultado correcto, a mi parecer:

    >>> [['Last Name', 'Smith', 'Bach', 'Doe', 'Conway'], ['First Name', 'John', 'Frank', 'Jason', 'Tim'], ['Email', 'jsmith@gmail.com', 'fbach@yahoo.com', 'jdoe@hotmail.com', 'tconway@earthlink.net'], ['Due', '$50.00', '$51.00', '$100.00', '$50.00']]

    NOTA: Modifiqué las url del código anterior, porque no me dejaba publica este comentario con dichas urls.

    Ahora, el inicio de cada sublista tiene el nombre de la columna y el resto de posiciones está la información de solo esa columna.

    El problema es como obtiene el valor de row_data. Dejo el código corregido para que puedan ver las diferencias:

    import unittest from selenium import webdriver class Typos(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path=r'./chromedriver.exe') driver = self.driver driver.get('https://the-internet.herokuapp.com/') driver.find_element_by_link_text('Sortable Data Tables').click() def test_sort_tables(self): driver = self.driver table_data = [[] for i in range(5)] print(table_data) for i in range(5): header = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{i + 1}]/span') table_data[i].append(header.text) for j in range(4): row_data = driver.find_element_by_xpath(f'//*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]') table_data[i].append(row_data.text) print(table_data) def tearDown(self): self.driver.quit() if __name__ == '__main__': unittest.main(verbosity=2)
      John Steven González

      John Steven González

      student•
      hace 4 años

      También noté que no funcionaba bien el método al imprimir la información.

      Gracias por compartir la solución, para los nuevos: Es iterar también con la variable {i + 1} en la línea de código 24.

      Ismael Danilo Herrera Sánchez

      Ismael Danilo Herrera Sánchez

      student•
      hace 4 años

      👏👏👏 Definitivamente de acuerdo.

    Victor Martin Ortiz Palacio

    Victor Martin Ortiz Palacio

    student•
    hace 5 años

    Lo realize de la siguiente manera:

    import unittest from selenium import webdriver from selenium.common.exceptions import NoSuchElementException class Tables(unittest.TestCase): def setUp(self): """Start web driver""" options = webdriver.ChromeOptions() options.add_argument('--no-sandbox') options.add_argument('--headless') options.add_argument('--disable-gpu') self.driver = webdriver.Chrome(options=options) def tearDow(self): """Stop web driver""" self.driver.quit() def test_sort_tables(self): driver = self.driver table_data = [] try: """Find and click link with text Sortable Data Tables""" driver.get('https://the-internet.herokuapp.com/') driver.find_element_by_link_text('Sortable Data Tables').click() get_rows_table = driver.find_element_by_id('table1').get_property('rows') get_head_table = get_rows_table[0].get_property('cells') for i in range(1, len(get_rows_table)): data = {} for j in range(len(get_rows_table)): get_head_cells = get_head_table[j].text get_body_cells = get_rows_table[i].get_property('cells')[j].text data.update({get_head_cells:get_body_cells}) table_data.append(data) print(table_data) except NoSuchElementException as ex: self.fail(ex.msg) if __name__ == "__main__": unittest.main(verbosity = 2)```

    Obteniendo el siguiente resultado:

    [{'Last Name': 'Smith', 'First Name': 'John', 'Email': 'jsmith@gmail.com', 'Due': '$50.00', 'Web Site': 'http://www.jsmith.com'}, {'Last Name': 'Bach', 'First Name': 'Frank', 'Email': 'fbach@yahoo.com', 'Due': '$51.00', 'Web Site': 'http://www.frank.com'}, {'Last Name': 'Doe', 'First Name': 'Jason', 'Email': 'jdoe@hotmail.com', 'Due': '$100.00', 'Web Site': 'http://www.jdoe.com'}, {'Last Name': 'Conway', 'First Name': 'Tim', 'Email': 'tconway@earthlink.net', 'Due': '$50.00', 'Web Site': 'http://www.timconway.com'}]
      Carlos Andres Ocampo Pabon

      Carlos Andres Ocampo Pabon

      student•
      hace 5 años

      ¿Qué es lo que escribes en la función de setUo, ese tema de las opciones, para qué son?

      Sebastián Andrade

      Sebastián Andrade

      student•
      hace 5 años

      Hola ¿Para que sirven las opciones que tienes arriba?

    Daniel Hernández Sánchez

    Daniel Hernández Sánchez

    student•
    hace 4 años

    ¿Qué les parece esta presentación?

    prettytable.png

    Aquí les dejo como lo hice con PrettyTable:

    import unittest from selenium import webdriver from selenium.webdriver.common.by import By from prettytable import PrettyTable class Tables(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(r'chromedriver') driver = self.driver #Aquí pongan el enlace, como no es https no me permite añadir mi comentario. driver.get() def test_table(self): driver = self.driver rows = [] ptable = PrettyTable() for i in range(5): header = driver.find_element( By.XPATH, f'//*[@id="table1"]/thead/tr/th[{i+1}]/span') for j in range(4): row = driver.find_element( By.XPATH, f'//*[@id="table1"]/tbody/tr[{j+1}]/td[{i+1}]') rows.append(row.text) ptable.add_column(header.text, rows) rows.clear() print(ptable) def tearDown(self): self.driver.quit() if __name__ == '__main__': unittest.main(verbosity=2)

    En este enlace encontrarán la info para usar PrettyTable.

      fidel angel ochoa

      fidel angel ochoa

      student•
      hace 4 años

      excelente aporte, me ayudo mucho y luce mejor la tabla de esta manera.

      fidel angel ochoa

      fidel angel ochoa

      student•
      hace 4 años

      ¿Como supiste como usar "prettyTable" de esta manera? lo que vi de la documentacion no usa muchos ejemplos

    Juan Antonio Pavon Carmona

    Juan Antonio Pavon Carmona

    student•
    hace 5 años

    El resultado del video no es correcto. min 6.10. No se vuelcan correctamente los datos de la lista

    Reto resuelto:

    def test_sort_tables(self): driver = self.driver # Total elementos del header a capturar header_data_size = len(driver.find_elements_by_css_selector('#table1 > thead > tr > th')) -1 # total elementos del body a capturar. body_data_size = len(driver.find_elements_by_css_selector('#table1 > tbody > tr')) # Se crea una lista de sublistas table_data = [[] for i in range(body_data_size)] # Se capturan los datos for i in range(body_data_size): for j in range(header_data_size): header_data = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{j+1}]/span').text cell_data = driver.find_element_by_xpath(f'//*[@id="table2"]/tbody/tr[{i+1}]/td[{j+1}]').text table_data[i].append({header_data : cell_data}) print(table_data)

    Resultado:

    [[{'Last Name': 'Smith'}, {'First Name': 'John'}, {'Email': 'jsmith@gmail.com'}, {'Due': '$50.00'}, {'Web Site': 'https://www.jsmith.com'}], [{'Last Name': 'Bach'}, {'First Name': 'Frank'}, {'Email': 'fbach@yahoo.com'}, {'Due': '$51.00'}, {'Web Site': 'https://www.frank.com'}], [{'Last Name': 'Doe'}, {'First Name': 'Jason'}, {'Email': 'jdoe@hotmail.com'}, {'Due': '$100.00'}, {'Web Site': 'https://www.jdoe.com'}], [{'Last Name': 'Conway'}, {'First Name': 'Tim'}, {'Email': 'tconway@earthlink.net'}, {'Due': '$50.00'}, {'Web Site': 'https://www.timconway.com'}]]```
      Henry Daniel

      Henry Daniel

      student•
      hace 5 años

      solo has separado, o sea has creado lista por persona no por columna, esa no era la idea en todo caso

    Gonzalo García

    Gonzalo García

    student•
    hace 5 años

    Lo más lindo de Python, además de ser Open Source, son sus librerías. Con esta van a poder visualizar de manera mucho más estética los valores obtenidos de la tabla: https://pypi.org/project/prettytable/ Además de jugar un poco más con el código :) Espero que les guste!

      Cristian David Restrepo Marin

      Cristian David Restrepo Marin

      student•
      hace 5 años

      Gonzalo muchas gracias por el aporte

    Andrés Xavier Vargas Vera

    Andrés Xavier Vargas Vera

    student•
    hace 4 años

    Deberían regrabar esta clase, ese ciclo for está otro nivel de mal :(

      Andrés Xavier Vargas Vera

      Andrés Xavier Vargas Vera

      student•
      hace 4 años

      Propongo esta solución: Agregar la dirección del sitio

      from unittest import TestCase, main from pyunitreport import HTMLTestRunner from selenium import webdriver class Tables(TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome(executable_path='./chromedriver.exe') driver = cls.driver driver.implicitly_wait(10) driver.maximize_window() driver.get("<direccion del sitio>") driver.find_element_by_link_text('Sortable Data Tables').click() def test_name_elements(self): driver = self.driver number_of_columns = len(driver.find_elements_by_xpath('//table[@id="table1"]/thead/tr/th')) number_of_rows = len(driver.find_elements_by_xpath('//table[@id="table1"]//tr')) print(number_of_rows) print(number_of_columns) table_data = [] print(table_data) for i in range(number_of_rows): row=[] for j in range(number_of_columns): if i==0: # Header data =driver.find_element_by_xpath(f'//table[@id="table1"]/thead/tr/th[{j+1}]') else: # Body data = driver.find_element_by_xpath(f'//table[@id="table1"]/tbody/tr[{i}]/td[{j+1}]') row.append(data.text) table_data.append(row) print(table_data) @classmethod def tearDownClass(cls): cls.driver.implicitly_wait(5) cls.driver.quit() if __name__ == "__main__": main(verbosity=2, testRunner=HTMLTestRunner( output="tables", report_name="test_tables"))
    Santiago Herrera Velásquez

    Santiago Herrera Velásquez

    student•
    hace 5 años

    Si se fijan el codigo de la clase retorna la misma fila de la tabla varias veces, dejo mi codigo con las pequeñas correcciones

    import unittest from selenium import webdriver from time import sleep ROWS = 5 class Tables(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome('../chromedriver') driver = self.driver driver.get('pagina de prueba') #no la pongo porque la IA de comentarios de platzi me la borra driver.find_element_by_link_text('Sortable Data Tables').click() def test_sort_tables(self): driver = self.driver table_data = [[] for _ in range(ROWS)] for i in range(ROWS): header = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{i + 1}]/span') table_data[i].append(header.text) for j in range(ROWS - 1): row_data = driver.find_element_by_xpath(f'//*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]') table_data[i].append(row_data.text) print(table_data) def tearDown(self): self.driver.close() if __name__ == "__main__": unittest.main(verbosity = 2)

    RESULTADO:

    test_sort_tables (__main__.Tables) ... DevTools listening on ws://127.0.0.1:50420/devtools/browser/1ba7a561-8b24-40af-9638-e8594d558ec8 [['Last Name', 'Smith', 'Bach', 'Doe', 'Conway'], ['First Name', 'John', 'Frank', 'Jason', 'Tim'], ['Email', 'jsmith@gmail.com', 'fbach@yahoo.com', 'jdoe@hotmail.com', 'tconway@earthlink.net'], ['Due', '$50.00', '$51.00', '$100.00', '$50.00'], ['Web Site', 'https://www.jsmith.com', 'https://www.frank.com', 'https://www.jdoe.com', 'https://www.timconway.com']]
    Israel Yance

    Israel Yance

    student•
    hace 5 años

    Acá lo hice con diccionario, listo para convertirlo en DataFrame si se desea:

    def test_sort_tables(self): driver = self.driver table_data = {} print(table_data) for i in range(5): header = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{i + 1}]/span') table_data[header.text] = [] for j in range(4): row_data = driver.find_element_by_xpath(f'//*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]') table_data[header.text].append(row_data.text) print(table_data)
    Gabriel Cayoja

    Gabriel Cayoja

    student•
    hace 3 años

    esta clase esta bastante improvisada, las iteraciones le salen mal y el lo sabe, y no hace nada por corregirlas

    Ismael Danilo Herrera Sánchez

    Ismael Danilo Herrera Sánchez

    student•
    hace 4 años

    Compañeros, alguien de casualidad sabe cual es la extensión que el profesor utiliza, para que el área de las funciones o condicionales este de colores?

      Beatriz Lumbreras Morales

      Beatriz Lumbreras Morales

      student•
      hace 4 años

      Los colores tiene que ver más con Themes, los puedes encontrar en el marketplace de Visual Studio Code

      Ismael Danilo Herrera Sánchez

      Ismael Danilo Herrera Sánchez

      student•
      hace 4 años

      Estos:

      Sin título.jpg

    Jeyson David Vargas Crespo

    Jeyson David Vargas Crespo

    student•
    hace 5 años

    Hola, me pueden ayudar, me está sacando este error y no he podido:

    Captura de Pantalla 2020-10-13 a la(s) 9.14.54 a. m..png

    Este es el código:

    def test_sort_tables(self): driver = self.driver #se crea una lista vacia donde se almacenan los datos, #esta lista se constituye de otras sublistas, con un comprehension list table_data = [[] for i in range(5)] #5 columnas print(table_data) #iterar por cada uno de los headers y los datos for i in range(5): header = driver.find_element_by_xpath(f'/html/body/div[2]/div/div/table[1]/thead/tr/th[{i + 1}]/span') #en el [había un 1] este se cambia para poder iterar y por eso se escogió el xpath table_data[i].append(header.text) #text para tomar solo el texto for j in range(4): #son 4 las filas que se están iterando row_data = driver.find_element_by_xpath(f'/html/body/div[2]/div/div/table[1]/tbody/tr[{j + 1}]/td[{i + 1}]') #agregar ese dato a la tabla table_data[1].append(row_data.text) #si queremos estar seguros que estamos tomando los datos print(table_data ) ``` Muchas gracias.
      Cristian David Restrepo Marin

      Cristian David Restrepo Marin

      student•
      hace 5 años

      Hola jeydvc, veo que el error puede estar en el xpath, prueba copiándolo de nuevo.

    Juan Esteban Sierra Aguilar

    Juan Esteban Sierra Aguilar

    student•
    hace 3 años

    Hola, acá mi aporte, tiene el extra de que determina el número de filas y columnas de la tabla, esto lo hace através de los selectores css.

    def test_sort_tables(self): driver = self.driver # Compute rows and columns rows = len(driver.find_elements_by_css_selector('#table1 > tbody > tr')) cols = len(driver.find_elements_by_css_selector('#table1 > thead > tr > th')) table = [[] for i in range(rows+1)] # Add headers for i in range(rows): header = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{i + 1}]/span') table[0].append(header.text) # Add table data for i in range(rows): for j in range(cols): row_data = driver.find_element_by_xpath(f'//*[@id="table1"]/tbody/tr[{i + 1}]/td[{j + 1}]') table[i].append(row_data.text) # Let's give it a basic format formated_rows = [', '.join(i) for i in table] print('\n' + '\n'.join(formated_rows))
    Randhal Smith Ramirez Orozco

    Randhal Smith Ramirez Orozco

    student•
    hace 3 años

    En mi humilde opinion con el selector CSS se puede hacer mas rapido, siplemente pones la tabla y ya, nada de for loop.

    En pantalla mi respuesta:

    import unittest from selenium import webdriver from pyunitreport import HTMLTestRunner from selenium.webdriver.common.by import By class HomePageTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome(executable_path = 'chromedriver.exe') cls.driver.get('https://the-internet.herokuapp.com/tables') cls.driver.maximize_window() cls.driver.implicitly_wait(15) def test_xfil(self): """Test of table by its xpath""" data_table = self.driver.find_element(By.CSS_SELECTOR, '#table1') print(data_table.text) @classmethod def tearDownClass(cls): cls.driver.quit() if __name__ == '__main__': unittest.main(verbosity = 2, testRunner = HTMLTestRunner(output = 'reportes', report_name = 'table-data-report'))
    Fabricio Quintas

    Fabricio Quintas

    student•
    hace 3 años

    Aquí está mi resolución del reto, espero a alguien le sea de ayuda.

    Con este código logré que devuelva, en cada lista creada (creadas en base a la cantidad de filas que tiene la tabla) en forma de diccionarios, cada dato del header junto al que contiene el body.

    El código está todo comentado para que se entienda mejor.

    import unittest from selenium import webdriver from time import sleep class Tables(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path=r'C:\chromedriver.exe') driver = self.driver driver.get('https://the-internet.herokuapp.com/') driver.find_element_by_link_text('Sortable Data Tables').click() def test_sort_tables(self): driver = self.driver # Get the len of the head data ( Table 1 ), getting a list of elements from his css selector ( -1 for the edit/delete panel ) columns_size = len(driver.find_elements_by_css_selector('#table1 > thead > tr > th')) - 1 # Get the len of data size ( in rows ) from the table 1 ( Without header ) row_size = len(driver.find_elements_by_css_selector('#table1 > tbody > tr')) table_data = [[] for i in range(row_size)] # Create a list with empty lists inside (the quantity of rows of the body) print(table_data) # Lets save all data for i in range(row_size): # Iter through each row of the data # Now iter through each column of the data for j in range(columns_size): # Take each head data text of the table header_data = driver.find_element_by_xpath(f'//*[@id="table1"]/thead/tr/th[{j + 1}]/span').text # j will iter column by column # Take each body data text row_data = driver.find_element_by_xpath(f'//*[@id="table1"]/tbody/tr[{i + 1}]/td[{j + 1}]').text # i iter row by row # Append to the table data, as a dict table_data[i].append({header_data : row_data}) print(table_data) def tearDown(self): self.driver.close() if __name__ == '__main__': unittest.main(verbosity = 2)

    Esto es lo que devuelve el código.

    1.png
    Jorge Heli Rueda Uribe

    Jorge Heli Rueda Uribe

    student•
    hace 5 años

    No comprendo el [ ] que está antes del for en la línea 16.

      Cristian David Restrepo Marin

      Cristian David Restrepo Marin

      student•
      hace 5 años

      Hola jorueda, en Python existen las list comprehensions que proporcionan una forma concisa de crear listas, esta imagen resumen un poco lo que sucede en la linea 16, donde el profe crea una lista con listas, es decir una lista padre que contiene varias listas hijas.

      Te recomiendo ver esta clase del curso de Python intermedio donde el profesor Facundo explica esta forma de crear listas https://platzi.com/clases/2255-python-intermedio/36463-list-comprehensions/

      Te dejo el enlace de la documentación oficial donde puedes profundizar un poco. https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions

      1_JtwtZPtmguABcRkayV-WIw.png
      Jorge Heli Rueda Uribe

      Jorge Heli Rueda Uribe

      student•
      hace 5 años

      ¡Que espectacular Christian! ¡Super poderoso lo de las list compehensions! Gracias. Por otro lado, viendo lo que me comentas, haré el curso de Python intermedio, se ve súper interesante. ¡Muchas gracias!

    Miguel Angel Lopez Monroy

    Miguel Angel Lopez Monroy

    student•
    hace 3 años

    El reto queda así:

    import unittest from selenium import webdriver from selenium.webdriver.common.by import By COLUMN_NUMBER = 5 ROW_NUMBER = 4 class Tables(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(executable_path="./usr/bin/chromedriver") driver = self.driver driver.get("https://the-internet.herokuapp.com/") driver.find_element(By.LINK_TEXT, "Sortable Data Tables").click() def test_sort_tables(self): driver = self.driver table_data = [[] for i in range(COLUMN_NUMBER)] print(table_data) for i in range(COLUMN_NUMBER): header = driver.find_element( By.XPATH, f'//*[@id="table1"]/thead/tr/th[{i + 1}]/span' ) table_data[i].append(header.text) for j in range(ROW_NUMBER): row_data = driver.find_element( By.XPATH, f'//*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]' ) table_data[i].append(row_data.text) print(table_data) def tearDown(self): self.driver.close() if __name__ == "__main__": unittest.main(verbosity=2)
    Gabriel Ichcanziho Pérez Landa

    Gabriel Ichcanziho Pérez Landa

    student•
    hace 3 años

    A quién le sirva, el siguiente código extrae los datos de header y body de forma aislada

    y genera un dataframe de pandas :)

    def test_sort_tables(self): driver = self.driver header = driver.find_elements(By.XPATH, '//*[@id="table1"]/thead/tr/th') header_text = [cell.text for cell in header[:-1]] body_table = driver.find_elements(By.XPATH, '//*[@id="table1"]/tbody/tr') table = [] for row in body_table: values = row.find_elements(By.XPATH, "td") values = [cell.text for cell in values[:-1]] table.append(values) table_df = pd.DataFrame(data=table, columns=header_text) print(table_df)

    el código para instalar pandas es

    pip install pandas
    Zacil Dzul

    Zacil Dzul

    student•
    hace 3 años

    Con el ordenamiento de la clase los datos quedan escalonados, se cambio la linea row_data = driver.find_element(By.XPATH,f'//*[@id="table1"]/tbody/tr[{j + 1}]/td[{i + 1}]') para que conserve los datos de la columna y se itere solo las filas y queda asi, ya sale la columna web site con los datos de sus filas: [['Last Name', 'Smith', 'Bach', 'Doe', 'Conway'], ['First Name', 'John', 'Frank', 'Jason', 'Tim'], ['Email', 'jsmith@gmail.com', 'fbach@yahoo.com', 'jdoe@hotmail.com', 'tconway@earthlink.net'], ['Due', '$50.00', '$51.00', '$100.00', '$50.00'], ['Web Site', aqui sales las urls que no deja aportar en el comentario']]

    Roger Christian Cansaya Olazabal

    Roger Christian Cansaya Olazabal

    student•
    hace 3 años

    Considerando la organizacion correcta de los datos, actualizando el codigo actualizado. (deprecated) El codigo final quedaria asi.

    import unittest from selenium import webdriver from prettytable import PrettyTable from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class Tables(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) driver = self.driver driver.get('https://the-internet.herokuapp.com/') driver.maximize_window() driver.implicitly_wait(3) driver.find_element(by=By.LINK_TEXT, value='Sortable Data Tables').click() def test_sort_table(self): driver = self.driver table_data = [[] for i in range(5)] print(table_data) ptable = PrettyTable() for i in range(5): header = driver.find_element(by=By.XPATH, value=f'//*[@id="table1"]/thead/tr/th[{i+1}]/span') table_data[i].append(header.text) for j in range(4): row_data = driver.find_element(by=By.XPATH, value=f'//*[@id="table1"]/tbody/tr[{j+1}]/td[{i+1}]') table_data[i].append(row_data.text) ptable.add_column(header.text, table_data[i]) #print(table_data) print(ptable) def tearDown(self): self.driver.implicitly_wait(3) self.driver.close() if __name__ == "__main__": unittest.main(verbosity = 2)
    pretty.png

Escuelas

  • Desarrollo Web
    • Fundamentos del Desarrollo Web Profesional
    • Diseño y Desarrollo Frontend
    • Desarrollo Frontend con JavaScript
    • Desarrollo Frontend con Vue.js
    • Desarrollo Frontend con Angular
    • Desarrollo Frontend con React.js
    • Desarrollo Backend con Node.js
    • Desarrollo Backend con Python
    • Desarrollo Backend con Java
    • Desarrollo Backend con PHP
    • Desarrollo Backend con Ruby
    • Bases de Datos para Web
    • Seguridad Web & API
    • Testing Automatizado y QA para Web
    • Arquitecturas Web Modernas y Escalabilidad
    • DevOps y Cloud para Desarrolladores Web
  • English Academy
    • Inglés Básico A1
    • Inglés Básico A2
    • Inglés Intermedio B1
    • Inglés Intermedio Alto B2
    • Inglés Avanzado C1
    • Inglés para Propósitos Específicos
    • Inglés de Negocios
  • Marketing Digital
    • Fundamentos de Marketing Digital
    • Marketing de Contenidos y Redacción Persuasiva
    • SEO y Posicionamiento Web
    • Social Media Marketing y Community Management
    • Publicidad Digital y Paid Media
    • Analítica Digital y Optimización (CRO)
    • Estrategia de Marketing y Growth
    • Marketing de Marca y Comunicación Estratégica
    • Marketing para E-commerce
    • Marketing B2B
    • Inteligencia Artificial Aplicada al Marketing
    • Automatización del Marketing
    • Marca Personal y Marketing Freelance
    • Ventas y Experiencia del Cliente
    • Creación de Contenido para Redes Sociales
  • Inteligencia Artificial y Data Science
    • Fundamentos de Data Science y AI
    • Análisis y Visualización de Datos
    • Machine Learning y Deep Learning
    • Data Engineer
    • Inteligencia Artificial para la Productividad
    • Desarrollo de Aplicaciones con IA
    • AI Software Engineer
  • Ciberseguridad
    • Fundamentos de Ciberseguridad
    • Hacking Ético y Pentesting (Red Team)
    • Análisis de Malware e Ingeniería Forense
    • Seguridad Defensiva y Cumplimiento (Blue Team)
    • Ciberseguridad Estratégica
  • Liderazgo y Habilidades Blandas
    • Fundamentos de Habilidades Profesionales
    • Liderazgo y Gestión de Equipos
    • Comunicación Avanzada y Oratoria
    • Negociación y Resolución de Conflictos
    • Inteligencia Emocional y Autogestión
    • Productividad y Herramientas Digitales
    • Gestión de Proyectos y Metodologías Ágiles
    • Desarrollo de Carrera y Marca Personal
    • Diversidad, Inclusión y Entorno Laboral Saludable
    • Filosofía y Estrategia para Líderes
  • Diseño de Producto y UX
    • Fundamentos de Diseño UX/UI
    • Investigación de Usuarios (UX Research)
    • Arquitectura de Información y Usabilidad
    • Diseño de Interfaces y Prototipado (UI Design)
    • Sistemas de Diseño y DesignOps
    • Redacción UX (UX Writing)
    • Creatividad e Innovación en Diseño
    • Diseño Accesible e Inclusivo
    • Diseño Asistido por Inteligencia Artificial
    • Gestión de Producto y Liderazgo en Diseño
    • Diseño de Interacciones Emergentes (VUI/VR)
    • Desarrollo Web para Diseñadores
    • Diseño y Prototipado No-Code
  • Contenido Audiovisual
    • Fundamentos de Producción Audiovisual
    • Producción de Video para Plataformas Digitales
    • Producción de Audio y Podcast
    • Fotografía y Diseño Gráfico para Contenido Digital
    • Motion Graphics y Animación
    • Contenido Interactivo y Realidad Aumentada
    • Estrategia, Marketing y Monetización de Contenidos
  • Desarrollo Móvil
    • Fundamentos de Desarrollo Móvil
    • Desarrollo Nativo Android con Kotlin
    • Desarrollo Nativo iOS con Swift
    • Desarrollo Multiplataforma con React Native
    • Desarrollo Multiplataforma con Flutter
    • Arquitectura y Patrones de Diseño Móvil
    • Integración de APIs y Persistencia Móvil
    • Testing y Despliegue en Móvil
    • Diseño UX/UI para Móviles
  • Diseño Gráfico y Arte Digital
    • Fundamentos del Diseño Gráfico y Digital
    • Diseño de Identidad Visual y Branding
    • Ilustración Digital y Arte Conceptual
    • Diseño Editorial y de Empaques
    • Motion Graphics y Animación 3D
    • Diseño Gráfico Asistido por Inteligencia Artificial
    • Creatividad e Innovación en Diseño
  • Programación
    • Fundamentos de Programación e Ingeniería de Software
    • Herramientas de IA para el trabajo
    • Matemáticas para Programación
    • Programación con Python
    • Programación con JavaScript
    • Programación con TypeScript
    • Programación Orientada a Objetos con Java
    • Desarrollo con C# y .NET
    • Programación con PHP
    • Programación con Go y Rust
    • Programación Móvil con Swift y Kotlin
    • Programación con C y C++
    • Administración Básica de Servidores Linux
  • Negocios
    • Fundamentos de Negocios y Emprendimiento
    • Estrategia y Crecimiento Empresarial
    • Finanzas Personales y Corporativas
    • Inversión en Mercados Financieros
    • Ventas, CRM y Experiencia del Cliente
    • Operaciones, Logística y E-commerce
    • Gestión de Proyectos y Metodologías Ágiles
    • Aspectos Legales y Cumplimiento
    • Habilidades Directivas y Crecimiento Profesional
    • Diversidad e Inclusión en el Entorno Laboral
    • Herramientas Digitales y Automatización para Negocios
  • Blockchain y Web3
    • Fundamentos de Blockchain y Web3
    • Desarrollo de Smart Contracts y dApps
    • Finanzas Descentralizadas (DeFi)
    • NFTs y Economía de Creadores
    • Seguridad Blockchain
    • Ecosistemas Blockchain Alternativos (No-EVM)
    • Producto, Marketing y Legal en Web3
  • Recursos Humanos
    • Fundamentos y Cultura Organizacional en RRHH
    • Atracción y Selección de Talento
    • Cultura y Employee Experience
    • Gestión y Desarrollo de Talento
    • Desarrollo y Evaluación de Liderazgo
    • Diversidad, Equidad e Inclusión
    • AI y Automatización en Recursos Humanos
    • Tecnología y Automatización en RRHH
  • Finanzas e Inversiones
    • Fundamentos de Finanzas Personales y Corporativas
    • Análisis y Valoración Financiera
    • Inversión y Mercados de Capitales
    • Finanzas Descentralizadas (DeFi) y Criptoactivos
    • Finanzas y Estrategia para Startups
    • Inteligencia Artificial Aplicada a Finanzas
    • Domina Excel
    • Financial Analyst
    • Conseguir trabajo en Finanzas e Inversiones
  • Startups
    • Fundamentos y Validación de Ideas
    • Estrategia de Negocio y Product-Market Fit
    • Desarrollo de Producto y Operaciones Lean
    • Finanzas, Legal y Fundraising
    • Marketing, Ventas y Growth para Startups
    • Cultura, Talento y Liderazgo
    • Finanzas y Operaciones en Ecommerce
    • Startups Web3 y Blockchain
    • Startups con Impacto Social
    • Expansión y Ecosistema Startup
  • Cloud Computing y DevOps
    • Fundamentos de Cloud y DevOps
    • Administración de Servidores Linux
    • Contenerización y Orquestación
    • Infraestructura como Código (IaC) y CI/CD
    • Amazon Web Services
    • Microsoft Azure
    • Serverless y Observabilidad
    • Certificaciones Cloud (Preparación)
    • Plataforma Cloud GCP

Platzi y comunidad

  • Platzi Business
  • Live Classes
  • Lanzamientos
  • Executive Program
  • Trabaja con nosotros
  • Podcast

Recursos

  • Manual de Marca

Soporte

  • Preguntas Frecuentes
  • Contáctanos

Legal

  • Términos y Condiciones
  • Privacidad
  • Tyc promociones
Reconocimientos
Reconocimientos
Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
Logo reconocimientoPrimera Startup EdTech · 2018
Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
Logo reconocimientoCEO Mejor Emprendedor del año · 2024
De LATAM conpara el mundo
YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads