No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

¡Se acaba el precio especial! Aprende Inglés, AI, programación y más.

Antes: $249

Currency
$209
Suscríbete

Termina en:

1 Días
10 Hrs
19 Min
16 Seg

Obteniendo los links de los artículos con Python

19/21
Recursos

Aportes 64

Preguntas 39

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

hey profe Facundo, sos lo maximo!, despues de maradona estas vos che!
muy muy buena esta clase

Para los que no les esté funcionando el path, recuerden cambiar los “h2” por “text-fill”. Ej de mi path:

XPATH_LINK_TO_ARTICLE = '//div[@class="news V_Title_Img" or @class="V_Title"]/text-fill/a/@href'```

No se muy bien porque con h2 no funciona.

Marzo 2022
Para los que tengan problema para recibir los links, revisando veo que dice que Python no interpreta adecuadamente los h2, ocasionando que tu código Xpath en la consola sí te da resultados pero en el programa no, la solución es reemplazar los h2 por text-fil:

Este era mi código:

//h2[@class=""]/a/@href```

Y este es el código que sí me funcionó:

//text-fill[not(@class)]/a/@href

Tengo un problemita con el scrapper y es que en la consola de Chrome el Xpath para los links me devuelve 84 urls (de los cuales 77 pertenecen a larepublica.co), y en el código solo me trae 15…
Adjunto el código y el screenshot de la consola de Chrome por si me pueden ayudar.

Codigo:

import requests
import lxml.html as html # para aplicar Xpath a HTML

HOME_URL = 'https://www.larepublica.co/'


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


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(len(links_to_notices))
            print(links_to_notices)
            
        else:
            raise ValueError(f"Error: {response.status_code}")


    except ValueError as ve: 
        print(ve)

def main():
    parse_home()

if __name__ == '__main__':
    main()

Screenshot:

![](

RESUMEN:Desarrollo proyecto

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  1. Obtener todos los links con python.
import requests
import lxml.html as html

# Creamos constantes

HOME_URL = 'https://www.larepublica.co/'

XPATH_LINK_TO_ARTICLE = '//div/h2[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()'

# 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 noes más que el HTML crudo.
            home = response.content.decode('utf-8')

            # Tambien podemos usar el método text para parsear la respuesta a texto.
            # home = response.text
            # print(home)

            # En esta línea uso el parser 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)
            
            # For debugg
            # print(len(links_to_notices))
            # print(type(links_to_notices))
            # print(links_to_notices)

        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()

Errores Asociados y comentarios:


1 ■ Primera recomendación es que uses el print statement para debuggear tus código
línea por línea. Es una práctica que resulta muy útil.

2 ■ ¿Tienes una lista vacía?, ¿No te trae los links al ejecutar scraper.py, pero tu expresion Xpath retorna en la consola de Chrome lo que buscas?.

  • R: Cambia tu expresión Xpath. Es posible que varias cosas estén ocurriendo y una de las más probables es la expresión Xpath, recuerda que tienes muchas formas de llegar al mismo nodo.

Que alguien le diga a Fredy que Facundo dicte todos los cursos donde tenga que ver Python. No es crear rivalidades pero el mejor de todos en enseñar en Python. Grande Facundo.

Si cuando importan los módulos les marca error, solo tienen que tener seleccionado el interprete correcto en Visual Studio Code.

Para cambiar el interprete accederemos con SHIFT + CONTROL + P y apuntaremos Select interpreter y seleccionaremos el entorno virtual correcto.

Antes deberán tener instalado los módulos como el profesor ha explicado. A mi me ha funcionado de esta manera, espero que les sea de ayuda. ^^

import requests
import lxml.html as html

HOME_URL = 'https://www.larepublica.co/'

XPATH_LINKS_TO_ARTICLE = '//text-fill[not(@class)]/a/@href'
XPATH_TITLE = '//div[@class="mb-auto"]/h2/a/text()'
XPATH_SUMMARY = '//div[@class="lead"]/p/text()'
XPATH_BOBY = '//div[@class="html-content"]/p/text()'


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_LINKS_TO_ARTICLE)
            print(link_to_notices)
        else:
            raise ValueError(f'Error: {response.status_code}')
    except ValueError as ve:
        print(ve)


def run():
    parse_home()


if __name__ == "__main__":
    run()```

Nosé si será por gitbash, pero a la hora de importar los módulos me sale un error que no me los reconoce.
Instalé los módulos en venv como nos enseñaron pero nosé a que se debe el error.

Prueben con este XPATH para los links

XPATH_LINKS = '//a[contains(@class, "kicker")]/@href'

Un poco tarde, pero les explico un poco por que en nuestro scrapper recibimos menos links de los que hay en la pagina

Lo que pasa es que la pagina carga primero un contenido ligero (que es lo que recibe nuetstro scrapper) y despues de unos segundos carga todo lo demás gracias al codigo javascript que se ejecuta en el navegador, es por esto que aunque nosotros podamos ver los h2 en la pagina, nuestro scrapper no puede por que no está ejecutando el javascript que los genera

El profe Facundo es EL MEJOR!!!, sus cursos son los mejores explicados y entendibles!

De todos los cursos de Platzi que he hecho por fin alguien que dice la importancia de escribir los códigos en inglés! Finally!! Esto es una buena práctica que veo que en muchos cursos tristemente no se sigue.

Hola a todos, yo tenia el problema de que no se adjuntaban los links a la lista links_to_notices, y la razon era un par de problemas con las expresiones de xpath, os adjunto la pregunta en el foro de esta clase que me ayudo a resolver mi problema.

https://platzi.com/comentario/2166481/

el diario de la republica realizo cambios y para obtener la expresion necesitada para los links ahora es:

//a[@class="economiaSect" or @class="kicker globoeconomiaSect"]/@href

¿A alguien más le pasó qué le devuelve una lista vacía?

Este es el código que estoy utilizando:

XPATH_LINK_TO_ARTICLE='//h2[@style and not(@class)]/a/@href'

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)

    else: 
      raise ValueError(f'Error: {response.status_code}')
 
  except ValueError as ve:
    print(ve)


def run():
  parse_home()

Después de un rato xD me faltaban dos cositas

Si no les trae todos los resultados es porque la página usa lazy load. Estuve chequeando y toca aprender Selenium

Si tienen problemas a la hora de importar los módulos porque no aparecen, vayan a View–>Command Palette(o Ctrl+Shift+P) y en el buscador escriban Python Select Interpreter, Después busquen en la carpeta donde instalaron su entorno virtual que maomeno sería venv/Scripts/python y lo seleccionan.
Si aun siguen teniendo problemas con los modulos, vuelvan a instalarlos y listo.

3/1/2023

import requests
import lxml.html as html

#Url de la pagina

HOME_URL = 'https://www.larepublica.co/'

#url del articulo
XPATH_LINK_TO_ARTICLE = '//h2/a/@href'

XPATH_TITLE='//div/h2/span/text()'
XPATH_SUMMARY='//*[@id="proportional-anchor-1"]/div/div/p/text()'
XPATH_BODY='//div/div[4]/p/text()'


#Extraer links
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)
        else:
            raise ValueError(f'Error: {response.status_code}')
    except ValueError as ve:
        print(ve)

def run():
    parse_home()

if __name__ == '__main__':
    run()

Dios mio que bellezaaa!!!

import requests
import lxml.html as html

home_url = "https://www.larepublica.co/"
links = "//h2/a/@href"
titulo = "//h2[not(@class)]/span/text()"
resumen  = '//div[@class = "lead"]/p/text()'
cuerpo    = '//div[@class = "html-content"]/p/text()'

def parse_home():
    try:
        response = requests.get(home_url)
        if response.status_code == 200:
            home = response.content.decode('utf-8') # Decode cambia los valores como ñ en letras que python entienda
            parse = html.fromstring(home)  # Usando lxml me transforma el codigo html de requests a codigo xpath
            links_xpath = parse.xpath(links) # Busca la expresión xpath en el html xpath
            print(links_xpath)

        else:
            raise ValueError(f"Error {response.status_code}")
    except ValueError as ve:
        print(ve)

def run():
    parse_home()

if __name__ == "__main__":
    run()

Para que Visual Studio Code tome correctamente las librerías del entrono virtual y no genere ese subrayado en los import debes debes indicarle que vas a usar el intérprete del entorno virtual así:

  • ctrl + shift + p
  • Python: Select interpreter
  • Seleccionar archivo “python.exe” dentro de venv/Scripts/

Yo estoy haciendo de una pagina de electrodomésticos, mas específicamente la sección de notebooks

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


#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 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)
            
            
        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()

Para que puedan visualizar de manera ordenada los links,
pueden usar el módulo pprint.
El cual imprime los arreglos de forma vertical y mejor a la vista.

#!/usr/bin/python

import requests
import lxml.html as html
from pprint import pprint

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


def parse_home():
    try:
        response = requests.get(HOME_URL)
        if response.status_code == 200:
            # response.content html document from the response
            home = response.content.decode('utf-8')

            # take the html content in home as text and transform in
            # special document to do xpath
            parsed = html.fromstring(home)

            links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE)
            pprint(links_to_notices)
        else:
            raise ValueError(f'Error: {response.status_code}')
    except ValueError as ve:
        print(str(ve))

def run():
    parse_home()



if __name__ == '__main__':
    run()

Hola, buen día compañeros,
Tengo una duda, ya solucione el tema de que el scraper no me arrojaba el total de lynks que arroja el navegador. Sin embargo ahora me arrojo muchos lynks duplicados. Alguien sabe como puedo solucionarlo?
Gracias!!

Hola, alguien sabe como era el nombre del emulador de consolas que nombró el profesor? Cender o Sender o algo así. No he conseguido encontrarlo en el buscador

Hola yo tuve el mismo problema que muchos otros en los comentarios, el cual nos dice que no se reconocen los modulos, lo solucione desinstalando y reinstalando manualmente los modulos usando pip. Se que no hace mucho sentido y tampo te podria decir por que funciono pero al fin es lo que a mi me soluciono el problema
Aqui los pasos para los que lo necesiten
pip uninstall <module_name>
pip install <module_name>

Hola a todos.
Las paginas web son seres vivientes que cambian cada tanto.
Hoy 25 de Junio el Xpath para el cuerpo del articulo a cambiado a:

//div[@class="articleWrapper  "]/div[not(@class)]/text()'

Tengo este error que no he podido solucionar, alguien me puede ayudar?

Traceback (most recent call last):
  File "D:\Documentos\PLATZI\Escuela_DS_AI_ML\Curso_Fundamentos_webScraping\LaReplublica_Scraper\scraper3.py", line 30, in <module>
    run()
  File "D:\Documentos\PLATZI\Escuela_DS_AI_ML\Curso_Fundamentos_webScraping\LaReplublica_Scraper\scraper3.py", line 27, in run
    parse_home()
  File "D:\Documentos\PLATZI\Escuela_DS_AI_ML\Curso_Fundamentos_webScraping\LaReplublica_Scraper\scraper3.py", line 19, in parse_home
    links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) #Obtener lista de links con comandos xtpath del documento contenido en parsed
  File "src\lxml\etree.pyx", line 1599, in lxml.etree._Element.xpath
  File "src\lxml\xpath.pxi", line 305, in lxml.etree.XPathElementEvaluator.__call__
  File "src\lxml\xpath.pxi", line 225, in lxml.etree._XPathEvaluatorBase._handle_result
lxml.etree.XPathEvalError: Invalid expression

Este es mi código:

import requests
import lxml.html as html 

HOME_URL = 'https://www.larepublica.co/' #URL de la página home

XPATH_LINK_TO_ARTICLE = "$x('//text-fill/a/@href').map(x => x.value)"
XPATH_TITLE = "$x('//h2/span/text()').map(x => x.wholeText)"
XPATH_SUMMARY = "$x('//div[@class='lead']/p/text()').map(x => x.wholeText)"
XPATH_BODY = "$x('//div[@class='html-content']/p[not(@class)]/text()').map(x => x.wholeText)"

#Función para extraer los links de las noticias
def parse_home():
    #Envolver el código dentro de un bloque try except
    try:
        response = requests.get(HOME_URL) #Método para traer el archivo html de la página > LA RESPUESTA ES el documento html y todo la estructura HTTP
        if response.status_code == 200: #Si la respuesta del servidor es 200 está OK
            home = response.content.decode('utf-8') #reponse.content -> devuelve el documento html .decode ->tranforma caracteres expeciales a python
            parsed = html.fromstring(home) #Toma el contenido html contenido en home y lo transforma en un documento para ejecutar xpath
            links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE) #Obtener lista de links con comandos xtpath del documento contenido en parsed
            print(links_to_notices)
        else:
            raise ValueError(f'Error: {response.status_code}') #Si la respuesta del servidor no es 200 se levanta un error ValueError para luego ejecutar el except
    except ValueError as ve: #Si sucede un error tipo 404 imprima ve
        print(ve)

def run():
    parse_home()

if __name__ == '__main__':
    run()

Brutal

Tambien pueden leer este articulo como aporte donde se explica mejor el termino Text-fill
[https://platzi.com/tutoriales/1908-web-scraping/7042-news-web-scraping-codigo-python/]

Si no les funciona el codigo revisen el archivo xpath.txt

Hola muchachos les dejo una solución del proyecto utilizando programación concurrente para acelerar los procesos. Saludos

import requests
import lxml.html as html
import threading
import datetime
import queue
import os


XPATH_LINK_TO_ARTICLES = '//div[@class="news V_Title_Img"]/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/text()'

HOME_URL = 'https://www.larepublica.co/'


def process(q,today):
	while True:
		try:
			no_notice, parsed = q.get(timeout=0.5)
		except queue.Empty:
			break
		
		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}/notice_{no_notice}.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")

		q.task_done()


def fetch(link,no_notice, q):
	try:
		response = requests.get(link)
		if response.status_code == 200:
			notice = response.content.decode('utf-8')
			parsed = html.fromstring(notice)
			q.put((no_notice, parsed))
		else:
			raise ValueError("Error {}".format(response.status_code))
	except ValueError as ve:
		print(ve)


def parse_home():
	
	q = queue.Queue()
	producer_threads = []
	consumer_threads = []

	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_ARTICLES)

			today = datetime.date.today().strftime('%d-%m-%Y') + "with_concurrency"
			if not os.path.isdir(today):
				os.mkdir(today)

			
			for no_notice,link in enumerate(link_to_notices,1):
				t = threading.Thread(target = fetch, args = [link,no_notice, q])
				t.start()
				producer_threads.append(t)

			for _ in range(len(link_to_notices)):
				t = threading.Thread(target = process, args = [q,today])
				t.start()
				consumer_threads.append(t)

			q.join()

			threads = producer_threads + consumer_threads
			for t in threads:
				t.join()

		else:
			raise ValueError("Error: {}".format(response.status_code))
	except ValueError as ve:	
		print(ve)



def run():
	parse_home()

if __name__=="__main__":
	run()

tuve que usar este para los links , ahora que han cambiado nuevamente el site .

$x('//div[@class="col mb-4"]/div[@class="news V_Title_Img"]/a[position()=1]/@href').map(x => x.value)

Hola amigos, tuve un problema con la cantidad de links que extraía mi código. Hay muchos aportes muy bien detallados, les comparto el link.

Pero si estas con los minutos, en resumen hay que cambiar h2 por text-fill

😃

'//h2/a/@href'
'//text-fill/a/@href'

Problema
Solucion

Para los nuevos que no les de el xpath reemplacen el h2 por text-fill en el path

'//text-fill[not(@class)]/a/@href'

https://platzi.com/tutoriales/1908-web-scraping/7042-news-web-scraping-codigo-python/

Excelente curso. A partir de este punto ya me largué solo. Ansioso por ver que más tiene para dar!

Al día de hoy (22 de Enero del 2021) esta fue la solución a la que yo llegué, por si alguien está teniendo problemas recientemente jaja

import requests
import lxml.html as html

home_url = 'https://www.larepublica.co/'

dummy_xpath = '//h2/a/@href'

xpath_links= '//div[@class="news V_Title_Img" or @class="V_Title"]/a/@href'

xpath_title = '//div[@class="mb-auto"]//a/text()'

xpath_summary = '//div[@class="lead"]/p/text()'

xpath_body = '//div[@class="html-content"]/p/text()'

def parse_home():
	try:
		response = requests.get(home_url)
		
		if response.status_code == 200:
			#response.content se trae el contenido html de la pagina
			#decode con utf-8 resuelve problemas de lectura de caracteres raros
			home = response.content.decode('utf-8')
			#en parsed almaceno un objeto hecho desde home
			#sobre el que voy a poder hacer busquedas de tipo xpath
			parsed = html.fromstring(home)
			
			links_to_news = parsed.xpath(xpath_links)
			
			print(links_to_news)
			
		else:
			raise ValueError(f'Error:{response.status_code}')
			
			
	except ValueError as ve:
		print(ve)
	
	
def run():
	parse_home()

#defino el entry-point
if __name__ == '__main__':
	run()

Buenas, alguien sabe si a la libreria requests hay que instalarla o viene preinstalada con Python?

import request
import lxml.html as html 
 
HOME_URL = 'https://www.larepublica.co/'

XPATH_LINK_TO_ARTICLE = '//h2[@class="headline"]/a/@href'
XPATH_TITLE = '//h1[@class]="headline"]/a/text()'
XPATH_SUMMARY = '//div[@class="lead"]/p/text()'
XPATH_BODY = '//div[@class"articlewrapper "]/p[not(@class)]/text()'

def parse_home():
    try:
        response = request.get(HOME_URL)
        if response.status_code == 200:
            home = response.contect.decode('utf-8')
            parsed = html.fronstring(home)
            links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE)
            print(links_to_notices)
        else:
            raise ValueError(f'Error: {response.status_code}')
    except ValueError as ve: 
        print(ve)

def run():
    parse_home()

if __name__ == '__main__':
    run()

Increible.

Demasiado util, aprender a hacerlo todo desde la consola.

Si tienen problema para que funcione el programa intenten con los siguientes comandos, en caso de que tengan zsh y ubuntu dentro de windows:
1.- python3.7 -m pip install requests.
2.- python3.7 -m pip install lxml.
3.- python3.7 scraper.py

Después de eso debería de funcionar correctamente, si tienen activado el venv.

Tengo ese error ?Como puedo arreglarlo?

![](

No olviden que tienen que estar en VENV para correrlo de lo contrario no reconocerá las librerías instaladas
En Win:
venv\Scripts\activate

Hola amigos! No sé si alguno haya tenido la misma situación que yo y es que en el VSCode no me funciona el autocompletado cuando estoy en un entorno virtual. supongo que es debido a que esas dependencias que instalamos están vinculadas a la version de Python que está dentro del entorno virtual. Para esto lo que hice fue una carpeta llamada .vscode en el directorio raíz del proyecto (también se añade al gitignore ya que es algo para trabajar de manera local) y dentro de esa carpeta se crea un archivo que tendrá como normbre settings.json. Aquí Pondremos el siguiente código:

{
    "python.pythonPath": "./venv/bin/python"
}

Aquí le estamos indicando al editor que la version de Python que deberá utilizar es la que está dentro de nuestro entorno virtual, para que pueda autocompletar todas las dependencias y con sus respectivos docstrings.

PD: Estoy trabajando en un ambiente UNIX, para Windows podrían probar usando la ruta con backslash (\) en lugar de slash (/). No se si funciona de esta manera, me comentan si alguien lo prueba

Creo que encontre el xpath correcto para los links de noticias:

//div[contains(@class, "V")]/a[contains(@class, "kicker")]/@href

Perdón por enviar esto a aportes y no a preguntas

Alguno no le funciono lxml.html ?

Añado una foto del codigo de scraper.py a mi consulta anterior, por si algún alma bro me ayuda 😃
![](

No consigo que en la consola Cmder me haga nada con py scraper.py
Los links que he puesto son del periódico El País en España, que en la consola de la página web me funcionaban bien.
He repasado el código del programa de Facundo y lo tengo todo igual (excepto los links, y la url)
La consola me funciona, pero esa instrucción no me hace nada. De hecho tenía unos errores sintácticos en scraper.py y cmder me los detectaba. ¿Tenéis alguna idea de qué puede pasar?![](

Mi path

Links = //h2/a[@class="empresasSect"]/@href
Titulo = //h2/a[@class="finanzasSect"]/text()
Resumen = //div[@class="lead"]/p/text()
Cuerpo = //div[@class="html-content"]/p[not(@class)]/text()

¿Con que objetivo se crea la función run, si podemos ejecutar la función parse_home directamente?

Hola a todos, os dejo mis apuntes de esta clase, sin embargo, este es un respositorio en el que estan todos loa apuntes de este curso: https://github.com/fer2002743/web-scraping

<h1>Obteniendo los links de los artículos con Python</h1>

Una vez ya tenemos las expresiones de XPath para obtener acceder a la informacion que queremos el sigiente paso es construir el script de python para extraer toda la informacion que deseemos.

El paso numero uno es importar todos los modulos necesarios, en este caso necesitamos requests y la funcion HTML de lxml.

import requests
from lxml import html

En el segundo paso vamos a crear las constantes que contiene los links a la informacion del periodico que quermos acceder.

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()'

El tercer paso consiste en crear la estructura basica del script:

#la funcion parse_home es la que se encarga de obtener
#los links a las noticias:

def parse_home():
  pass

#la funcion principal del programa
def run():
  parse_home()

#creamos el entry point
if __name__ == '__main__':
  run()

Una vez hecho empezaremos con el paso cuatro el cual consiste en escribir el codigo de la funcion parse_home(), encargada de obtener los links que necesitamos. Primero vamos a proteger a nuestro codigo de posibles errores como el status code 404, para ello usaremos un bloque try.

def pearse():
    #protejo mi codigo en caso
    #de errores como el codigo 404
    try:
      pass

    except ValueError as ve:
      print(ve)

Una vez hecho esto procederemos a hacer una peticion al periodico la republica, para ello usaremos el metodo get() del modulo requests. Este metodo nos sirve para hacer una peticion al servidor usando python y nos retorna un objeto con toda la informacion de la respuesta, como el status code y el contenido.

def pearse():
    try:
      response = requests.get(HOME_URL)

    except ValueError as ve:
      print(ve)

Despues procedo a verificar que todo esta bien (status code 200), si hay algo fuera de lo comun levanto un error.

def pearse_home():
    try:
      response = requests.get(HOME_URL)
      if response.status_code == 200:
        pass
      else:
        raise ValueError(f'ERROR: {response.status_code}')

    except ValueError as ve:
      print(ve)

Genal, ya hemos conseguido la pagina principal del periodico, sin embargo, ahora necesitamos hacer que su contenido se convierta en algo entendible para python. Para conseguir esto accedo al contenido de la respuesta del servidor (response.content) y uso el metodo decode('utf-8) para convertirlo en algoo entendible para python.

def pearse_home():
    try:
      response = requests.get(HOME_URL)
      if response.status_code == 200:
        home = response.content.decode('rtf-8')
      else:
        raise ValueError(f'ERROR: {response.status_code}')

    except ValueError as ve:
      print(ve)

Finalmente necesito tomar el tipo de archivov HTML de home y convertirlo en un tipo de archivo con el cual pueda usar expresiones de XPath para navegar entre sus datos. Para ello usaremos el metodo .fromstring() de la funcion html del modulo xml.

import requests
from lxml import html 

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()'

def pearse_home():
    
    try:
      response = requests.get(HOME_URL)
      if response.status_code == 200:
        home = response.content.decode('rtf-8')

        parsed = html.fromstring(home)

        #una vez tenemos el archivo en un formato estructurado, vamos a usar XPath para navegar por el archivo y guardaremos esos datos en una lista

        links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE)
      else:
        raise ValueError(f'ERROR: {response.status_code}')

    except ValueError as ve:
      print(ve)

def run():
  pearse_home()

if __name__ == '__main__':
  run()

Adjunto mi codigo comentado por si a alguien le sirve:

#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


#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 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)
            
            
        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()

yo ocupe este comando: //a[@class=“economiaSect”]/@href
a la fecha de hoy ese sirve nose si luego reestructuren el html y sea de otra forma

Pero hoy en dia toca hacer link por cada sección que nos interesa sacar los links

import requests
import lxml.html as html


HOME_URL='https://www.larepublica.co'

XPATH_LINK_2_ARTICLE = '//h2/a/@href'
XPATH_TITLE = '//h2/a/text()'
XPATH_RESUME = '//div[@class="lead"]/p/text()'
XPATH_BODY = '//div[@class="html-content"]/p[not(@class)]/text()'

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_2_ARTICLE)
            print(links_to_notices)
        else:
            raise ValueError(f'Error: {response.status_code}')
    except ValueError as ve:
        print(ve)

def run():
    parse_home()

if __name__ == '__main__':
    run()

En caso de que, desees que se importen solamente los links que cuentan con una palabra clave (por ejemplo, que deseas extraer solamente la sección de finanzas), es posible con list comprehension en Python:

print([k for k in links_to_notices if "finanzas" in k])

Hola, alguein sabe como instalar el ambiente virtual en windows? gracias