Scraping

Últimamente veo muchos artículos sobre bots que se hace la gente para conseguir datos de la web, y muchos de ellos tienen dudas o preguntas que suelen presentarse a la hora de hacer scraping…

¿Qué herramientas son mejores? ¿Porqué estas urls no me funcionan? ¿Porqué me va tan lento? ¿Cómo automatizar el sistema de extracción? ¿Dónde lo pongo todo?…

Las dudas son muchas porque es un ámbito complejo, pero ya que me dedico profesionalmente a ello desde hace tiempo, voy a intentar aportar mi granito de arena al foro con mi humilde experiencia. Intentaré empezar desde lo más básico por si alguien se apunta al carro. Comenzamos.

1. Qué es el scrapping.

Scrapear una web significa extraer la información de esa web, la información que presenta por pantalla.

Es legal ya que se asume que se están cogiendo datos que cualquier usuario vería siempre que tuviera acceso a lo que se está scrapeando, puede ser ilegal si se ddosea o tumba sin querer la web de la que se quiere extraer información o se realiza extracción de datos que no son visibles para el usuario.

Ejemplo: tu puedes scrapear una web pública pero también podrías scrapear tu web de la seguridad social con tus datos médicos porque tu tienes tu contraseña. Si otra persona scrapeara tus datos médicos sin tu permiso sería un delito, pero no por el hecho de scrapearlos, sino por tener acceso a los mismos habiendo violado diferentes protocolos de seguridad.

2. Cuales son las mejores herramientas para hacer scraping.

El lenguaje maestro para el scraping es Python ya que es el que está más orientado hacia el datascience o data engineering. Se puede scrapear con cualquier lenguaje «moderno» pero con Python es bastante más sencillo. Otra herramienta indispensable para el buen ejercicio es el navegador web y su inspector.

3. Qué se necesita saber para hacer scraping.

Depende de la página web de la que quieras extraer datos. En general se requieren conocimientos de programación y scripting, de aplicaciones web y su data-flow (te tienen que sonar cosas como session, cookies, headers, params, jsons, xml, html, xsd, get, post… y sobre todo blacklisted jeje), ingeniería inversa, algo de criptografía y seguridad para las webs más complejas, javascript y mucha paciencia e inventiva. Una web sencilla requiere poco más que hacer peticiones get e iterar sobre una sucesión de divs, pero una web compleja puede requerir que bypasees un saml o que ejecutes su javascript de encriptación, mientras luego te pide que valides un captcha, aceptes en un 2FA o valides un sms/mail.

4. Que librerías son las mejores.

Si has elegido Python sin duda necesitarás requests, beautifulsoup y selenium o pyppeteer.

5. Como es el proceso de scraping.

El proceso de scraping se divide claramente en dos partes:

  1. La primera parte donde debes averiguar que peticiones hace al servidor y en que endpoint, en que formato está el dato que quieres (json, html, xml) y que posición ocupa en esta sucesión de datos.
  2. Qué cookies o variables de sesión necesitas para que el servidor responda de forma correcta a tu petición y te de lo que quieres. Esta es la parte complicada. El servidor requiere de una serie de parámetros para responder a tus preguntas, pero también valida que tu sesión tenga una serie de valores, esto lo puede validar en el header o en las cookies. A veces algunas peticiones requieren de un login, o de que previamente un servlet te haya autorizado en una request anterior. Aquí es donde la experiencia en backend/security se nota más.

Ejemplo práctico:

Vamos a hacer una aplicación sencilla paso a paso cuya funcionalidad será darnos la nota media de filmaffinity dado el nombre de una película. Esto lo hará casi inmediatamente ya que solo usaremos requests y beautifulsoup.

NOTA: No es objeto de este minitutorial de iniciación centrarse en las buenas prácticas de programación/scripting, por eso vamos a hacer las cosas deprisa sin entrar en el control de errores Más adelante si sigue esta iniciativa, nos meteremos en el tema, que es profundo (desde los None del soup hasta los >=400 codes, 500, toomanyredirects, toomanyrequests, remotedisconnect, lambdas… etc)

PASO 1: PLANTEAR LA LÓGICA

Lo primero que tenemos que hacer es tener claro cual va a ser el flujo del programa:

Primero, el usuario introducirá un nombre de película.
Segundo, analizando el funcionamiento de la web sabemos que para ir al detalle de la película con todas las cookies de session del sitio, primero hay que pasar por la main page, luego introducir la película a buscar, luego seleccionar de la lista la que más se parece y finalmente dentro del detalle de la película coger el dato de la nota media.

nota: no sabemos si las cookies del sitio/session son necesarias, pero a priori siempre vamos a dar por hecho que sí, esto luego lo podemos optimizar

Entonces en el paso segundo, el más complejo, nuestra aplicación necesitará hacer tres requests:

  • 1era request a la página principal, para coger las variables de session si hubiera y cookies necesarias (probablemente prescindible)
  • 2nda request, cuando el usuario introduce la película en el buscador y hace click en buscar
  • 3era request, cuando la página ha dado una lista de objetos que coinciden con la búsqueda, nosotros seleccionaremos uno y entraremos a ver su detalle.

PASO 2: ANÁLISIS DE LAS REQUESTS

Para esto necesitaremos el inspector del navegador. En mi experiencia chrome y firefox van bien, pero a veces chrome pierde algunas responses por el camino del server, cosa que dificulta mucho el proceso.

Para utilizar el inspector haz click en F12 y para ver las requests que está haciendo el navegador, dentro del inspector ves a la pestaña RED. Ahí verás uan tabla con las urls donde hace las peticiones, su respuesta, los tiempos y demás parámetros.

En este punto deberías saber algo de códigos http, por ejemplo sabiendo que un 302 es redirección o un 403 es que no se te permite (posible login necesario). Los códigos 500 suelen ser errores ajenos a nuestra aplicación y que tienen que ver con la imposibilidad del servidor de atender a nuestra peticiones (un pod que acaba de morir, un exceso de requests… depende).

En este punto, haciendo click derecho sobre la requests podemos copiar el comando CURL que está haciendo el navegador, es decir, saber exactamente que le está mandando al server, con sus headers y sus cookies. En función del lenguaje de programación que uses, podrás traducir este CURL a Java, Python, Node o lo que necesites para montarte tu propia request.

Debemos ser observadores y manejar bien el inspector para saber cuales son las tres requests EXACTAS que necesitamos y que parámetros se están mandando. Mirando bien el inspector también se intuye (sin tener que hacer uso de herramientas curl to python/node/java) que en nuestro caso de ejemplo, gladiator, se pasa como param en el get para la request.

PASO 3: RECONOCER LOS TAGS HTML QUE NECESITAMOS

Para esto también necesitaremos el inspector. Necesitamos saber donde está el tag que queremos, y como diferenciarlo de manera clara. Primero necesitaremos saber la URL del primer resultado para ir luego al detalle, así que con el inspector miraremos si tiene algún id, clase o tag html por el que podamos cogerlo de manera sencilla. Como solo queremos el primero y b4soup con find devuelve el primero, usaremos un find sobre ese div, luego sobre ese div buscaremos un enlace, y luego del enlace nos quedaremos el href.

A la izquierda dondde pone Inspector, hay una flechita dentro de un cuadrado, si clicas en ella puedes marcar en el html el elemento que quieras y te indicara cual es su posición, nombre y detalle en el documento:

En nuestro caso vemos que del div mc-tittle cuelga un a donde se encuentra el href que necesitamos, y así lo ahremos con b4soup.

Luego dentro del detalle de la película buscaremos cual es el tag que alberga la nota media del mismo modo:

En este caso es un div con id claro, aún más fácil de coger.
Con todo esto ya tenemos lo necesario para montar nuestro sencillo e inmediato programa.

PASO 4: CREACIÓN DEL SCRAPER

Después de aplicar los procesos del think twice code once, nos ponemos a codificar el bot de manera sencilla.

Os voy a poner un snippet del code en algún sitio para que lo podáis probar, con sus debidos comentarios. En cualquier caso podemos seguir scrapeando cosas más complicadas, ver como guardamos los datos, dockerizar, montar unos pods en algún sitio, y ver como automatizar todo esto con un gestor de colas, etc. Ahora la pelota está en vuestro tejado, todos estáis invitados a participar y también a dejar vuestras dudas!

Aquí el código

Algunas capturas para curiosos: