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.

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.

javascript
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.

javascript
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.

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

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

    steps:
      - name: Checkout
        uses: actions/checkout@v2.4.0
        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!

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!