em Tecnologia

O pessoal no escritório está se divertindo muito com o Cartola FC. Graças a Liga que criamos por lá, todos estamos envolvidos em escalar nossos times e para isso eu gosto de ver as probabilidades de resultado dos jogos. Descobri a pouco que o Bing faz uma previsão quando você busca por dois times que irão se enfrentar. Então resolvi automatizar essa busca para me divertir e experimentar o BeautifulSoup4  (BS) para fazer crawler.

A ideia de um crawler é pegar um HTML de um site e procurar informações dentro dele. O BeautfulSoup4 é quem faz o parse deste HTML e nos permite executar métodos que fazem essa busca por informações no mesmo.

Comecei fazendo um app de um arquivo só com o Flask apenas para executar os crawlers facilmente e exibir as informações e dentro dele criei dois métodos que executam crawlers. O primeiro atualiza a tabela de jogos com os resultados (e na primeira execução popula o banco com os jogos) e o segundo executa a busca no Bing e me retorna a previsão de resultado de cada jogo.

Então o primeiro passo é buscar esse HTML no site onde você tem a informação. No caso das informações dos jogos eu fui buscar no site tabeladobrasileirao.net.

Começo utilizando o requests do Python para retornar o HTML dos jogos e seus resultados (no caso dos que já aconteceram).

import requests
r = requests.get('http://www.tabeladobrasileirao.net/')

Depois é a vez do BeautifulSoup4 entrar em ação. Passo o resultado para o BS (com o encode) e ele “parseia” o HTML.

from bs4 import BeautifulSoup
soup = BeautifulSoup(r.text.encode('utf-8'), 'html.parser')

E aí começo a procurar. Depois de analisar o HTML do site, descubro onde as informações estão e uso o método find do BS para pegar as informações.

table = soup.find('table', id="jogos")
for row in table.findAll("tr")[1:]:
    cells = row.findAll("td")
    if len(cells) == 12:
        game = {}
        game['round'] = int(cells[0].find(text=True))

        date_string = cells[1].find(text=True)
        date_string = '{}/{}'.format(date_string, '2016')
        game['date'] = datetime.datetime.strptime(date_string, "%d/%m/%Y").date()

        game['home_team'] = cells[4].find(text=True)

        home_team_result = cells[5].find(text=True)
        if home_team_result:
            game['home_team_result'] = int(cells[5].find(text=True))
        else:
            game['home_team_result'] = None

        away_team_result = cells[7].find(text=True)
        if away_team_result:
            game['away_team_result'] = int(cells[7].find(text=True))
        else:
            game['away_team_result'] = None
            
        game['away_team'] = cells[8].find(text=True)

Neste código estou buscando a tabela com id igual a “jogos” e iterando sobre suas células, a partir das linhas da tabela. Como já identifiquei onde estão os dados, comecei a guardá-los em um dicionário (tratando datas, tipos e resultados nulos) que usarei para salvar no banco de dados posteriormente. Por exemplo, cada jogo está em uma linha e a data dele está na segunda coluna, então uso cells[1].find(text=true) para pegar somente o texto da célula.

Omiti a parte de salvar no banco de dados, mas o código todo está disponível no meu Github.

Com todos os jogos salvos é a vez de procurar pela previsão de resultados no Bing.

Mais uma vez começo com o requests e dou um parse no resultado com o BS. Leve em consideração que a variável “game” no código abaixo retorna a string com o jogo em questão, por exemplo, “Internacional x Grêmio” ou “Corinthians x Flamengo”.

r = requests.get(u'http://www.bing.com/search?q={}'.format(game))

soup = BeautifulSoup(r.text.encode('utf-8'), 'html.parser')
div = soup.find('div',{'id':'tab_4'}).findNext('span',{'class':'b_demoteText'}).find_next_sibling(text=True)

predicts_string = div

Nesse caso foi muito mais difícil achar o local exato no código fonte do resultado da busca do Bing do que foi no caso do tabeladobrasileirao.net. Mas com um pouco de pesquisa e muita tentativa e erro eu acabei chegando no texto de previsão do Bing usando soup.find(‘div’,{‘id’:’tab_4′}).findNext(‘span’,{‘class’:’b_demoteText’}).find_next_sibling(text=True), mais uma vez com text=true para retornar somente o texto do objeto que vem no formato “Chapecoense 14% – Empate 29% – Corinthians 57%”, por exemplo.

Com os templates do Flask eu criei um pequeno site que executa e exibe o resultado desses crawlers. Ficou assim:

brasileirao-2016

Essa foi minha primeira experiência com BeautifulSoup4 e crawlers. Qualquer dúvida ou sugestão, deixe um comentário abaixo. E para ver o código fonte desse pequeno app acesse meu Github.