DEV Community

Cover image for Raspagem de dados de um site de notícias em pt-BR
msc2020
msc2020

Posted on • Originally published at dev.to

Raspagem de dados de um site de notícias em pt-BR

Neste post realizamos a raspagem de dados (web scraping) de um site de notícias em português do Brasil (pt-BR). Utilizando a biblioteca Requests do Python 3, coletamos o conteúdo HTML do site. Em seguida, extraímos as notícias mais lidas e seus respectivos links com o BeautifulSoup. Introduzimos alguns aspectos legais do scraping e apresentamos casos de uso que estão atualmente rodando na Internet.

Sumário ☕


📻 Sugestão de disco para acompanhar o tutorial:


Pré-requisitos ^

Para rodar os códigos apresentados, é necessário instalar as seguintes bibliotecas do Python 3:

  • Beautiful Soup (pip install beautifulsoup4)

  • Requests (pip install requests)


Coleta do conteúdo do HTML ^

O primeiro passo para extrair as notícias mais lidas é obter o HTML do site de interesse. Para isso usamos a biblioteca Requests. Com ela é possível executar requisições HTTP como GET, POST, PUT e DELETE.

Homepage site UOL

Homepage do site www.uol.com.br

A página escolhida para realizarmos a raspagem é a tela inicial do site de notícias UOL (https://www.uol.com.br). O código abaixo realiza a coleta do conteúdo HTML deste site:

import requests
url = ('https://www.uol.com.br')
content_html = requests.get(url).text

# descomente a linha abaixo para ver o conteúdo do HTML
# print(content_html)
Enter fullscreen mode Exit fullscreen mode

html homepage

Imagem do HTML coletado com a biblioteca Requests.

Após coletar o HTML, usamos o BeautifulSoup para extrair os dados de interesse. Essa biblioteca disponibiliza funções para a navegação e extração de elementos das tags HTML.

Para transformar o conteúdo de texto HTML coletado (content_html) em um objeto BeautifulSoup, é necessário realizar o parsing desse texto, convertendo ele numa estrutura de dados navegável.

from bs4 import BeautifulSoup

soup = BeautifulSoup(content_html, 'html.parser')
Enter fullscreen mode Exit fullscreen mode

Após realizar o parsing do conteúdo HTML (content_html), temos um objeto que organiza as tags, e todo conteúdo do HTML, em forma de árvore. As relações das tags (pais, filhos, etc,) é mantida, o que facilita a navegação nos elementos HTML. No código acima, esse objeto é chamado de soup.

Exemplo

Como teste inicial, vamos extrair o título (tag <title>) do HTML coletado. Para isso basta acessar o elemento title do objeto soup:

print(soup.title)

# saída esperada: 
# <title>UOL - Seu universo online</title>
Enter fullscreen mode Exit fullscreen mode

É possível extrair outros elementos de forma semelhante. Por exemplo, para obter o primeiro link (tag <a>) do HTML, usamos o elemento a:

print(soup.a)

'''
saída esperada: 
<a class="hyperlink" href="https://www.ingresso.com/?partnership=home&amp;utm_source=uol.com.br&amp;utm_medium=barrauol&amp;utm_campaign=linkfixo_barrauol&amp;utm_content=barrauol-link-ingressocom&amp;utm_term=barrauol-ingressocom" title="Ingresso.com">
Ingresso.com
</a>
'''
Enter fullscreen mode Exit fullscreen mode

Podemos coletar todos os links do HTML com o método find_all('a'):

print(soup.find_all('a'))

'''saída esperada: uma lista com todos os links da página

[<a class="hyperlink" href="https://www.ingresso.com/?partnership=home&amp;utm_source=uol.com.br&amp;utm_medium=barrauol&amp;utm_campaign=linkfixo_barrauol&amp;utm_content=barrauol-link-ingressocom&amp;utm_term=barrauol-ingressocom" title="Ingresso.com">
Ingresso.com
</a>,
 <a class="hyperlink" href="https://batepapo.uol.com.br/?utm_source=uol.com.br&amp;utm_medium=barrauol&amp;utm_campaign=linkfixo_barrauol&amp;utm_term=barrauol-uolplay&amp;utm_content=barrauol" title="Bate-Papo">
Bate-Papo
</a>,
...
]
'''
Enter fullscreen mode Exit fullscreen mode

Documentação: Uma lista completa dos comandos do BeautifulSoup pode ser encontrada em sua documentação. Clique aqui para acessá-la.


Inspecionando o trecho HTML de interesse ^

Agora veremos como coletar a seção das notícias mais lidas do site de notícias.

Mais lidas

Atualmente (maio/2024), essa seção fica mais a direita da página. Para obter o elemento HTML referente a ela, inspecionamos a página . Posicionamos o cursor do mouse sobre a região da seção 'Mais lidas', clicamos com o botão direito do mouse e, em seguida, clicamos em Inspecionar.

Inspecionar

Atalho: Também é possível acessar o Inspect (Inspetor) do navegador web com o atalho Ctrl + Shift + c.

Com o Inspetor é possível identificar a tag HTML que caracteriza o elemento HTML desejado.

Inspetor check

A figura acima mostra essa etapa. Note que o trecho destacado, mostra que a seção "Mais Lidas" está na tag <li> e sua classe (class) é igual a mostRead__item.


Busca pela tag com o BeautifulSoup ^

Agora que identificamos a tag HTML correspondente as notícias mais lidas, basta procurarmos por ela no objeto soup.

O código abaixo procura por todas tags to tipo <li class= "mostRead__item"> e exibe o resultado.

all_most_read = soup.find_all('li', class_='mostRead__item')

print(all_most_read)

'''saída esperada:
[<li class="mostRead__item"><a class="mostRead__item__hyperlink hyperlink" href="https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/quatro-membros-da-mesma-familia-sao-encontrados-mortos-abracados-no-rs.htm" title="Quatro membros da mesma família são encontrados mortos abraçados no RS"><h3 class="title__element mostRead__title">
Quatro membros da mesma família são encontrados mortos abraçados no RS
<!-- --></h3><!-- --></a></li>, <li class="mostRead__item"><a class="mostRead__item__hyperlink hyperlink" href="https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/nunca-vi-um-rapaz-ele-conta-como-e-ser-marido-de-presa.htm" title="Ele narra a rotina de 'marido' de presa: 'Nunca vi um rapaz nas visitas'"><h3 class="title__element mostRead__title">
Ele narra a rotina de 'marido' de presa: 'Nunca vi um rapaz nas visitas'
<!-- --></h3><!-- --></a></li>, <li class="mostRead__item"><a class="mostRead__item__hyperlink hyperlink" href="https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/rs-prefeito-de-canoas-pede-evacuacao-imediata-de-quem-retornou-as-casas.htm" title="Com novo alerta de cheias, prefeitos do RS pedem que moradores deixem casas"><h3 class="title__element mostRead__title">
Com novo alerta de cheias, prefeitos do RS pedem que moradores deixem casas
<!-- --></h3><!-- --></a></li>, <li class="mostRead__item"><a class="mostRead__item__hyperlink hyperlink" href="https://noticias.uol.com.br/opiniao/coluna/2024/05/12/minha-indignacao.htm" title="'Confesso que perdi a paciência com mentirosos', diz ministro Paulo Pimenta"><h3 class="title__element mostRead__title">
'Confesso que perdi a paciência com mentirosos', diz ministro Paulo Pimenta
<!-- --></h3><!-- --></a></li>, <li class="mostRead__item"><a class="mostRead__item__hyperlink hyperlink" href="https://www.uol.com.br/esporte/futebol/colunas/futebol-pelo-mundo/2024/05/12/como-mensagem-de-rodrygo-para-o-rs-virou-fake-news-politica-na-europa.htm" title="Mensagem de Rodrygo para o RS vira fake news política na Europa"><h3 class="title__element mostRead__title">
Mensagem de Rodrygo para o RS vira fake news política na Europa
<!-- --></h3><!-- --></a></li>]
'''
Enter fullscreen mode Exit fullscreen mode

Para melhorar a organização dos dados coletados, podemos separar o título e o link da notícia mais lida com o get_text().

Código completo

Incluindo essa etapa o código completo para coleta e exibição das notícias na seção mais lida fica:

import requests

url = ('https://www.uol.com.br')
html = requests.get(url).text

soup = BeautifulSoup(html, 'html.parser')

news_most_read = []
i=0
for row in soup.find_all('li', class_='mostRead__item'):
    print(f'\n{i}. {row.get_text().strip()}')
    for a in row.find_all('a', href=True):
        print(f'>>> {a["href"]}')
    i+=1

'''saída esperada:
0. Quatro membros da mesma família são encontrados mortos abraçados no RS
>>> https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/quatro-membros-da-mesma-familia-sao-encontrados-mortos-abracados-no-rs.htm

1. Ele narra a rotina de 'marido' de presa: 'Nunca vi um rapaz nas visitas'
>>> https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/nunca-vi-um-rapaz-ele-conta-como-e-ser-marido-de-presa.htm

2. Com novo alerta de cheias, prefeitos do RS pedem que moradores deixem casas
>>> https://noticias.uol.com.br/cotidiano/ultimas-noticias/2024/05/12/rs-prefeito-de-canoas-pede-evacuacao-imediata-de-quem-retornou-as-casas.htm

3. 'Confesso que perdi a paciência com mentirosos', diz ministro Paulo Pimenta
>>> https://noticias.uol.com.br/opiniao/coluna/2024/05/12/minha-indignacao.htm

4. Mensagem de Rodrygo para o RS vira fake news política na Europa
>>> https://www.uol.com.br/esporte/futebol/colunas/futebol-pelo-mundo/2024/05/12/como-mensagem-de-rodrygo-para-o-rs-virou-fake-news-politica-na-europa.htm
'''
Enter fullscreen mode Exit fullscreen mode

Nota: Uma raspagem de dados como a que fizemos acessa os elementos HTML disponíveis no momento atual. Como os sites podem mudar ao longo do seu desenvolvimento, sempre que houver alterações, os nomes utilizados nas buscas e os resultados devem ser atualizados conforme necessidade. O site da UOL, em particular, tem mantido sua estrutura de HTML há um bom tempo, mudando apenas o conteúdo.


Sobre o robots.txt ^

Alguns sites não autorizam a raspagem de dados e informam isso no arquivo robots.txt. Para verificar o conteúdo deste arquivo basta acessar www.<nome-do-site.com.br>/robots.txt.

No caso do site de notícias aqui escolhido, ao acessar www.uol.com.br/robots.txt temos o seguinte retorno:

Print robots

O asterisco em User-agent: * indica que todos os agentes (softwares/bots) podem acessar todo conteúdo do site (Allow: /) com exceção do conteúdo de /carros/dev/ (Disallow: /carros/dev/).

Ainda há outras restrições. Os agentes GPTBot e Google-Extended não podem acessar o site (Disalow: /).

Uma lista de agentes e mais informações sobre o robots.txt estão disponíveis em https://www.robotstxt.org/db.html.

Atenção: Embora o robots.txt possua recomendações do que o site permite ou não acessar via software, algumas vezes o webmaster responsável não inclui o robots.txt, pois não é algo obrigatório. O que de fato regulamenta a coleta, armazenamento, uso, etc. dos dados vindo da raspagem é a legislação do país. Geralmente, para projetos pessoais, sem fins lucrativos, sem requisições massivas, costuma ser tranquilo.

De toda forma, vale avaliar como os dados coletados serão usados, visto que dependendo do caso pode haver implicações legais.


Exemplos de uso da raspagem de dados rodando em produção ^

A fim de ilustrar as possibilidades de uso do web scraping, deixamos dois exemplos de uso.

Querido Diário (https://queridodiario.ok.org.br)

A plataforma Querido Diário disponibiliza vários conteúdos de interesse público, muitas vezes coletados através da raspagem de dados. Nela o usuário pode obter informações relacionadas ao Diário Oficial de inúmeros municípios brasileiros.

Os dados do Querido Diário muitas vezes servem de matéria-prima para reportagens, pesquisas e análises de diferentes tipos.

Para contribuir com o esse projeto open source acesse seu Github: https://github.com/okfn-brasil/querido-diario-comunidade

Mini-app ^

Outro exemplo que usa a raspagem de dados é esse mini-app experimental que fizemos algum tempo atrás:

https://newsaggapp-1-j9368482.deta.app/

Ele foi disponibilizado em produção de forma 100% gratuita com o Deta Space: https://deta.space/.


Conclusão e próximos passos ^

Assim como fizemos o scraping da seção "mais lidas", podemos coletar outras seções do site da UOL ou de outro de preferência. Basta usar a etapa de análise com o Inspetor do navegador web para conhecer a estrutura do HTML. Além disso, o que vimos sobre o robots.txt pode servir de base caso haja dúvidas sobre a viabilidade ou não de realizar a raspagem de algum site. Acreditamos que o conteúdo visto pode contribuir de alguma forma para iniciantes no assunto ou interessados. Dicas ou sugestões são bem-vindas.

Agradecemos a leitura! ☕ 💻 🗞️

Top comments (0)