coding

Usando Node.js e GitHub Action para encontrar uma casa no Funda.nl

Escrito em 12 de março de 2022 - 🕒 4 min. de leitura

Se você quer alugar ou comprar uma casa na Holanda, é melhor se preparar porque não é uma tarefa fácil, especialmente se você estiver procurando em Amsterdam.

Candidatar-se para alugar ou comprar uma casa é como uma entrevista de emprego ou como obter um visto para outro país. Você precisa fornecer seus contracheques, contrato de trabalho, recomendações de proprietários anteriores e muito mais.

Não só isso, mas muitas vezes você nem tem a chance de ir ver a casa, porque eles já têm tantos pedidos de pessoas querendo ir ver a casa que eles não precisam aceitar mais. Às vezes, dentro de 2 dias após a casa ser listada no Funda.nl, eles já não estão agendando visitas.

Se você pelo menos conseguir marcar uma visita, verá a casa com muitas outras pessoas e às vezes até fazer fila para isso.

Por causa disso, eu tive que abrir constantemente o Funda.nl e verificar novas casas, para que assim que uma nova casa estivesse disponível eu pudesse marcar uma visita.

funda scraper

Partiu automatizar!

O bom do Funda.nl é que eles possuem uma grande variedade de filtros para a busca, e esses filtros ficam salvos na URL. Nice!

Por exemplo, este link listará todas as casas publicadas desde 1 dia atrás, com 2 quartos, no mínimo 40m² e no máximo €2000 de aluguel.

Os resultados nesta página estão listados em um elemento HTML li com uma classe search-result, com isso dá para obter todos os elementos com o document.querySelectorAll('.search-result') e dentro de cada um dos desses elementos, posso obter o link para a casa com element.querySelectorAll('a').[0].href.

Agora com o puppeteer.js eu posso automatizar um processo de ir a essa URL e verificar se alguma casa nova apareceu e salvá-la em um arquivo. Como este é um script Node.js, usarei o jsdom para trabalhar com os elementos DOM.

const { writeFileSync } = require('fs');
const puppeteer = require('puppeteer');
const jsdom = require('jsdom');

const runTask = async () => {
  const url = 'https://www.funda.nl/en/huur/amsterdam/beschikbaar/0-2000/40+woonopp/2+slaapkamers/1-dag/';
  const browser = await puppeteer.launch({
    headless: true,
  });

  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'domcontentloaded' });

  const htmlString = await page.content();
  const dom = new jsdom.JSDOM(htmlString);
  const result = dom.window.document.querySelectorAll('.search-result');

  const urls = [];
  for (const element of result) {
    urls.push(element?.querySelectorAll('a')?.[0]?.href);
  }

  writeFileSync('urls.json', JSON.stringify(urls));
}

runTask();

Agora eu posso simplesmente executar node script.js e terei todas as URLs em um arquivo urls.json.

Enviando novas URLs para o Telegram

Em vez de salvar as URLs em um arquivo urls.json, quero que essas URLs sejam enviadas para um grupo do Telegram usando um bot, para isso precisarei usar o node-fetch.

const nodeFetch = require('node-fetch');

const runTask = async () => {
  for (const element of result) {
    nodeFetch(`https://api.telegram.org/bot${BOT_API}/sendMessage`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        text: element?.querySelectorAll('a')?.[0]?.href,
        chat_id : CHAT_ID,
        parse_mode : 'markdown',
      }),
    });
  }
}

runTask();

Isso é ótimo, mas não é muito útil porque não quero ter que executar o script manualmente, então partiu corrigir isso.

Usando o GitHub Actions

GitHub Actions é ótimo, eu uso o tempo todo para tarefas como testes e builds do meu blog, mas também pode ter scripts rodando periódicamente usando cron.

Para este script, preciso usar actions/checkout para fazer o checkout do meu código e stefanzweifel/git-auto-commit-action para persistir uma lista das URLs que já foram enviadas ao Telegram.

name: Run Task
on:
  workflow_dispatch:
  schedule:
    - cron: "*/30 * * * *"

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/[email protected]
        with:
          ref: ${{ github.head_ref }}

      - name: Running
        run: |
          npm cache clean --force
          npm install
          npm run task
        env:
          CHAT_ID: ${{ secrets.CHAT_ID }}
          BOT_API: ${{ secrets.BOT_API }}

      - uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: Update db.json
          branch: main

E é isso! Agora, sempre que uma nova casa estiver listada na minha URL, receberei uma mensagem no Telegram 🎉.

Bonus

Agora corre pra marcar uma visita na casa!
Agora corre pra marcar uma visita na casa!

Existe uma extensão para Chrome de código aberto muito boa que adiciona muitos dados novos ao Funda.nl sobre a casa, então copiei algumas partes do código desse projeto para adicione informações extras às casas enviadas para o Telegram.

Você pode clonar este projeto no GitHub, adicionar sua própria lista de URLs do Funda.nl e o script será executado automaticamente a cada 30 minutos para verificar novas casas e enviá-las para o Telegram.

Até a próxima, pessoal!

Tags:


Publicar um comentário

Comentários

Nenhum comentário.