Como fazer webscraping com Python e Beautiful Soup
Tutorial de webscraping com pyhton utilizando a biblioteca BeautifulSoup
Conheça nosso canal no YouTube, com cursos gratuitos de qualidade e vídeos semanais, para acessar o canal clique aqui!
O que é webscraping?
Webscraping é uma técnica de extração de dados, com ela podemos coletar dados de sites. Fazemos a ‘raspagem’ dos dados que são interessantes para nós.
Por exemplo: resgatar os últimos posts que foram escritos em vários blogs, assim sem precisarmos entrar nos sites alvo, podemos simplesmente iterar sobre eles e resgatar os dados, este seria um exemplo simples da aplicação da técnica.
Ei você leitor! Criei um novo blog para os meus conteúdos, pois o Medium mesmo sendo uma excelente plataforma, me limitava em alguns recursos, que acredito que podem atrapalhar seu aprendizado/leitura…
Você pode acessar cliquando aqui!
Obrigado pela atenção, e boa leitura! :)
O que é muito mais rápido do que entrar em blog por blog e verificar o conteúdo e copiar para alguma planinha.
Há muitas empresas que utilizam como forma de gerar recursos, um exemplo clássico é o site Buscapé, ele varre os sites que vendem os produtos pesquisados em busca dos menores preços.
Mais sobre o webscraping:
Depois da extração dos dados, podemos armazenar eles de diversas formas:
- Salvar em um banco de dados;
- Salvar em CSV;
- Salvar em XLS;
- Entre outros;
O processo em si é bem básico, definimos os dados que queremos, escolhemos os sites, montamos o script e recebemos os dados para análise, este é o ciclo de vida do webscraping.
Outro ponto legal é que se você souber um pouco de programação web vai se sentir muito confortável na exploração das tags, e na própria estrutura do HTML, isso já te deixa na frente.
Porque utilizar?
Bom, vamos imaginar um caso: precisamos dos comentários dos usuários de um produto X em 200 e-commerces diferentes para analisa-los e validar se o produto tem aceitação no mercado.
Por exemplo, nós poderíamos entrar nos 200 sites copiar todos os comentários e salvar de alguma forma, mas quantas horas gastaríamos nisso? E se a pesquisa precisa ser repetida toda semana? Se faltou algum dado na primeira pesquisa?
Nós teríamos que novamente nos submetermos a todo este processo manual, gastando horas para gerar algo super simples!
É aí que entra o webscraping, automatizamos todo o processo e só precisamos rodar o script até quando precisarmos, é muito mais vantajoso, e se feito de maneira correta se torna muito mais preciso também, a prova de erros humanos.
Antes de iniciarmos a prática
Vou utilizar o Jupyter Notebook para demonstrar todos os exemplos, instalando o Anaconda você já consegue todas as libs usadas neste tutorial e inclusive o Notebook, que é uma forma excelente para executarmos nossos testes.
Caso você opte por instalar as libs separadamente, faça isso com o pip, o resultado final será o mesmo, gosto da solução do Anaconda pois é prática e rápida, além de ser muito utilizada para tutoriais e compartilhamento de notebooks.
Fiz um artigo de como instalar o Jupyter em diversas plataformas, caso queira aproveitar: confira aqui!
Projeto no final
Outro aviso é para os que gostam de prática, no fim do artigo teremos um mini projeto que simula uma situação do dia a dia, explorando todos os conceitos aprendidos durante a leitura!
Repositório
Todo o conteúdo se encontra no Github caso queira analisar o código: ir para o repositório!
Hello World em webscraping
Quem está nesse mundo da programação sabe que precisamos fazer um Hello World o quanto antes, é parte da tradição!
Vamos colocar a mão na massa para adicionar um pouco de prática, assim já conseguiremos abordar tópicos mais avançados
Pronto!
Temos o primeiro resultado por webscraping, foi fácil não?
O retorno do método urlopen foi um HTML simples com diversos elementos que vemos todos os dias, o próximo passo seria extrair os dados que nós desejamos.
Outro ponto importante é que no passo acima utilizamos a lib urllopen, nativa do Python, porém em outros tutoriais você pode se deparar com a Requests, que é bem conhecida e a comunidade abraça bem ela, então porque utilizamos a urllib?
Requests ou urllib?
Bom, como vamos fazer requisições HTTP, no caso get, nas páginas que queremos extrair dados, precisamos de uma lib para isso, durante meus estudos sobre o tema estas duas apareceram de forma igual, então fui atrás para saber as vantagens e desvantagens de cada uma.
Basicamente o que encontrei é que Requests é uma lib externa, no caso estariamos criando uma dependência para o projeto, já um ponto forte é a simplicidade de escrever o código, escrevemos menos linhas para chegar ao mesmo resultado comparando com a urllib, além disso há alguns comentários que dizem que Requests tem um código mais limpo e moderno que a outra.
Já urllib é nativa do Python, o que quer dizer que provavelmente será mantida pela mesma equipe que trabalha na linguagem e até enquanto Python durar ou fizeram outra versão que resolva este problema, há alguns comentários pelo stackoverflow que falam sobre o desenvolvimento dela ser feito numa lógica de ‘resolver o problema’ ao invés de código limpo e performático.
Neste post pretendo seguir com a urllib, mas teremos um exemplo com a Requests para você poder escolher a que mais te agrada.
Agora que vimos como conseguir os dados de um site, está na hora de avançarmos ao próximo nível: usar uma biblioteca para poder manipular o HTML de uma forma mais fácil
BeautifulSoup
Com a BeautifulSoup tudo será mais fácil, esta biblioteca do Python serve para extrairmos dados de HTML e XML, de forma fácil e descomplicada podemos acessar os ‘nós’ da estrutura do HTML da página ou até mesmo classes e pegar as informações
Vamos utilizar ela num exemplo para que fique claro o quanto mais fácil será se locomover pelas tags HTML ao invés de texto puro, como nos retornos dos métodos anteriores
No próximo exemplo vou pegar o título da página
Já neste exemplo eu procuro por todas as tags h1 da página com o método find_all()
Introdução de HTML
Vou apresentar uma rápida introdução ao HTML, caso você já se sinta confortável para entender a estrutura ou já trabalhou com desenvolvimento web, pule para a próxima parte. :)
A seguir uma estrutura HTML simples:
Toda página HTML tem pelo menos 3 tags que vão definir o esqueleto principal:
- < html >: ela define que este é um documento HTML;
- < head >: dentro destas tags serão colocadas configurações da página como encode, adicionados outros arquivos externos como scripts, definido o título da página ( o que aparece na aba do browser ), entre outras que são como parâmetros para a página web;
- < body >: esta tag contém todos os elementos visíveis da página, textos, listas, parágrafos e etc;
Tudo que está entre sinais de < e > são tags, é por meio delas que estruturamos a página, a grande maioria precisa ser aberta e fechada, como no exemplo a seguir:
< p >Texto do parágrafo< /p >
Porém há algumas que não tem essa necessidade, mas não vem ao caso neste post, fogem do escopo.
Como observado antes no nosso primeiro exemplo de webscraping, requisitamos title que é a tag title
HTML é uma linguagem de marcação, não de programação, ela nos ajuda a estruturar as páginas, com elementos que podem representar blocos que dividem as páginas em partes (div), elementos de texto como título (h1), listas (ul), tabelas (table) e por aí vai, sempre seguindo esta lógica de cada tag conter um conteúdo diferente, lembrando que tudo que é visível fica dentro da tag body.
As tags tambem aceitam parâmetros, os mais utilizados são classes e ids:
- classe: o intuito de adicionar uma classe é que vários elementos possam aproveitar suas características
- id: quando colocamos um id num elemento, ele tende a ser único na página, nas boas práticas dois elementos diferentes não podem ter o mesmo id
Quando falo características me refiro a CSS ou manipulação do DOM com JS, não vou entrar nesse assunto também, mas é basicamente estilização dos elementos ou manipulação deles por meio destas duas linguagens.
Voltando para o webscraping, as classes e ids nos auxiliarão a acessar os elementos que queremos resgatar os dados.
Por exemplo: identificamos que um dado importante está em um parágrafo, se procurarmos por parágrafos podemos achar inúmeros elementos com essa tag, agora se o elemento alvo conter um id ele será apenas um, e isso facilitará muito nossa vida.
Creio que com isso, o básico do HTML está exemplificado e além disso conseguimos estabelecer ligações entre o webscraping e a estrutura HTML, como iremos navegar para resgatar os dados!
Vamos retornar para a BeautifulSoup
Métodos find() e find_all()
O método find_all procura por todo o documento por resultados da nossa pesquisa, e nos retornas toda as ocorrências encontradas.
Porém as vezes queremos encontrar apenas um elemento, o que nos dá duas possibilidades
- passar o argumento limit = 1, no find_all()
- utilizar o find()
Com o find() o primeiro elemento encontrado é retornado, assim caso buscassemos uma tabela e soubermos que apenas uma tabela existe em todo o HTML é desnecessário utilizar o find_all() que leria o documento todo, assim por questões até de performance optariamos pelo find()
Veremos agora os dois na prática:
O que aconteceu?
Usamos bs que é a instância de BeautifulSoup criada anteriormente para extrair dados da página.
Conseguimos pegar todos os h1’s presentes na home do site, vimos que 6 elementos foram encontrados.
E caso quisessemos apenas o primeiro?
find() ao resgate!
O primeiro h1 foi encontrado e o método ja nos retornou
Como explicado anteriormente, em vez de ler todo o HTML a bs4 apenas achou o elemento alvo e nos retornou.
Simples não?
Selecionando por class e id
Agora vamos mudar de URL, para termos mais exemplos e trabalharmos com estruturas diferentes.
O que será abordado neste tópico é a seleção de elementos por class e id, como vimos anteriormente no HTML estes dois atributos são amplamente utilizados e vão nos guiar até os elementos corretos
BeautifulSoup não poderia ficar para trás, criou formas de selecionarmos os elementos pelos dois.
Inspecionando elemento
Vale a pena ressaltar aqui também, caso você não tenha muita experiência com web, a funcionalidade de inspecionar elementos do HTML
Com ela é que vamos descobrir as classes e ids que queremos.
- No Chrome: podemos acessar clicando com o botão direito na página e selecionando ‘Inspecionar’
- No Firefox: podemos acessar clicando com o botão direito na página e selecionando ‘Inspecionar Elemento’
Nos demais brownsers a lógica é a mesma, não tem muito mistério.
Voltando ao exemplo
Vamos inspecionar o título principal do site da Wikipedia
Agora vamos ver a estrutura HTML
Temos uma div com uma classe chamada ‘central-textlogo__image’, é exatamente ela que vamos selecionar para extrair o texto do título, veja abaixo:
Conseguimos ter o retorno esperado, pela classe conseguimos filtrar melhor o que queremos extrair
Selecionando por id
Agora vamos ver com o parâmetro id, como devemos utilizar para selecionar o elemento alvo
Mais abaixo no HTML temos as seleções de linguagem, vamos selecionar a que se refere a língua francesa
O elemento com id ‘js-link-box-fr’ é o que precisamos selecionar
Mais preciso
Agora temos maneiras de selecionar dados de formas mais precisas, sem ter que navegador muito pelo HTML, com classes e ids nosso trabalho é facilitado
Seletores CSS
Outra maneira de selecionar dados são os seletores CSS, como vimos anteriormente no HTML as tags são aninhadas uma nas outras, assim sendo podemos nos guiar por esta estrutura para selecionar algum elemento, exemplos:
- p a: todas as tags a dentro de um parágrafo
- div p: todos os parágrafos dentro de divs
- div p span: todos os spans que estão dentro de um parágrafo que estes estão dentro de uma div
- table td: todos os tds que estão dentro de tables
Basicamente selecionamos de acordo com o aninhamento da estrutura, talvez se você conheça um pouco de web já se sinta mais confortável, mas caso não, é bem simples: olhe a árvore do HTML e verifique dentro de que elemento está o seu alvo, quanto mais preciso for, no caso de mais tags forem especificadas, mais refinado seu resultado virá
E uma pequena mudança: agora vamos utilizar o método select(), passando como argumento o seletor CSS desejado
Podemos também utilizar os seletores CSS para classes e ids, que são representados por:
- . : quando colocamos um . (ponto) na frente de algum texto, bs4 assim como CSS vai automaticamente procurar por classes deste nome
- # : e o mesmo caso acontece para ids, colocando # na frente de algum nome de id
Veja nos exemplos abaixo a aplicação:
Validação de erros
Agora que já vimos as maneiras mais comuns de selecionar dados, e posso dizer que para operações simples de webscraping isso já está de bom tamanho, mas precisamos falar de erros
Erros podem acontecer por vários motivos:
- Servidor
- Programação
- Mudança do site
Quando saímos da prática e o webscraping vira uma atividade do nosso trabalho, precisamos adicionar confiabilidade no código, e com isso tratar erros para que o código não simplesmente exploda quando alguém tentar rodar, mas sim, informe a pessoa sobre o que provavelmente aconteceu
Vamos ver agora a nível de requisição como é possível fazer uma validação simples, porém efetiva
Primeiramente devemos importar o submódulos que tratam estes erros, que são:
E então podemos fazer uma validação por classificação de erro, que fica assim:
Como exemplo forcei um erro de URL errada, porém caso o servidor retorne erros como 404 ou 503, caíriam no primeiro caso
Isso nos ajudará, não só nós mas também quem vai pegar o código depois, a ter um log que fará com que os problemas se identifiquem mais rapidamente
É de responsabilidade do desenvolvedor fazer um código consistente e que trate erros, então fora destes exemplos aqui, sempre opte por tratar os erros e enviar mensagens ao usuários do sistema, caso não possam aparecer na tela emita logs
Projeto
Agora para fixar os conceitos vamos nos aproximar de algo mais real, que será explorar os dados da lista dos 250 melhores filmes no IMDB, que é um site de review, críticas e notícias de filmes, séries e afins, nossos objetivos serão:
- Importar as libs necessárias;
- Validar a URL dos 250 filmes;
- Resgatar os dados título, direção e escritores, data do filme e nota;
- Transferir os dados para um dataset
- Salvar num arquivo CSV
Nós vamos iniciar do absoluto zero e comentar cada passo dado até o fim do procedimento, incialmente vamos importas as libs que serão utilizadas:
Importando libs:
Com a pandas vamos trabalhar no dataset, urllib nos auxiliará a fazer as requisições ao site, e a BeautifulSoup que fará a extração de forma fácil
Com as bibliotecas importadas, o próximo passo é definir a URL e o termo de pesquisa para que as consultas não sejam fixas, vamos deixar que o usuário do script escolha o termo a pesquisar
Validando URL:
Temos nossa URL definida, agora vamos fazer a validação da url com os submódulos de urllib
A URL é válida, e o servidor não apresentou erros, agora vamos para a etapa de selecionar os dados.
Primeiramente devemos analisar o HTML
Para selecionar cada filme:
Vamos selecionar todas as tr’s dentro dessa tbody com classe lister-list
Precisamos também instaciar o objeto da BeautifulSoup com a url escolhida
Resgatando os dados:
Primeiro vamos analisar o HTML para saber quais elementos devemos resgatar
Para o título:
Para o título vamos selecionar o a que esta dentro de um td com classe titleColumn e pegar o texto dela
Para os diretores e escritores:
Vamos aproveitar a estrutura dos títulos e selecionar o parâmetro title, que nos vai dar os diretores e escritores
Para o ano do filme:
Ainda no td com classe titleColumn, vamos selecionar o span que é o ano do filme
Para as ratings:
Vamos selecionar o td com a classe imdbRating e pegar o texto da tag strong dentro deste td
Agora que sabemos como selecionar todos os dados, vamos ao código
Criamos vários arrays, um para cada atributo que vamos coletar, para preenchermos eles com os dados, que mais tarde formarão o dataset
Agora vamos criar o dataframe com os dados que nós extraímos
Criando o dataset:
Vamos definir o nome das colunas, e testar o dataset com o método head()
Dataset criado e testado, vamos prosseguir para a etapa de salvar os dados em um arquivo CSV
Salvando em um arquivo:
Com o método to_csv() o pandas vai criar um arquivo .csv do dataset para nós
Ética
Bom, esse é um tópico interessante, e não se refere necessáriamente a lei, porém as boas maneiras que devemos praticar ao pegar dados de sites que não nos pertençam
Pense no contrário: alguem entrando em nossos sites fazendo varreduras, carregando servidores, o que você acharia disso?
Estando no outro lado vemos que as vezes isso pode ser incomodo, então preste atenção nestes tópicos:
- Caso o site disponibilize uma API, prefira usar ela ao scraping;
- Faça requisições de forma moderada, para que afetem de forma menor possível a infraestrurura do proprietário do site
- Só pegue os dados que você realmente precisa;
- Tente de alguma forma retornar algo que seja de valor para o site, como por exemplo: tráfego;
- Tenha em mente seus objetivos, para que fim o dado será usado e que seja diferente do objetivo do site, caso não você estaria apenas duplicando um dado, o que não é interessante para o detentor do conteúdo;
É o básico, como viver em sociedade, respeite o próximo, neste caso, o site dele.
Conclusão
Bom, vimos do básico a prática do webscraping, claro que no dia a dia veremos situações talvez mais desafiadores que nos levará a procurar num Stackoverflow ou docs das libs, porém a ideia é esta.
Precisamos de uma biblioteca para fazer as requisições, que neste caso escolhemos a urllib, e também uma para manipulação do HTML que é a BeautifulSoup, esta última está presente em 100% dos materais que busquei sobre o assunto.
E então com as bibliotecas solicitadas, nós precisamos ter conhecimento dos dados que queremos extrair, definir o site alvo e aí olhar sua estrutura HTML para podermos iniciar a raspagem.
Tendo as informações já em nossa mão talvez vamos precisar fazer algumas mínimas manipulações de string para termos exatamente o que precisamos.
Por fim, podemos utilizar os dados, salvar em um arquivo, montar um dataset, aí vai de acordo com o nosso objetivo.
Obrigado por lerem, e qualquer dúvida ou sugestão comentem! :)