Cómo construir un bot de búsqueda simple en 30 minutos

La búsqueda de apartamentos apesta, especialmente en Montreal. Esta guía le mostrará cómo construir un bot que se mantenga al tanto de la búsqueda por usted. De esta manera, nunca más tendrá que actualizar sus búsquedas sin cesar.

Contexto

A diferencia de otras ciudades, la mayoría de las personas que alquilan apartamentos en Montreal tienen el mismo plazo de arrendamiento. Los nuevos contratos de arrendamiento comienzan en julio, duran 12 meses y finalizan el 30 de junio. Si bien se podría argumentar que esto simplifica muchas cosas, como la disponibilidad y las expectativas, también significa que la competencia es fuerte.

Todos los días me despertaba, actualizaba mis 10 páginas abiertas de Kijiji y enviaba correos electrónicos preguntando sobre todos los anuncios nuevos. Volvería a hacer esto en el almuerzo, la cena y antes de acostarme. Mi tasa de respuesta fue baja, muy por debajo del 10%. Cuando alguien respondía, su respuesta era generalmente sombría.

Mi siguiente paso fue subir la apuesta y levantar el teléfono. Llamar hizo que mis posibilidades fueran un poco mejores. Los propietarios fueron más receptivos, y esta vez generalmente había menos de 10 personas por delante de mí. Pero definitivamente todavía más de 5. De vuelta a la mesa de dibujo.

Un día, mientras me quejaba con un compañero de trabajo de que todo mi tiempo estaba siendo devorado por esta búsqueda de apartamentos, me di cuenta. Podría resolver este problema con mi computadora.

Cuando llegué a casa, escribí un pequeño programa que observa cómo Kijiji busca cambios. Cuando los ve, envía un mensaje de texto del Servicio de mensajes cortos (SMS) a mi teléfono con la información relevante. El resto de este artículo explicará cómo hice eso.

Nota: para aquellos a los que no les importa el tutorial, he puesto el raspador de Kijiji como un repositorio de código abierto aquí:?

Edificio Pad-Patrol

Cuando llegué a casa del trabajo, saqué mi computadora portátil y encendí mi terminal. Sabía que el programa debería ser liviano, ya que lo ejecutaré las 24 horas del día, los 7 días de la semana, o al menos hasta que encuentre un apartamento. Decidí simplemente crear un script de nodo simple que pudiera ejecutar desde mi terminal.

Preparar

Asumiendo que usted tiene nodey npmha instalado, el primer paso - de cualquier proyecto de nodo - es inicializar NPM dentro del directorio del proyecto.

A continuación, creemos un srcdirectorio donde vivirá nuestro código.

Dentro del srcdirectorio, crea un index.jsarchivo donde irá nuestro script.

Puedes hacerlo así:

$ npm init // this will ask a few questions$ mkdir src$ cd src && touch index.js

Escribiendo el guión

Cuando hago un proyecto en solitario, tiendo a hacer estilo libre: romper cosas y luego arreglarlas (posiblemente la mejor manera de aprender). Intentaré imitar mi proceso de pensamiento inicial con las siguientes instrucciones, pero avíseme si parecen estar por todos lados.

Lo primero que tenemos que hacer es enviar una solicitud a Kijiji. Para asegurarnos de que podemos obtener una respuesta adecuada, hagamos una búsqueda muy básica.

Para hacer eso, necesitaremos instalar una biblioteca de solicitudes:

$ npm install request-promise

y luego agregue lo siguiente a index.js:

Una vez que está guardado, podemos ejecutar $ node src/index.jsy deberíamos ver algunas marcas HTML en nuestra consola. Paso uno completo - ¡Fácil!

Debido a que solo nos importa cuando cambia el contenido, hagamos un simple hash de la respuesta. De esa forma, podemos comparar la respuesta y comparar los valores hash. En caso de que necesitemos registrar nuestros resultados, esto será mucho menos engorroso que el marcado sin formato.

Para hacer esto, podemos usar una herramienta hash llamada checksum:

$ yarn add checksum

y entonces:

Ok genial, esto funcionó! Nuestras 1500 líneas de HTML se han reducido a 32 dígitos. Ahora, envuémoslo en una función reutilizable:

El código anterior creará un hash a partir del valor obtenido. Luego, en la siguiente búsqueda, comparará los hash originales y nuevos.

Si son diferentes, volverá true. Esto funcionó muy bien ... como, demasiado bien. Como verás, ¿vuelve truesiempre?

Después de una inspección más profunda de la respuesta de la búsqueda, podemos ver que Kijiji tiene una marca de tiempo en el encabezado. Esto significa que el hash será diferente en cada búsqueda. Es importante tener en cuenta que esto también habría sucedido debido a la rotación de anuncios y un montón de otro contenido dinámico.

La conclusión de la supervisión anterior es siempre inspeccionar cuidadosamente su respuesta cuando se trata de una API que no escribió.

Esto significa que necesitaremos acceder a partes granulares del marcado, así que instalemos un paquete de terceros para ayudar a analizar la respuesta. Cheerio es una biblioteca que puede ingerir marcado HTML y convertirlo en una API JavaScript accesible. Su propósito era ayudar a los jQuerydesarrolladores a no usar jQuery, pero las intenciones están sobrevaloradas.

Para nosotros, será un conjunto falso de herramientas de desarrollo de Chrome.

Como requisito previo para usar Cheerio de esta manera, necesitamos saber qué buscar en nuestro marcado. Así que abramos Chrome e inspeccionemos nuestra URL.

Si inspeccionamos los anuncios, podemos ver que todas las respuestas de búsqueda tienen las clases .search-itemy .regular-ad. ¡Perfecto!

Podemos seleccionar aquellos con Cheerio así:

Tal como habíamos planeado, esto escupe una serie de objetos perfectamente organizados. Según la documentación de Cheerio, todos los atributos de un elemento están anidados en una clave llamada attribs. Si volvemos a las herramientas para desarrolladores de Chrome, podemos ver que cada anuncio tiene un atributo de datos único llamado ID. Apuntemos a eso: reemplace el código dentro de su checkURLfunción con lo siguiente:

rp(siteToCheck).then(response => { const $ = co.load(HTMLresponse); let apartmentString = "";
 // use cheerio to parse HTML response and find all search results $(".search-item.regular-ad").each((i, element) => { console.log(element.attribs["data-ad-id"]); });});

Muy bien, estamos obteniendo una lista de números de identificación únicos. Estas identificaciones son la única información que nos importa en la página.

Así que volvamos a nuestro plan original de comparar hashes, excepto que solo aplicaremos hash a las ID únicas:

¡Perfecto! Funciona exactamente como se esperaba. Cuando alguien publica un anuncio nuevo (o quita un anuncio antiguo, una advertencia de ver el orden de las identificaciones) imprimimos trueen nuestra consola. Todo lo que queda por hacer es configurar nuestra herramienta de SMS.

Envío de SMS desde la Terminal

En realidad, esto es mucho más fácil de lo que parece. Para hacer esto, usaremos un software de terceros llamado Twilio. Hace mucho, pero una de sus características principales es enviar SMS. Como beneficio adicional, ¡también tiene una excelente API de JavaScript! Para terminar el tutorial, necesitará una de sus cuentas (una prueba gratuita será más que suficiente para jugar) y tal vez incluso conseguir un nuevo apartamento.

Ok, para empezar tenemos que ejecutar:

$ yarn add twilio

a partir de ahí, index.jsagreguemos Twilio y definamos una nueva función llamada SMS:

const twilio = require(twilio);
// you'll need to get your own credentials for this oneconst client = new Twilio("accountID", "authKey");
function SMS({ body, to, from }) { client.messages .create({ body, to, from }) .then(() => { console.log(`? Success! Message has been sent to ${to}`); }) .catch(err => { console.log(err); });} 

This simple function takes two phone numbers (to and from) and a message (body). Instead of console logging the result of our checkURL function, we can call SMS with whatever message we want:

There you have it! Every time our script sees a change between the site hashes, it will send a text message with the URL right to your phone ?.

Happy Hunting!

The actual script that I’ve built is a little more complicated than the above example — I’ve put it up as an open source repo on GitHub.

Eventually, I’d like to make some additions to it — the first of which will be making it more generic and not just a Kijiji scraper. It’s pretty basic, so it will be a great first-time project for new contributors.

Feel free to contribute in any way you see fit ?

Also, in case anyone was wondering, I just signed a lease last Sunday. The apartment I ended up renting was from the very first update pad-patrol sent me — it was destiny ✨

I’m currently working as a software developer at luxury fashion company in Montreal. I’ve been doing that for about a year, after finishing a web dev bootcamp last summer. I spend my free time learning hot new tech and, up until a few days ago, hunting for apartments.