CursosEmpresasBlogLiveConfPrecios

Guardando las noticias en archivos de texto

Clase 20 de 21 • Curso de Fundamentos de Web Scraping con Python y Xpath

Clase anteriorSiguiente clase

Contenido del curso

Introducción al web scraping

  • 1
    ¿Qué es el web scraping?

    ¿Qué es el web scraping?

    02:06 min
  • 2
    ¿Por qué aprender web scraping hoy?

    ¿Por qué aprender web scraping hoy?

    03:05 min
  • 3
    Python: el lenguaje más poderoso para extraer datos

    Python: el lenguaje más poderoso para extraer datos

    03:21 min

Fundamentos de la web

  • 4
    Entender HTTP

    Entender HTTP

    07:02 min
  • 5
    ¿Qué es HTML?

    ¿Qué es HTML?

    08:08 min
  • 6
    Robots.txt: permisos y consideraciones al hacer web scraping

    Robots.txt: permisos y consideraciones al hacer web scraping

    05:41 min

XML Path Language

  • 7
    XML Path Language

    XML Path Language

    03:35 min
  • 8
    Tipos de nodos en XPath

    Tipos de nodos en XPath

    05:18 min
  • 9
    Expresiones en XPath

    Expresiones en XPath

    08:18 min
  • 10
    Predicados en Xpath

    Predicados en Xpath

    05:34 min
  • 11
    Operadores en Xpath

    Operadores en Xpath

    05:51 min
  • 12
    Wildcards en Xpath

    Wildcards en Xpath

    06:11 min
  • 13
    In-text search en Xpath

    In-text search en Xpath

    08:21 min
  • 14
    XPath Axes

    XPath Axes

    05:16 min
  • 15

    Resumen de XPath

    00:01 min
  • 16
    Aplicando lo aprendido

    Aplicando lo aprendido

    08:52 min

Proyecto: scraper de noticias

  • 17
    Un proyecto para tu portafolio: scraper de noticias

    Un proyecto para tu portafolio: scraper de noticias

    10:08 min
  • 18
    Construcción de las expresiones de XPath

    Construcción de las expresiones de XPath

    10:29 min
  • 19
    Obteniendo los links de los artículos con Python

    Obteniendo los links de los artículos con Python

    10:56 min
  • 20
    Guardando las noticias en archivos de texto

    Guardando las noticias en archivos de texto

    Viendo ahora

Conclusiones

  • 21
    Cómo continuar tu ruta de aprendizaje

    Cómo continuar tu ruta de aprendizaje

    02:13 min
  • Tomar el examen del curso
    • Pamela Pimentel

      Pamela Pimentel

      student•
      hace 5 años

      Hola, les dejo la solución de los títulos y en mi caso también de los links. Por algún motivo el response toma el tag h2 como text-fill.

      code.png

        Mario Alberto Vásquez Arias

        Mario Alberto Vásquez Arias

        student•
        hace 5 años

        Tienes mucha razón. También tenia el problema de que me aparecía una lista vacía, y solo cambie h2 por text-fill y se solucionó. Alguien sabrá por que ocurre esto?

        María José Medina

        María José Medina

        student•
        hace 5 años

        Hola Pamela, tambien tuve el mismo problema con el h2. De hecho, cuando ejecuto el código incluyendo h2 en el Xpath me trae 15 de los 84 urls de la página. Ahora, cuando lo ejecuto con tu modificación (el text-fill) me trae las restantes 69... Es extraño

      Alonso Melgar Lopez

      Alonso Melgar Lopez

      student•
      hace 5 años

      Excelente día veo que aun no hay solución al problema de no generar los archivos, esto se debe a un problema con el título de la noticia, lo que regresa es una lista vacía, y por eso entra en el "except", sin embargo en la propia URL de la noticia se encuentra el título, por lo tanto e creado una pequeña función que extrae dicho título.

      Es la solución que encontré, sin embargo seria bueno que alguien que sepa más del tema pueda ayudar con este error

      import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//a[contains(@class,"kicker")]/@href' #XPATH_TITLE = Titulo XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY ='//div[@class="html-content"]//text()' def get_title(link): #separamos por "/" y nos quedamos con el ultimo que elemento url = link.split('/')[-1] #separamos por "-" y eliminamos el ultimo elemento title_list=url.split('-')[:-1] #Unimos lo anterior title = " ".join(title_list) return(title) def parse_notice(link, today): try: response = requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') parsed = html.fromstring(notice) try: title = get_title(link) summary = parsed.xpath(XPATH_SUMMARY)[0] body = parsed.xpath(XPATH_BODY) except IndexError: print("as") return with open(f'{today}/{title}.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: home = response.content.decode('utf-8') parsed = html.fromstring(home) links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) #print(links_to_notices) today = datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in links_to_notices: parse_notice(link, today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == "__main__": run()
        José Alberto Ortiz Vargas

        José Alberto Ortiz Vargas

        student•
        hace 5 años

        Muy buena solucion para extraer el titulo desde la URL eliminando los guinones (-) y quedarnos con el texto. Asi lo pude solucionar para poder crear mis archivos. Sin embargo, considero que el problema esta al momento de ejecutar el XPATH del titulo en el request y que este traiga algo diferente que como lo vemos en Chrome. Me hare un espacio para buscar la solucion.

        Gracias y excelente solucion.

        Edwin San

        Edwin San

        student•
        hace 5 años

        Muchas gracias!!! Me sirvióoo :DD

      Hector F

      Hector F

      student•
      hace 6 años

      Les comparto mi repositorio con mejoras en el proyecto del curso aquí.

      Modularize el código y ahora se puede scrapear varios sitios.

      ¡Saludos!

      Bardo Santiago

      Bardo Santiago

      student•
      hace 5 años

      PROBLEMA CARPETA SE CREA PERO NO SE GUARDAN LOS ARCHIVOS. Todo funcionaba bien el momento de crear la carpeta, pero los archivos no se creaban dentro. El problema estaba en uno de los XPATH. Originalmente estaba usando las siguientes constantes:

      XPATH_LINK_TO_ARTICLE = '//a[@class="globoeconomiaSect"]/@href' XPATH_TITLE = '//div[@class="mb-auto"]/h2/span/text()' XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY = '//div[@class="html-content"]/p[not(@class)]/text()'

      Después de buscar entre los aportes de la comunidad encontré un ejemplo que me ayudó. Sin modificar mucho, realicé un cambio en la constante XPATH_TITLE y quedo de la siguiente manera.

      #ANTES XPATH_TITLE = '//div[@class="mb-auto"]/h2/span/text()'
      #DESPUES XPATH_TITLE = '//div[@class="mb-auto"]//span/text()'

      Lo que hice fue remover la etiqueta h2 de la sentencia. Sin embargo hacer este ajuste implicó modificar el índice en la siguiente línea.

      #Antes title = parsed.xpath(XPATH_TITLE)[0]
      #Despues title = parsed.xpath(XPATH_TITLE)[1]

      Este cambio se debe a que la nueva estructura de XPATH_TITLE devuelve dos elementos y el título es el segundo, por esta razón utilicé el índice [1]. ..

      Utilicé el código tal cual se desarrolló en la clase solo realice estos dos ajustes para que me funcionara.

        Aaron Fabrizio Calderon Guillermo

        Aaron Fabrizio Calderon Guillermo

        student•
        hace 5 años

        Genial! También funciona correctamente y con dos cambios en el código.

        Rodrigo Rodriguez

        Rodrigo Rodriguez

        student•
        hace 5 años

        Gracias Bardo Santiago, fuiste de gran ayuda para encontrar el title. Igualmente seria bueno plantear la pregunta: ¿Porque en python no funciona, si en chrome el xpath propuesto por el profesor obtiene el titulo ?

        Yo he hecho las pruebas el 1-5-21 de los xpath de title, summay y body , en la consola de chrome y todos funcionan.

      Alejandro Giraldo Londoño

      Alejandro Giraldo Londoño

      student•
      hace 5 años

      RESUMEN:Guardando las noticias en archivos de texto ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

      Vamos a realizar una lógica para ir de cada link al sitio de cada noticia y de ahí extraer:

      • Titulo
      • Resumen
      • Cuerpo
      import requests import lxml.html as html # Lo usaremso para crear una carpeta import os # Lo usaremos para manipular fechas. import datetime # Creamos constantes HOME_URL = 'https://www.larepublica.co/' #Recuerda que tu Xpath puede variar. XPATH_LINK_TO_ARTICLE = '//text-fill[not(@class)]/a/@href' XPATH_LINK_TO_TITLE = '//div[@class="mb-auto"]/h2/a/text()' XPATH_LINK_TO_SUMMARY = '//div[@class="wrap-post col-9"]/div/div[@class="lead"]/p/text()' XPATH_LINK_TO_BODY = '//div[@class="html-content"]/p[not(@class)]/text()' def parse_notice(link, today): try: response = requests.get(link) if response.status_code == 200: # Traigo el docuemnto html de la noticia. notice = response.content.decode('utf-8') parsed = html.fromstring(notice) #Quiero traer el título, el cuerpo y el resumen, hago una validación # try -except, estoy haciendolo para los índices de la lista. # Pueden haber noticias con nodos faltantes por lo que arrojará un error try: #Traemos el primer elemento de la lista. title = parsed.xpath(XPATH_LINK_TO_TITLE)[0] # No es deseable tener comillas en los títulos porque presentan un error en OS. # Para solucionar esto, hacemos uso de que title es un str y del metodo replace() title = title title = title.replace('\"','') summary = parsed.xpath(XPATH_LINK_TO_SUMMARY)[0] body = parsed.xpath(XPATH_LINK_TO_BODY) except IndexError: return # Guardamos en un archivo # with es un manejador contextual. Si algo sucede y el script se cierra, mantiene las cosas # de manera segura y así no se corrompe el archivo. with open(f'{today}/{title}.txt','w', encoding ='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) # Creamos las funcioens para ejecutar el script. def parse_home(): # Creamos un bloque try para manejar los errores. Y manejar los Status Code. try: response = requests.get(HOME_URL) # Aqui va la lógica para traer los links. if response.status_code == 200: # .content trae el HTML que necesita ser traducido con un decode para que python lo entienda # en terminos de caracteres, me devuelve un string que no es más que el HTML crudo. home = response.content.decode('utf-8') # home = response.text # print(home) # En esta línea uso el parser html para transformar el contentido # html a un archivo que sea de utilidad para las expresiones xpath parsed = html.fromstring(home) print(parsed) # En esta línea estoy usando el archivo parseado con la función xpath y le paso por parámetro mi constante # la cual almacena la expresión Xpath. links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) # La línea de código me arroja un array vacío. Pero en google si lo enseña. print(len(links_to_notices)) # Depende de tu Xpath y la página web. print(type(links_to_notices)) # Tipo lista print(links_to_notices) # Traigo una fecha con la función fecha. Y Today, la fecha del dái de hoy. La variable today # se almacena un objeto de tipo fecha, pero nos interesa más tener una cadena de caracteres que contenga la fecha # en determinado formato que será guardado en la carpeta y con la función strftime logramos esto today = datetime.date.today().strftime('%d-%m-%Y') # Este condicional sirve para decirle que si no existe una carpeta con la fehca del día de hoy # me cree una carpeta. if not os.path.isdir(today): os.mkdir(today) # Creo la función para recorrer la lista de links y ejecuto en cada ciclo la función parse_notice() for link in links_to_notices: parse_notice(link,today) else: #Elevamos el error para ser capturado en el try-except, too lo que sea un error. raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == '__main__': run()
      Daniel Noreña

      Daniel Noreña

      student•
      hace 5 años

      Les compartomi codigo realizado en Abrl 15 (He visto difernecia entre varios compañeros en la estructura de la pagina). Como varios tuve problemas con los h2 que se solucionó reemplazando por text-fill. Así mismo tuve problemas con otras etiquetas que soluciones haciendo la expresión regular lo mas sencilla posible.

      Saludos a todos.

      <code> import requests import lxml.html as html import os import datetime HOME_URL='https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE= '//text-fill/a[@class="economiaSect" or @class="empresasSect" or @class="ocioSect" or @class="globoeconomiaSect" or @class="analistas-opinionSect"]/@href' XPATH_TITTLE='//div[@class="mb-auto"]/text-fill/span/text()' XPATH_SUMMARY='//div[@class ="lead"]/p/text()' XPTAH_BODY='//div[@class="html-content"]/p[not(@class)]/text()' def parse_notice(link,today): try: response=requests.get(link) if response.status_code==200: notice=response.content.decode('utf-8') parsed=html.fromstring(notice) try: tittle=parsed.xpath(XPATH_TITTLE)[0] print(tittle) tittle=tittle.replace('\"','') summary=parsed.xpath(XPATH_SUMMARY)[0] body=parsed.xpath(XPTAH_BODY) except IndexError: return with open(f'{today}/{tittle}.txt','w',encoding='utf-8') as f: f.write(tittle) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response= requests.get(HOME_URL) if response.status_code==200: home=response.content.decode('utf-8') parsed=html.fromstring(home) links_to_notices=parsed.xpath(XPATH_LINK_TO_ARTICLE) today=datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in links_to_notices: parse_notice(link,today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__=='__main__': run()
        Andres muñoz

        Andres muñoz

        student•
        hace 5 años

        muchas gracias por compartir la solución, a mi me tenia cabezón que solo me traía una noticia y cuando vi su código vi que en la variable XPATH_LINK_TO_ARTICLE yo la tenia trayendo una sola. Ya con su respuesta traer todo. Excelente bro

        Oscar Eduardo Chaparro Blancas

        Oscar Eduardo Chaparro Blancas

        student•
        hace 4 años

        Gracias a tu código encontré un error bien tonto en el mío, en donde estaba generando el response dentro del parseo de noticias con el link del home en vez del link de la noticia especifica.

        Agradezco mucho tu aporte compañero :)

      Elliot Ramirez

      Elliot Ramirez

      student•
      hace 4 años

      02/2022

      Para la solución removí el tag h2 del xpath titile, de resto todo continuo igual a la clase.

      import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//text-fill[not(@class)]/a/@href' XPATH_TITTLE = '//div[@class="mb-auto"]//span/text()' XPATH_SUMMARY = '//div[@class = "lead"]/p/text()' XPATH_BODY = '//div[@class = "html-content"]/p[not (@class)]/text()' def parse_notice(link,today): try: response=requests.get(link) if response.status_code==200: notice=response.content.decode('utf-8') parsed=html.fromstring(notice) try: tittle=parsed.xpath(XPATH_TITTLE)[0] print(tittle) tittle=tittle.replace('\"','') summary=parsed.xpath(XPATH_SUMMARY)[0] body=parsed.xpath(XPATH_BODY ) except IndexError: return with open(f'{today}/{tittle}.txt','w',encoding='utf-8') as f: f.write(tittle) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response= requests.get(HOME_URL) if response.status_code==200: home=response.content.decode('utf-8') parsed=html.fromstring(home) links_to_notices=parsed.xpath(XPATH_LINK_TO_ARTICLE) today=datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in links_to_notices: parse_notice(link,today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__=='__main__': run()
        Raul Burbano

        Raul Burbano

        student•
        hace 4 años

        Genial, pase mas una hora viendo que fallaba y esto me funciono perfecto

        Andres Matías Andreotta

        Andres Matías Andreotta

        student•
        hace 4 años

        Gracias! No encontraba el problema!

      Osvaldo Damián Ruiz

      Osvaldo Damián Ruiz

      student•
      hace 3 años

      Funcional al 3/1/2023

      saque lo del titulo del comentario de alonmar y de Pamela Pimentel lo de remplazar el h2

      import requests import lxml.html as html import os import datetime #Url de la pagina HOME_URL = 'https://www.larepublica.co' #url del articulo XPATH_LINK_TO_ARTICLE = '//text-fill/a/@href' #Extraer de cada articulo XPATH_TITTLE='//div/text-fill/span/text()' XPATH_SUMMARY='//*[@id="proportional-anchor-1"]/div/div/p/text()' XPATH_BODY='//div/div[4]/p/text()' def get_title(link): #separamos por "/" y nos quedamos con el ultimo que elemento url = link.split('/')[-1] #separamos por "-" y eliminamos el ultimo elemento title_list=url.split('-')[:-1] #Unimos lo anterior title = " ".join(title_list) return(title) def parse_notice(link, today): try: response = requests.get(link) if response.status_code==200: notice = response.content.decode('utf-8') #Guarda el contenido parsed = html.fromstring(notice) try: tittle = get_title(link) #obtiene el titulo summary = parsed.xpath(XPATH_SUMMARY)[0] #get te summary body = parsed.xpath(XPATH_BODY) #get the body except IndexError as ie: print(ie) return try: with open(f'{today}/{tittle}.txt', 'w', encoding='utf-8') as f: f.write(tittle) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: if p.endswith('.'): f.write(p) f.write('\n') else: f.write(p) except: print('no se pudo escribir') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) #Extraer links def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: #si la conexion es correcta home = response.content.decode('utf-8') #guarda en formato leible parsed = html.fromstring(home) #parsea links_to_notice = parsed.xpath(XPATH_LINK_TO_ARTICLE) # print(links_to_notice) today = datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in links_to_notice: parse_notice(link,today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == '__main__': run()
        Rafael Rivera

        Rafael Rivera

        student•
        hace 3 años

        Lo tenia muy similar, gracias por compartir.

        Julian Loaiza Lopez

        Julian Loaiza Lopez

        student•
        hace 3 años

        Gracias, me sacaste de un punto donde no podia avanzar

      Diego Martín

      Diego Martín

      student•
      hace 4 años

      06 de noviembre 2021 Con esto me funcionó:

      HOME_URL ='https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//text-fill/a/@href' XPATH_TITLE = '//div[@class="mb-auto"]/text-fill/span/text()' XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY = '//div[@class="html-content"]/p[not(@class)]/text()'

      El resto, todo es igual :)

        Mauro Andino

        Mauro Andino

        student•
        hace 4 años

        Gracias Diego, me funciono tu aporte

        Giocrisrai Godoy Bonillo

        Giocrisrai Godoy Bonillo

        student•
        hace 4 años

        genial muchas gracias por tu aporte

      David Santiago Martínez Vargas

      David Santiago Martínez Vargas

      student•
      hace 3 años

      Xpath a 14 de agosto de 2022

      En Body se usa descendant-or-self:: * para poder extraer TODO el texto ya que las palabras resaltadas en algunos artículos no son tomadas en la extracción.

      from string import printable import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = "//text-fill/a/@href" XPATH_TITLE = "//div[@class='mb-auto']/h2/span/text()" XPATH_SUMMARY = "//div[@class='lead']/p/text()" XPATH_BODY = "//div[@class='html-content']/p/descendant-or-self::*/text()" #to do: check how to extract the u html def parse_notice(link, today): try: response = requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') #save the content of the page in a variable parsed = html.fromstring(notice) #parse the html content try: title = parsed.xpath(XPATH_TITLE)[0] #get the title of the article title.replace('\"', '') #remove the quotes from the title title = title.replace('\'', '') #remove the quotes from the title title = title.replace('\n', '') #remove the newlines from the title title = title.replace('\t', '') #remove the tabs from the title title = title.replace('\r', '') #remove the carriage returns from the title title = title.strip() #remove the whitespaces from the title final_title = title title = title.replace('á', 'a').replace('é', 'e').replace('í', 'i').replace('ó', 'o').replace('ú', 'u') #replace the accents from the title title = title.replace('Á', 'A').replace('É', 'E').replace('Í', 'I').replace('Ó', 'O').replace('Ú', 'U') #replace the accents from the title title = title.replace('?', '').replace('¿', '').replace('!', '').replace('¡', '') #remove the question marks and exclamation marks from the title title = title.replace(':', '').replace(';', '').replace(',', '').replace('.', '').replace('(', '').replace(')', '') #remove the colons, semicolons, commas, dots, parentheses and spaces from the title title = title.replace('%', '').replace('$', '').replace('#', '').replace('@', '').replace('&', '').replace('*', '').replace('+', '').replace('=', '').replace('-', '').replace('_', '').replace('/', '').replace('\\', '').replace('|', '').replace('<', '').replace('>', '').replace('"', '').replace('\'', '') #remove the special characters from the title summary = parsed.xpath(XPATH_SUMMARY)[0] #get the summary of the article body = parsed.xpath(XPATH_BODY) #get the body of the article except IndexError as ie: print(ie) return try: with open(f'{today}/{title}.txt', 'w', encoding='utf-8') as file: file.write(final_title) file.write('\n\n') file.write(summary) file.write('\n\n') for p in body: file.write(p) file.write('\n') except: print('No se pudo escribir el archivo') else: raise ValueError(f'Error {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: home = response.content.decode('utf-8') #save the content of the page in a variable parsed = html.fromstring(home) #parse the html content links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) #get the links to the articles # print(links_to_notices) today = datetime.date.today().strftime('%d-%m-%Y') #get the current date if not os.path.isdir(today): #if the directory doesn't exist, create it os.mkdir(today) for link in links_to_notices: #for each link parse_notice(link, today) else : raise ValueError(f'Error {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == "__main__": run()
      Juan Fernando Moyano Ramírez

      Juan Fernando Moyano Ramírez

      student•
      hace 5 años

      Hola a todos, os comparto como ha quedado mi codigo al final:

      #el primer paso es importar todas las libreias que voy #a utilizar: import requests from lxml import html #la funcion HTML sirve para convertir archivos de HTML a un tipo de archivo con el cual pueda aplicar XPath import os #vamos a utilizar este modulo para crear una carpeta con la fecha de hoy import datetime #nos permite traer la fecha de hoy #despues debo crear las constantes que me llevaran #al cuerpo, el titulo y el resumen de la noticia. #contiene el link a la pagina principal de la republica HOME_URL = 'https://www.larepublica.co' XPATH_LINK_TO_ARTICLE = '//div[@class="V_Title"]/text-fill/a/@href' XPATH_LINK_TO_TITLE = '//div[@class="mb-auto"]/text-fill/span/text()' XPATH_LINK_TO_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_LINK_TO_BODY = '//div[@class="html-content"]/p[not(@class)]/text()' #ahora voy a crear las funciones de este programa #la funcion parse_home es la que se encarga de obtener #los links a las noticias: def parsed_notice(link, today): #envuelvo en un bloque try en caso de que el status_code de mi #peticion sea distinto a 200 try: response = requests.get(link)#solicito respusta al link de la noticia if response.status_code == 200: #primero quiero traer el documento html de la noticia notice = response.content.decode('utf-8') parsed = html.fromstring(notice)#lo convierto a un documento para aplicar xpath(un HTML con superpoderes) #el error contra el que me quiero proteger es si summary no tiene indices #es decir, no existe, en ese caso lo que quiero es salirme de la fucnion porque no #quiero noticias sin resumen try: #a estas variables pongo indices porque el resultado de aplicar xpath #a un html con superpoderes (parsed) nos devuleve una lista que puede tener uno a varios elementos #en este caso nosotros sabemos que el titulo, el resumen y el cuerpo #son el elemento 1 de una lista (index 0) title = parsed.xpath(XPATH_LINK_TO_TITLE)[0] #ahora voy a manejar el posible error de que el titulo tenga comillas #este link explica porque https://platzi.com/comentario/2198698/ title = title.replace('\"','') summary = parsed.xpath(XPATH_LINK_TO_SUMMARY)[0] #a body lo dejamos sin indice porque body es una lista de parrafos y quiero traerme la lista completa body = parsed.xpath(XPATH_LINK_TO_BODY) except IndexError: return #ahora vamos a guardar esta informacion. with es un gestor de contexto #es como un try bloc, en caso de que algo salga mal hace que el #archivo se cierre y no se corrampa. despues uso la funcion open para abrir archivo. Con esta fucnion #busco la carpeta que se creo con la fecha de hoy y dentro de esa carpeta #guardo un archivo que tiene como nombre el titulo de la noticia. #dentro de la funcion open el primer parametro nos indica la ruta del archivo, el segundo #nos dice que entramos en modo escritura, y el encoding nos permite guardar los caracteres especiales #de manera correcta para que no haya errores. Finalmente, nombro todo esto como # f with open(f'{today}/{title}.txt','w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') #necesito el for porque el body es una lista de parrafos for p in body: f.write(p) f.write('\n') else: raise ValueError(f'ERROR: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): #sin embargo, tendo que proteger mi codigo en caso #de errores como el codigo 404 try: #con la funcion de request me traigo el archivo #HTML de la pagina response = requests.get(HOME_URL)#con esto no solo obtengo el documentos HTML sino tambien http, como las cabeceras if response.status_code == 200: home = response.content.decode('utf-8') #.content traer el archivo HTML y el .decode('utf-8') #me ayuda a convertir los caracteres raros (ñ, tildes) en algo que #python pueda entender parsed = html.fromstring(home) #toma el archivo html de home y lo convierte en un tipo de archivo #a partir del cual yo puedo hacer XPath #ahora lo que me falta es obtener una lista de los links #que obtenga que he obtenido hasta ahora links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) #print(links_to_notices) today = datetime.date.today().strftime('%d-%m-%Y') #del modulo datetime traemos la funcion date y traemos #la fecha de hoy. Hasta esta parte guardamos un objeto #que nos da la fecha de hoy, pero lo que yo quiero es una string #que me de la fecha en el formato dia/mes/año, par ello uso #la funcion .strftime('%d-%m-%Y') #os.path.isdir(today) trae un booleano cuyo valor dependen de si hay #o no una carpeta con el nombre que hemos establecido (today) en la #carpeta en la que estamos. Si esa carpeta no existe creamos esa carpeta. isdir() method in Python is #used to check whether the specified path is an existing directory or not. if not os.path.isdir(today): #con esto creamos una carpeta con el nombre de la fecha de hoy si esa carpeta no existe os.mkdir(today) #por cada link en la lista vamos a entrar y extraer lo que queremos for link in links_to_notices: #esta funcion entra al link y extrae la infomacion que queremos #y eso lo va a guardar usando la fecha de hoy. parsed_notice(link, today) else: raise ValueError(f'ERROR: {response.status_code}') except ValueError as ve: print(ve) #la siguiente es la funcion principal, la que se va a ejecutar def run(): parse_home() if __name__ == '__main__': run()
      Jose David Ballesteros Paternina

      Jose David Ballesteros Paternina

      student•
      hace 5 años

      Tengo un problema al scrapear titulos que contengan simbolos como "¿?", lo que es raro ya que con el encoding UTF-8 arreglaria este tipo de problemas. El error es el siguiente:

      OSError: [Errno 22] Invalid argument: '19-03-2021/¿Los hombres son los que más compran vivienda nueva? Un estudio le aclara la duda.txt
        Jesús Eduardo Salgado Hernández

        Jesús Eduardo Salgado Hernández

        student•
        hace 4 años

        Hola, yo lo hice de esta manera, creando una función en donde use replace cada vez que encuentra un caracter especial:

        def delete_punctuation(sentence): for c in '?¿\"': sentence = sentence.replace(c, "") return sentence def parse_notice(link, today): try: response = requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') parse = html.fromstring(notice) try: title = parse.xpath(xpath_title)[0] new_title = delete_punctuation(title) summary = parse.xpath(xpath_summary)[0] body = parse.xpath(xpath_body) except IndexError: return with open(f'{today}/{new_title}.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve)
        Juan de Jesús Seco Arias

        Juan de Jesús Seco Arias

        student•
        hace 3 años

        Hola! a todos los que les salga este error, se soluciona incluyendo est linea inmediatamente debajo de la creación de la variable title:

        title= title.replace('\n', '').replace('“', '').replace('”', '')

      Joel Blanco

      Joel Blanco

      student•
      hace 4 años

      Lo que genera el cambio de h2 a text-fill és el decode.

      response.content.decode("utf-8")

      Si lo quitan no realitzarà cambios

      Yerson Alexander Arredondo García

      Yerson Alexander Arredondo García

      student•
      hace 5 años

      Les comparto mi código con la solución del ejercicio. Haciendo el análisis en la web, para sacar el titulo lo hice con //div[@class="mb-auto"]/h2/a/text(), pero la respuesta era diferente y tuve que usar //div[@class="mb-auto"]/text-fill/a/text()

      Vi en la sección de comentarios que también le paso a varios.

      import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//div[@class="V_Title"]/a/@href' XPATH_TITLE = '//div[@class="mb-auto"]/text-fill/a/text()' XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY = '//div[@class="html-content"]/p[not(@class)]/text()' def parse_notice(link, today): try: response = requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') parsed = html.fromstring(notice) try: title = parsed.xpath(XPATH_TITLE)[0] title = title.replace('\"', '') summary = parsed.xpath(XPATH_SUMMARY)[0] body = parsed.xpath(XPATH_BODY) except IndexError: return with open(f'{today}/{title}.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') f.write('\n\n') f.write(f'Más información en: {link}') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: home = response.content.decode('utf-8') parsed = html.fromstring(home) link_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) # print(link_to_notices) today = datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in link_to_notices: parse_notice(link, today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == '__main__': run()
        Aaron Fabrizio Calderon Guillermo

        Aaron Fabrizio Calderon Guillermo

        student•
        hace 5 años

        Genial! Funciona correctamente y con un solo cambio en el código.

      Alex Dario Portilla Chungandro

      Alex Dario Portilla Chungandro

      student•
      hace 5 años

      Por alguna razón mi codigo corre sin ningun error, pero al momento que me crea la carpeta que es donde se supone que se guardaran los archivos .txt estos no aparecen, la carpeta queda totalmente vacía. Alguien sabe como solucionarlo??. Les dejo mi codigo

      import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//div/h2/a/@href' XPATH_TITLE = '//h2[@style="font-size: 49px; line-height: 53px;"]/a/text()' XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY = '//div[@class="autoArticle" or @class="html-content"]/p/text()' def parse_notice(link, today): try: response= requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') parsed = html.fromstring(notice) try: title = parsed.xpath(XPATH_TITLE)[0] title = title.replace('\"','') summary = parsed.xpath(XPATH_SUMMARY)[0] body = parsed.xpath(XPATH_BODY) except IndexError: return with open(f'{today}/{title}.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ver: print(ve) def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: home = response.content.decode('utf-8') parsed = html.fromstring(home) links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) today = datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(today) for link in links_to_notices: parse_notice(link, today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__=="__main__": run()
        Massimo Di Berardino

        Massimo Di Berardino

        student•
        hace 5 años

        ¡Hola Alex! Validaste que el contenido de las variables title, summary y body esté llegando de manera correcta, puede ser que estas variables no estén tomando los valores y por eso no se escribe nada en el archivo.

        Alex Dario Portilla Chungandro

        Alex Dario Portilla Chungandro

        student•
        hace 5 años

        Hola si, yo tambien pense que ese podría ser el causante del porque no se guardan mis archivos, pero al revisar los xpath estos si me regresaban el texto, los verifique usando el .map(x => x.wholeText) para ver si realmente me regresaban el texto y efectivamente estos si me traen el texto que solcite.

      Helberts Andres Mosquera Clavijo

      Helberts Andres Mosquera Clavijo

      student•
      hace 4 años

      comence sacando noticias y el what if en mi cabeza se encendio y termine sacando todas las url de las paginas que ponia

      Alan Mariño

      Alan Mariño

      student•
      hace 4 años

      Los archivos no se pueden nombrar con caracteres como el ?, ¿ o el >, <, sin embargo, es posible que las noticias los tengan en sus títulos. Por esto se puede crear una simple solución con el mismo método que utiliza el profe cambiando las comillas por otros caracteres que nos interesen:

      title = title.replace('\"', '') title = title.replace('¿', '') title = title.replace('?', '')
        Anthony Campos

        Anthony Campos

        student•
        hace 3 años

        genial, con esta correción, triplqué mis archivos aprox a 30.

        = )

      Rene Rosas

      Rene Rosas

      student•
      hace 4 años

      Yo decidi hacer como ejercicio extraer la informacion de los libros de la tienda de toscrape(pagina que recomendo el profe facundo para practicar) con categoria "sequential art" extrae(titulo, precio, existencia y calificacion):

      import requests import lxml.html as html import os #BOOKS DATA XPATH_LINKS='//section/div/ol[@class="row"]/li/article[@class="product_pod"]/h3/a/@href' XPATH_TITLE='//section/div/ol[@class="row"]/li/article[@class="product_pod"]/h3/a/text()' XPATH_PRICE='//section/div/ol[@class="row"]/li/article[@class="product_pod"]/div[@class="product_price"]/p[@class="price_color"]/text()' XPATH_AVAILABILITY='//section/div/ol[@class="row"]/li/article[@class="product_pod"]/div[@class="product_price"]/p[@class="instock availability"]/text()' XPATH_RATE='//section/div/ol[@class="row"]/li/article[@class="product_pod"]/p/@class' URL='http // books toscrape com/catalogue/category/books/sequential-art_5/'#platzi me pidio romper el codigo URL_LIST= [] LINK_LIST=[] TITLE_LIST=[] PRICE_LIST=[] AVAILABILITY_LIST=[] RATE_LIST=[] #rate 1 to 5 def URL_PAGES(): for i in range(1,5): x=i y=(f'{URL}page-{x}.html') URL_LIST.append(y) def BOOK_INFO(): LINK=[] TITLE=[] PRICE=[] AVAILABILITY=[] RATE=[] for a in range(len(URL_LIST)): try: response=requests.get(URL_LIST[a]) if response.status_code == 200: home=response.content.decode('utf-8') parsed = html.fromstring(home) try: link= parsed.xpath(XPATH_LINKS) title= parsed.xpath(XPATH_TITLE) for i in range(len(title)): title[i]=title[i].replace('\"','') price= parsed.xpath(XPATH_PRICE) availability= parsed.xpath(XPATH_AVAILABILITY) for i in range(len(availability)): availability[i]=availability[i].strip('\n ') rate= parsed.xpath(XPATH_RATE) for i in range(len(rate)): rate[i]=rate[i].replace('star-rating ','') for x,n in enumerate(['One','Two','Three','Four','Five']): if rate[i]==n: rate[i]=x+1 except IndexError: return else: raise ValueError(response.status_code) except ValueError as ve: print(ve) LINK+=link TITLE+=title PRICE+=price AVAILABILITY+=availability RATE+=rate LINK_LIST.append(LINK) TITLE_LIST.append(TITLE) PRICE_LIST.append(PRICE) AVAILABILITY_LIST.append(AVAILABILITY) RATE_LIST.append(RATE) def run(): URL_PAGES() BOOK_INFO() print(TITLE_LIST[0][3]) print(PRICE_LIST[0][3]) print(AVAILABILITY_LIST[0][3]) print(RATE_LIST[0][3]) if __name__=='__main__': run()
      Geovany Uribe Aguirre

      Geovany Uribe Aguirre

      student•
      hace 5 años

      No me dejó correr el script, me aparece: UnboundLocalError: local variable 'title' referenced before assignment

        Saúl Alejandro Tapia Loya

        Saúl Alejandro Tapia Loya

        student•
        hace 5 años

        ¿Resolviste el problema? El error te está diciendo precisamente que estás accediendo a la variable "title" antes de que esta sea definida, puede ser que haya habido un error y se haya saltado la parte donde se definió.

      Luis Blas

      Luis Blas

      student•
      hace 4 años

      Les comparto como termine haciendo el reto. Cosas a considerar:

      • Como muchos otros notaron, en el XPath que usamos para extraer el titulo en Python, hay que cambiar el h2 por text-fill.

      • En el parse_home(), cuando extraigamos los links puede hayan algunos que estén repetidos. Por esto, usamos el links_to_notice = list(set(links_to_notice)) para quitar los duplicados de la lista. El set() transforma la lista en un conjunto donde todos sus elementos son diferentes, despues el list() lo vuelve a lista

      import requests import lxml.html as html import os import datetime HOME_URL = 'https://www.larepublica.co/' XPATH_LINK_TO_ARTICLE = '//div[@class="news V_Title_Img"]//a/@href' XPATH_TITLE = '//div[@class="mb-auto"]/text-fill/span/text()' XPATH_SUMMARY = '//div[@class="lead"]/p/text()' XPATH_BODY = '//div[@class="html-content"]/p/text()' def parse_notice(link,today): try: response = requests.get(link) if response.status_code == 200: notice = response.content.decode('utf-8') parsed = html.fromstring(notice) try: title = parsed.xpath(XPATH_TITLE)[0] title = title.replace('\"','') summary = parsed.xpath(XPATH_SUMMARY)[0] body = parsed.xpath(XPATH_BODY) except IndexError: print(IndexError) with open(f'{today}/{title}.txt', 'w', encoding='utf-8') as f: f.write(title) f.write('\n\n') f.write(summary) f.write('\n\n') for p in body: f.write(p) f.write('\n') else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def parse_home(): try: response = requests.get(HOME_URL) if response.status_code == 200: home = response.content.decode('utf-8') parsed = html.fromstring(home) links_to_notice = parsed.xpath(XPATH_LINK_TO_ARTICLE) # print(links_to_notice) links_to_notice = list(set(links_to_notice)) today = datetime.date.today().strftime('%d-%m-%Y') if not os.path.isdir(today): os.mkdir(f'{today}') for link in links_to_notice: parse_notice(link,today) else: raise ValueError(f'Error: {response.status_code}') except ValueError as ve: print(ve) def run(): parse_home() if __name__ == '__main__': run()

    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