Desenvolvimento

6 nov, 2017

Web Scraping com Node.js e Cheerio

Publicidade

Um dos meus hobbies favoritos é participar de Meetups e eventos de tecnologia. Apesar de cada um ter a suas particularidades, fiquei surpreso com o fato de que quase todos enfrentam um mesmo problema em comum (quando há brindes para sortear): “como faremos o sorteio?”.

Para resolver este problema, pensei em desenvolver uma simples aplicação que fizesse este sorteio de forma automática através da plataforma do Meetup. A ideia era bem simples: dado a url (ou identificador) do evento, o sistema olharia quem eram os participantes e escolheria um deles de forma aleatória. Bem simples e objetivo.

A primeira ideia era usar a API REST da plataforma para fazer isso. Apesar de ser possível, algo me incomodou: era necessário ser o dono do Meetup para poder obter essa informação via API. Como o objetivo era tornar o sistema o mais acessível possível, descartei a possibilidade. Então pensei em uma outra abordagem: obter essa informação da própria página do Meetup usando a técnica de Web Scraping. Para quem não conhece o conceito, em resumo esse é o nome dado a técnica de extrair informações de uma página web.

Para desenvolver isso com o Node como backend (opção apenas por preferência pessoal), comecei a me aventurar com a biblioteca cheerio. Esse pacote é uma abstração do core do jQuery focada em rapidez e flexibilidade para ser usada no backend.

Para mostrar como isso foi feito, vou mostrar alguns trechos do código do programa final. Você pode baixá-lo em casa e modificá-lo à vontade, basta acessar este link do repositório no GitHub.

O primeiro passo para utilizar a biblioteca é trazê-la ao projeto. Para isso basta executar:

npm install --save cheerio

Feito isso, temos que importar o módulo.

var cheerio = require('cheerio');

Com o módulo importado, já conseguimos utilizá-lo. Para que a biblioteca consiga extrair dados da página, precisamos dar a ele o respectivo HTML. Na aplicação do sorteador, a url da página de participantes do Meetup é enviada para um endpoint no backend.

Screenshot da aplicação

Ao chegar lá, o pacote request faz uma requisição para a página enviada e então o HTML da página é retornado. Com o HTML em mãos, conseguimos carregá-lo no cheerio com a função load:

const $ = cheerio.load(html);

Depois disso, já conseguimos navegar pelo nós da página como já estamos acostumados com o jQuery. No caso do Meetup, a lista de participantes fica na tag ul com a classe css “attendees-list” e cada item possui a classe css ”attendee-item”. Sabendo disso, não foi difícil obter os dados dos participantes:

$('ul.attendees-list li.attendee-item').each((i, element) => {
      const cheerioElement = $(element);
      const avatar = cheerioElement.find('.avatar');
      const avatarPathRaw = avatar.attr('style');
      const avatarImage = avatarPathRaw.substring(avatarPathRaw.indexOf('(') + 1, avatarPathRaw.indexOf(')'));
      const avatarName = avatar.text();
      
      participantes.push({'nome': avatarName, 'avatar': avatarImage});
    });

Com os participantes em mãos, bastou usar o Math.random() para fazer o resto do trabalho. Bem legal, né? O resultado final é simples, mas cumpre o objetivo.

Screenshot da aplicação: sorteio realizado!

Conclusão

Há inúmeras maneiras de se resolver este mesmo problema, mas o cheerio se mostrou uma ótima opção. Além de ser extremamente familiar, ele é uma opção muito leve, já que elimina toda a parte do core jQuery desnecessária. Além disso, ele é muito rápido. Existem benchmarks que dizem que ele até 8x mais rápido que o JSDOM, por exemplo. E por fim, como ele é construído com o html2parser, também é bastante flexível.