73

Extrayendo datos de la Secretaría de Hacienda con scraping en Node.js

1431Puntos

hace 9 días

Curso de Backend con Node.js
Curso de Backend con Node.js

Curso de Backend con Node.js

Crea aplicaciones backend utilizando Node.js, Express y Mongo. Entiende cómo funciona Javascript en un servidor y escribe aplicaciones con Node.js. Crea una API, manipula errores y valida tus datos con Express. Elabora pruebas para encontrar errores en tu código y finalmente pon tu aplicación en producción en un servicio web.

Node.js es un entorno en tiempo de ejecución multiplataforma y es una de las tecnologías líderes cuando hablamos de áreas como backend y desarrollo de aplicaciones de lado de servidor.

En el Curso de fundamentos de Node.js, se explican detalles y fundamentos básicos que nos permitirán iniciar de cero en esta increíble y potente tecnología.

Ahora, vayamos al grano. En este blog les explicaré paso a paso como extraer datos del Diario Oficial de la Federación.

El Diario Oficial de la Federación (DOF) es el periódico oficial del gobierno mexicano. Su función es la publicación de leyes, acuerdos, circulares, órdenes y todos los actos expedidos por los poderes de la Federación, con el fin de que sean observados y aplicados debidamente en sus respectivos ámbitos de competencia.

En este Diario, la Secretaría de Hacienda y en específico el Servicio de Administración Tributaria (SAT), publica de manera periódica la lista de **PRESUNTAS “**empresas fantasma” o “empresas de papel” a las que se les da un plazo de 15 días hábiles para presentar ante las oficinas de las autoridades un escrito libre en original y dos copias firmado por el contribuyente o su representante legal en el que manifiesten y anexen documentación e información que desvirtúen los hechos que llevaron a la autoridad a notificarlos.

Algunos de los motivos por los cuales se notifica, son emitir comprobantes fiscales sin contar con:

  • Los activos.
  • El personal.
  • La infraestructura o capacidad material para prestar los servicios o entregar los bienes que amparen tales comprobantes.

Para fines prácticos, utilizaremos la lista publicada el 27 de Enero del 2020:

https://www.dof.gob.mx/nota_detalle.php?codigo=5584830&fecha=27/01/2020

Entonces… comencemos.

Lo primero que hay que hacer:

  1. Abrir la línea de comandos, crear la carpeta que contendrá el proyecto e inicializar el proyecto con npm
> mkdir DOF-Scraper
> cd DOF-Scraper
> npm init -y
  1. Instalar el paquete table-scraper con npm
> npm install table-scraper
  1. Abrir el proyecto en tu editor de código favoritos y crear un archivo index.js. Importar los paquetes que utilizaremos:
// Table-scraper nos permitirá extraer la información.const scraper = require("table-scraper");
// Fs nos servirá para crear nuestros archivos de resultados.const fs = require("fs");

  1. Usamos la constante scraper y en específico el método get que recibe un parámetro en formato string (URL)
scrapper.get(
  "https://www.dof.gob.mx/nota_detalle.php?codigo=5584830&fecha=27/01/2020"
);

Como podrán ver, aún no podemos ver ningún resultado porque no estamos haciendo nada con la respuesta de la promesa que contiene el método get.

Captura_de_Pantalla_2021-02-12_a_la(s)_11.52.30.png
  1. Cambiaremos nuestro código para agregar un .then que nos permite manipular la respuesta.
scrapper
  .get(
    "https://www.dof.gob.mx/nota_detalle.php?codigo=5584830&fecha=27/01/2020"
  )
  .then((data) => {
    console.log(data);
    return data;
  });
Captura_de_Pantalla_2021-02-12_a_la(s)_11.55.46.png
  1. Como podrán ver, ahora ya estamos imprimiendo en consola los datos que nos devuelve la función pero al ser mucha la información, es muy difícil analizar la estructura. Es por eso que guardaremos todo este primer resultado en un archivo llamado RAW.json
scrapper
  .get(
    "https://www.dof.gob.mx/nota_detalle.php?codigo=5584830&fecha=27/01/2020"
  )
  .then((data) => {
    fs.writeFile("RAW.json", JSON.stringify(data), function (err, res) {
      if (err) {
        console.log(err);
      }
    });
    return data;
  });
Captura_de_Pantalla_2021-02-12_a_la(s)_11.58.22.png

Ahora, podemos ver toda la estructura del sitio que estamos extrayendo y ver que estamos obteniendo un Json. Analizando el archivo, podremos buscar por patrones y áreas específicas para extraer la información que necesitamos.

  1. Después de un no tan breve análisis, encontramos que en el arreglo 5, línea 7455 del archivo, encontramos los objetos relacionados a la tabla.
Captura_de_Pantalla_2021-02-12_a_la(s)_12.02.16.png
  1. Ahora que conocemos qué parte del archivo contiene la información que necesitamos, procederemos a codificar lo siguiente:
.then((data) => {
    //console.log(data);
    fs.writeFile("RAW.json", JSON.stringify(data), function (err, res) {
      if (err) {
        console.log(err);
      }
    });
    return data;
  })
  .then((data) => {
    let arrayOne = data[5];
    console.log(arrayOne);
  });
Captura_de_Pantalla_2021-02-12_a_la(s)_12.05.13.png

Nos daremos cuenta de que la tabla está partida en arreglos de objetos, por lo que procederemos a hacer la continuidad llamando el siguiente para validar:

.then((data) => {
    let arrayOne = data[6];
    console.log(arrayOne);
  });
Captura_de_Pantalla_2021-02-12_a_la(s)_12.06.37.png

Nos daremos cuenta de que el arreglo 6 no tiene ningún valor definido y por lo tanto, nos devuelve undefined al momento de imprimirlo.

Una vez que seguimos con el siguiente arreglo, nos damos cuenta de que podremos continuar del arreglo 7 al 20 para así obtener la lista completa incluida en la tabla. Utilizaremos el método .concat() para ir concatenando los arreglos:

let concat = arrayOne
      .concat(data[7])
      .concat(data[8])
      .concat(data[9])
      .concat(data[10])
      .concat(data[11])
      .concat(data[12])
      .concat(data[13])
      .concat(data[14])
      .concat(data[15])
      .concat(data[16])
      .concat(data[17])
      .concat(data[18])
      .concat(data[19])
      .concat(data[20]);

console.log(concat)
Captura_de_Pantalla_2021-02-12_a_la(s)_12.10.24.png

Una vez verificamos que efectivamente ya tenemos un json limpio, procederemos a guardarlo en un archivo llamado CLEAN.json:

.then((data) => {
    let arrayOne = data[5];

    let concat = arrayOne
      .concat(data[7])
      .concat(data[8])
      .concat(data[9])
      .concat(data[10])
      .concat(data[11])
      .concat(data[12])
      .concat(data[13])
      .concat(data[14])
      .concat(data[15])
      .concat(data[16])
      .concat(data[17])
      .concat(data[18])
      .concat(data[19])
      .concat(data[20])
      .concat(data[21]);
    console.log(concat);

    fs.writeFile(
      "CLEAN.json",
      JSON.stringify(concat),
      function (err, res) {
        if (err) {
          console.log(err);
        }
      }
    );

    return concat;
  });

Y nuestro archivo se verá así:

Captura_de_Pantalla_2021-02-12_a_la(s)_12.12.36.png

Y ahora tendremos un archivo json almacenado para consumir o almacenar en alguna base de datos como MongoDB y poder generar un script que periódicamente haga la recolección.

Conclusión:

Scrapear es más fácil de lo que parece. En solo 50 líneas de código, obtuvimos información específica de un archivo de más de 5000 líneas. Aprende a hacerlo en la página que quieras con Platzi 💚.

Si quieres seguirme en Github: Rafael Lagunas

Curso de Backend con Node.js
Curso de Backend con Node.js

Curso de Backend con Node.js

Crea aplicaciones backend utilizando Node.js, Express y Mongo. Entiende cómo funciona Javascript en un servidor y escribe aplicaciones con Node.js. Crea una API, manipula errores y valida tus datos con Express. Elabora pruebas para encontrar errores en tu código y finalmente pon tu aplicación en producción en un servicio web.
Rafael
Rafael
rafalagunas

1431Puntos

hace 9 días

Todas sus entradas
Escribe tu comentario
+ 2
Ordenar por:
3
17219Puntos

Excelente, @rafalagunas, me gustaría hacer la prueba

2
17219Puntos
9 días

Gracias coach por el aporte en verdad

2
6111Puntos

Wow, está genial. Hasta hoy pensaba que sólo se podía hacer con pyhton y que era algo “difícil”. Salgo corriendo a probrarlo.

0
1431Puntos
7 días

¡Qué bueno que te gustó! Para nada, muchas cosas son más fácil de lo que parecen, solo es cuestión de práctica!

2
8173Puntos

Yo hice un scraper con puppeteer que me trae el texto de los comentarios de cualquier blogpost de Platzi. Lo que no sé es como traer los usuarios, me encantó este post.

2
17131Puntos

Muchas gracias @rafalagunas por este ejemplo y explicación, está todo bien claro, y que facil que resulta.

0
1431Puntos
9 días

Gracias por tu comentario Migue! Node.js es muy poderoso. Saludos

2
71820Puntos

Estimado Rafael que buen aporte, funciona al 100.

0
1431Puntos
9 días

Muchas gracias por tu comentario, saludos!

2

Que buen ejemplo y explicación. Desconocía que se podía hacer scrapping con node.js!!
A poner manos a la obra!!

2
9191Puntos

Genial otro motivo más para aprender Node.js, cuando leo scrapping pienso en Python ahora tengo más ganas de aprender node