Web crawlers 101

Neste post mostrarei algumas ferramentas interessantes para desenvolver web crawlers.

Pré-requisitos:
– Conhecimento básico em python
– Conhecimento básico em HTML
– Conhecimento básico em HTTP

Para quem não sabe, um web crawler é basicamente um software que visita várias páginas web em busca de algum tipo de informação.

Por exemplo, suponha que você queira encontrar um emprego como freelancer, digamos, para desenvolver crawlers. Talvez você já tenha outros projetos, e não queria ficar passeando entre os sites com as vagas todos os dias. Não seria legal automatizar esse processo e ainda torná-lo divertido? E ainda teria uma boa experiência para citar em sua entrevista! 😉

Iremos fazer aqui um crawler simples para o 99freelas, e pegaremos todas as vagas que tenham algumas palavras chaves que definiremos. Sim, eu sei que existe um filtro de pesquisas para isso, mas lembre-se que este post tem apenas fins didáticos.

Vamos começar?

Para começar, é importante ter alguma ferramenta para inspecionar o código que iremos buscar. Particularmente, eu gosto de usar as DevTools do Chrome, que você pode entender muito melhor aqui, mas sinta-se à vontade para utilizar as ferramentas de desenvolvimento web de sua preferência.

Usando o DevTools do Chrome, vá para a página do 99freelas e pressione F12 no teclado. Essa nova janela que apareceu mostram as DevTools de que falei. Antes de prosseguir, tente entender um pouco de como funciona essa ferramenta!

Mas e que horas que começaremos a extrair os dados?

Calma! Antes vamos instalar as dependências! Aconselho a usar um ambiente virtual do python:

$ pip install requests beautifulsoup4  

Agora sim podemos começar nosso script para buscar os dados do site:

import requests
from bs4 import BeautifulSoup as bs

URL = 'https://www.99freelas.com.br/projects'

# Parâmetros da query string da URL, utilizados como filtro
params = {
    'categoria': 'web-e-desenvolvimento',
}

# Fazendo a requisição
resposta = requests.get(URL, params)

Antes de prosseguir, vamos brincar um pouco com a resposta do sistema.

resposta.status_code
resposta.content
resposta.text

O primeiro irá mostrar o status HTTP de resposta da requisiçao. O resposta.content e o resposta.text ambos retornam a informação buscada no site, mas a primeira dá o resultado em bytes e o segundo em unicode.

Utilizaremos o BeautifulSoup para explorar o HTML da página. Que é bem mais fácil que fazer um parser de texto puro para o resposta.content.

Vamos buscar a primeira entrada da tabela no site 99freelas. Pressionando Ctrl+Shift+C e clicando na primeira entrada da tabela, o inspetor de elementos provavelmente irá aparecer na tela. No HTML vamos buscar pela div <div class="projects-result">, e dentro desse tag, buscar cada elemento da lista:

import requests
from bs4 import BeautifulSoup as bs

URL = 'https://www.99freelas.com.br/projects'

# Filtros da busca no site, que são a query string da URL
params = {
    # Na URL isso estará como ?categoria=web-e-desenvolvimento
    'categoria': 'web-e-desenvolvimento',
}

# Fazendo a requisição para a URL completa:
# https://www.99freelas.com.br/projects?categoria=web-e-desenvolvimento
resposta = requests.get(URL, params)

# Porque com o BeautifulSoup fica mais fácil analisar a página
site = bs(resposta.content, 'html.parser')

# Extraímos a tabela com o BeautifulSoup
tabela = site.find(attrs={'class': 'projects-result'})

# E agora extraímos todos os elementos da lista na tabela
vagas = tabela.find_all('li')

Cada elemento o BeautifulSoup é explorável. Aconselho a bincar um pouco com os
elementos do BeautifulSoup antes de prosseguirmos…

Vamos selecionar todos os clientes com quatro estrelas ou mais que tenham a palavra “crawler” na descrição.

# ... Continuando...
vagas = tabela.find_all('li')

# Quais termos serão buscados?
termos = ['crawler', 'spider']
vagas_interessantes = []

# E varremos todas as vagas para encontrar os termos selecionados
for vaga in vagas:
    # Busca pela classe description (repare na conversão para texto!)
    descricao = vaga.find(attrs={'class': 'description'}).text
    avaliacao = float(vaga.find(attrs={'class': 'avaliacoes-star'})['data-score'])
    link_vaga = vaga.find(attrs={'class': 'title'}).find('a')['href']

    if any(termo for termo in termos if termo in descricao) and avaliacao > 4:
        vagas_interessantes.append({
            'link_vaga': link_vaga,
            'descricao': descricao
        })

Todas as vagas interessantes estarão (com seus links) na lista vagas_interessantes. Podemos agora paginar a busca, criar algum tipo de notificação quando houver uma vaga interessante, dentre outras inúmeras possibilidades. Divirta-se!