Web Scraping con Python

Semillero de Ciencia de Datos

2022-12-10

Nuestro objetivo

  • Construir un lector de noticias actuales a través de Google Noticias con Python.

Flujo de trabajo…


¿HTML? 🤔

Estructura de árbol

Etiquetas, clases y atributos

¿Cómo acceder a los componentes?

¿xPath vs CSS?

ejemplo_css = '#yDmH0d > c-wiz:nth-child(27) > div > main > c-wiz > div.c4Stqc > c-wiz > c-wiz:nth-child(1) > c-wiz > div > article > div.XlKvRb > a'


❓❓❓
ejemplo_xpath = '/html/body/c-wiz[3]/div/main/c-wiz/div[2]/c-wiz/c-wiz[1]/c-wiz/div/article/div[1]/a'


🤔🤔🤔

Ejemplo con Scrapy

from scrapy import Selector    # Selector de componentes
import requests                # Peticiones a la página web
from datetime import datetime  # Conversión de fechas
import numpy as np             # Cálculos numéricos
import pandas as pd            # Manipulación de datos

Componentes en la página web

  • ¿Cuántos componentes tiene la página web de Google Noticias para Colombia?
# URL
url = 'https://news.google.com/topics/CAAqJggKIiBDQkFTRWdvSUwyMHZNREZzY3pJU0JtVnpMVFF4T1NnQVAB?hl=es-419&gl=CO&ceid=CO%3Aes-419'

# Acceso al contenido de la página web
html = requests.get(url).content
sel = Selector(text = html)

# Total de elementos en la página web
len(sel.xpath('//*'))
6050

Títulos de noticias

# Con xPath
titulos_xpath = sel.xpath('//a[@class = "WwrzSb"]/@aria-label').extract()

# Con CSS
titulos_css = sel.css('a.WwrzSb::attr(aria-label)').extract()

# ¿Tienen la misma longitud?
len(titulos_xpath) == len(titulos_css)
True
  • Primeras 5 noticias:
titulos_css[0:5]
['Así fue operativo en el que murió sujeto señalado de asesinar a dos policías en Bosa',
 'Habla uno de los policía que se enfrentó con presuntos delincuentes en Bosa',
 'Abatido uno de los asesinos de dos uniformados en Bosa',
 'Revelan video del asesino de dos policías en Bogotá justo luego del crimen; iba tranquilo',
 'Ya hay 156 quemados con pólvora en solo 8 días']

Fuente de noticias

# xPath
fuente_xpath = sel.xpath('//span[@class = "vr1PYe"]/text()').extract()

# CSS
fuente_css = sel.css('span.vr1PYe::text').extract()

# ¿Tienen la misma longitud?
len(fuente_xpath) == len(fuente_css)
True
  • Primeras 5 fuentes:
fuente_xpath[0:5]
['Noticias Caracol',
 'Noticias Caracol',
 'Canal 1',
 'Pulzo.com',
 'El Colombiano']

Fecha de noticia

# xPath
fecha_xpath = sel.xpath('//time[@class = "hvbAAd"]/@datetime').extract()

for i in range(len(fecha_xpath)):
  fecha_xpath[i] = datetime.strptime(fecha_xpath[i], '%Y-%m-%dT%H:%M:%SZ')

# CSS
fecha_css = sel.css('time.hvbAAd::attr(datetime)').extract()

for i in range(len(fecha_css)):
  fecha_css[i] = datetime.strptime(fecha_css[i], '%Y-%m-%dT%H:%M:%SZ')

# ¿Tienen la misma longitud?
len(fecha_xpath) == len(fecha_css)
True
  • Fecha mínima:
print(np.min(fecha_css))
2022-12-07 14:26:57
  • Fecha máxima:
print(np.max(fecha_css))
2022-12-10 13:19:10

Tabla final de noticias

lista_noticias = [titulos_xpath, fuente_xpath, fecha_xpath]

df_noticias = pd.DataFrame(lista_noticias).transpose()
df_noticias.columns = ['noticia', 'fuente', 'fecha']

df_noticias.head(n=2)
noticia fuente fecha
0 Así fue operativo en el que murió sujeto señal... Noticias Caracol 2022-12-09 18:21:04
1 Habla uno de los policía que se enfrentó con p... Noticias Caracol 2022-12-10 01:17:12

Rastreadores web con Scrapy

Recursos de información

Gracias