El scraping o web scraping es una técnica utilizada para extraer datos de sitios web de manera automatizada. Consiste en usar programas o scripts para navegar por una página web, extraer información específica (como texto, imágenes, precios de productos, etc.), y guardarla.
En este post, enseñaré el proceso que uso para hacer scraping y qué puntos importantes hay que tener en cuenta al hacerlo.
En mi caso, realizaré scraping en PcComponentes para recolectar información sobre laptops. Estos datos se utilizarán para crear un dataset que servirá como base para un modelo de Machine Learning, diseñado para predecir el precio de un portátil según los componentes que se le especifiquen.
Primero, es necesario identificar a qué URL debe acceder el script para hacer el scraping:
En este caso, si nos fijamos en la URL de PcComponentes, podemos ver que pasa un parámetro por la URL, el cual podemos usar para especificar lo que queremos buscar.
Una vez hecho esto, veremos el resultado de la búsqueda:
Después de esto, utilizaremos la herramienta para desarrolladores que casi todos los navegadores tienen integrada:
Al hacer clic derecho y luego seleccionar la opción "Inspeccionar", se abrirá la herramienta de desarrollador, y veremos lo siguiente:
Una etiqueta de tipo anchor (<a></a>
) que contiene bastante información referente al producto que vemos en los resultados de la búsqueda.
Si nos fijamos en la siguiente zona, veremos prácticamente todos los datos del producto:
¡Listo! Tenemos la zona de donde extraer los datos. Ahora toca crear el script para que los extraiga.
Pero nos encontramos con un problema: si se accede a PcComponentes directamente, siempre nos pide que aceptemos las políticas de cookies. Entonces, no podemos hacer una petición GET y realizar el scraping del resultado, ya que no obtendríamos nada.
Por lo tanto, tendremos que usar Selenium para simular el navegador y poder interactuar con él.
Comenzamos haciendo lo siguiente:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
options = Options()
options.headless = True
#Abrimos el navegador
driver = webdriver.Firefox(options=options)
time.sleep(5)
#Vamos a la página indicada pccomponentes.com/laptops
driver.get(url+str(i))
#Esperamos 30 segundos hasta que aparezca el botón de cookies y al aparecer hace clic
accept_cookies = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((By.ID, 'cookiesAcceptAll'))
)
accept_cookies.click()
#Descargamos el HTML
html = driver.page_source
Una vez hecho esto, en la variable html
obtendremos el código HTML de la página a scrapear.
Sin embargo, nos encontramos con otro problema. Al abrir el navegador con Selenium y hacer 2 o 3 peticiones, Cloudflare nos limita las peticiones y no nos permite hacer más. Por lo tanto, solo podríamos scrapear unas 3 páginas, lo cual serían unos 20 ordenadores distintos. Insuficiente para hacer un dataset.
Una solución que se me ocurrió fue descargar la página localmente y trabajar con el HTML en local. Luego de haber hecho el scraping, podríamos abrir otro navegador (esperando un tiempo prudencial) y descargar la siguiente.
Así que agregué el código anterior a una función y lo englobé en un for de la siguiente manera:
#Función que se conecta a pccomponentes y guarda el html en local
def guarda_datos_html(i=0):
try:
options = Options()
options.headless = True
#Abrimos el navegador
driver = webdriver.Firefox(options=options)
time.sleep(5)
#Vamos a la página indicada pccomponentes.com/laptops
driver.get(url+str(i))
#Esperamos 30 segundos hasta que aparezca el botón de cookies y al aparecer hace clic
accept_cookies = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((By.ID, 'cookiesAcceptAll'))
)
accept_cookies.click()
#Descargamos el HTML
html = driver.page_source
#Lo guardamos en local
with open(f'html/laptops_{i}.html','w',encoding="utf-8") as document:
document.write(html)
driver.close()
except:
print(f'Error en página: {i}')
for i in range(0,58):
guarda_datos_html(i)
time.sleep(30)
Ahora sí podremos recuperar los HTML y trabajar con ellos. Para ello, instalé BeautifulSoup, un paquete que se usa muy a menudo en scraping.
Vamos a desarrollar la función para recabar la información del HTML que hemos descargado gracias a la función anterior.
La función quedó así:
# Función que abre el HTML guardado con anterioridad y filtra los datos
# para guardarlos en un CSV ordenados
def get_datos_html(i=0):
try:
with open(f'laptop_data_actual.csv','a') as ldata:
field = ['Company','Inches','Cpu','Ram','Gpu','OpSys','SSD','Price']
writer = csv.DictWriter(ldata, fieldnames=field)
with open(f'html/laptops_{i}.html','r',encoding="utf-8") as document:
html = BeautifulSoup(document.read(), 'html.parser')
products = html.find_all('a')
for element in products:
pc = element.get('data-product-name')
if pc:
pc = pc.lower()
marca = element.get('data-product-brand')
price = element.get('data-product-price')
pc_data = pc.split('/')
cpu = pc_data[0].split(' ')
cpu = buscar_cpu(cpu)
gpu = buscar_gpu(pc_data)
inches = '.'.join([s for s in re.findall(r'\b\d+\b', pc_data[-1])])
OpSys = bucar_opsys(pc_data, marca)
row = {
'Company': marca,
'Inches': inches,
'Cpu': cpu,
'Ram': pc_data[1],
'Gpu': gpu,
'OpSys': OpSys,
'SSD': pc_data[2],
'Price': price
}
writer.writerow(row)
except:
print(f'Error en página: {i}')
Básicamente, abrimos el archivo CSV donde guardaremos la información, seguidamente le indicamos al CSV qué campos queremos que tenga, y luego leemos y trabajamos con el HTML. Como ves, he tenido que hacer algunas funciones extras para poder extraer la información necesaria de cada campo que queremos guardar en el CSV.
¡Os dejo el script completo aquí por si queréis probarlo!
Top comments (0)