Rincon Sapência como exemplo. Logo de início vemos o nome do músico, mais tocadas e todas as músicas, sendo este parte da página uma lista com, como o próprio nome diz, todas as músicas daquele cantor. agora é só analisar o HTML. Inspecionando o elemento dessa pequena parte:
Encontramos uma estrutura parecida com esta:
<div class="cnt-list--alp">
<ul class="cnt-list">
<li><a id="A" href="/rincon-sapiencia/a-coisa-ta-preta/">A Coisa Tá Preta</a></li>
<li><a href="/rincon-sapiencia/a-noite-e-nossa/">A Noite é Nossa</a></li>
<li><a href="/rincon-sapiencia/a-volta-pra-casa/">A Volta pra Casa</a></li>
<li><a href="/rincon-sapiencia/afro-rep/">Afro Rep</a></li>
<li><a href="/rincon-sapiencia/amores-as-escuras/">Amores às Escuras</a></li>
<li><a href="/rincon-sapiencia/andar-com-fe/">Andar Com Fé</a></li>
<li><a href="/rincon-sapiencia/rea-de-conforto/">Área de Conforto</a></li>
</ul>
</div>
Nesse bloco de HTML já entendemos que uma vez na página do músico conseguimos o nome da música e um link para cada música. Esse será nosso primeiro trabalho.
Vamos fazer agora, em Python, exatamente o que fizemos aqui: Acessar a página de um músico e listar as suas músicas.
Se a primeira coisa que vamos fazer é acessar uma página precisamos então usar a biblioteca requests do python para a tal, uma requisição get, com a URL do que queremos pegar deve ser o bastante:
import requests
def get_all_musics(musician):
all_musics = []
# Url que iremos fazer a raspagem, nesse caso, a url
# base do Letras + o nome do musico que queremos trabalhar.
url = "https://www.letras.com/{}".format(musician)
# Requisição web para a nossa url ja montada
# isso no retornara um resultado http
response = requests.get(url)
# Desse resultado, podemos pegar o seu conteudo, que sera uma lista de bytes
# representando o nosso html
html = response.content
return all_musics
Do jeito que as coisas estão o código ainda retorna apenas uma lista vazia. Ainda precisamos popular a lista all_musics
com o conteúdo dos elementos que havíamos observado no HTML do site.
Como já temos o HTML basta trabalharmos nele, vamos usar a biblioteca BeautifulSoup. Ela vai facilitar filtrarmos elementos por id e classe sem precisarmos aprender seletores CSS ou XPath (ainda reservo um post só para isso).
Para instalar use pipy:
pip install beautifulsoup4
Agora vamos transformar o conteúdo de nossa requisição em um objeto que possa ser filtrado para acharmos a url e o nome da musica.
import requests
from bs4 import BeautifulSoup
def get_all_musics(musician):
all_musics = []
# Url que iremos fazer a raspagem, nesse caso, a url
# base do Letras + o nome do musico que queremos trabalhar.
url = "https://www.letras.com/{}".format(musician)
# Requisição web para a nossa url ja montada
# isso no retornara um resultado http
response = requests.get(url)
# Desse resultado, podemos pegar o seu conteudo, que sera uma lista de bytes
# representando o nosso html
html = response.content
# faz o 'parsing' para um objeto em que possamos trabalhar
soup = BeautifulSoup(html, 'html.parser')
# captura o elemento div que tenha a classe 'cnt-list--alp'
all_songs = soup.find('div', {'class': 'cnt-list--alp'})
# Do elemento armazenado em all_songs, procura em seus filhos por
# elementos de tag 'li' (aqui chegamos nas linhas da lista)
song_list = all_songs.find_all('li')
return all_musics
Ainda não retornamos nada, mas se quisermos retornar o song_list
teremos algo parecido com isso:
[
<li><a href="/rincon-sapiencia/a-coisa-ta-preta/" id="A">A Coisa Tá Preta</a></li>,
<li><a href="/rincon-sapiencia/a-noite-e-nossa/">A Noite é Nossa</a></li>,
<li><a href="/rincon-sapiencia/a-volta-pra-casa/">A Volta pra Casa</a></li>,
<li><a href="/rincon-sapiencia/afro-rep/">Afro Rep</a></li>,
<li><a href="/rincon-sapiencia/amores-as-escuras/">Amores às Escuras</a></li>,
<li><a href="/rincon-sapiencia/andar-com-fe/">Andar Com Fé</a></li>,
<li><a href="/rincon-sapiencia/rea-de-conforto/">Área de Conforto</a></li>,
<li><a href="/rincon-sapiencia/autentico-x-excentrico-x-incomparavel/">Autêntico X Excêntrico X Incomparável</a></li>,
<li><a href="/rincon-sapiencia/batidao/" id="B">Batidão</a></li>,
<li><a href="/rincon-sapiencia/bencao/">Benção (part. William Magalhães)</a></li>,
<li><a href="/rincon-sapiencia/coisas-de-brasil/" id="C">Coisas de Brasil</a></li>,
[...]
Isso tudo é uma lista com todas as músicas presentes naquela página, agora só precisamos extrair a url e o nome da musica. Para isso continuaremos usando o BeautifulSoup, adicionamos ao código anterior as linhas:
for song_elem in song_list:
# Note que o href esta dentro da tag 'a', que esta dentro do nosso item capturado 'li'
link = song_elem.find('a')['href']
name = song_elem.find('a').text
# Concatena com a url base
link = 'https://www.letras.com' + link
song = {
"url": link,
"name": name
}
all_musics.append(song)
Dessa forma temos agora na lista all_musics
um dicionário com nome e link de cada música! Conseguimos com poucas linhas de código já fazermos algo interessante, mas ainda não é nosso objetivo final, nosso próximo passo é pegar essa lista e para cada música capturar a letra dessa música acessando a url.
Inspecionando o elemento que armazena a letra temos isso:
<div class="cnt-letra p402_premium" style="font-size: 19px;">
<article>
<p>Salve!
<br>OK!<br>
Rincon Sapiência, conhecido também como Manicongo, certo?
<br>Quando alguém fala que eu não sou um MC acima da média, eu falo<br>
(Ahn? Ahn? Ahn? Ahn?)<br>
Eu não entendo nada, pai!<br>
(Ahn? Ahn? Ahn? Ahn?)<br>
A cultura do MC ainda vive, certo? Se depender de mim<br>
Vam'bora!</p>
<p>Meu verso é livre, ninguém me cancela
<br>Tipo Mandela saindo da cela
<br>Minhas linha voando cheia de cerol
<br>E dá dó das cabeça quando rela nela
<br>Partiu para o baile, fugiu da balela
<br>Batemos tambores, eles panela
<br>Roubamos a cena, não tem canivete
<br>As patty derrete que nem muçarela
<br>Quente que nem a chapinha no crespo
<br>Não, crespos estão se armando
<br>Faço questão de botar no meu texto<br>
Dessa forma, conseguimos fazer um script parecido com o anterior, porém agora filtrando pela classe cnt-letra
e pegando todo o conteúdo de texto nele contido, a gente pode fazer isso dessa forma:
def get_lyric_from_url(url):
response = requests.get(url)
soup = BeautifulSoup(response.content, 'lxml')
lyric = soup.find('div', 'cnt-letra').getText(separator=' ')
return lyric
Se rodarmos o método get_lyric_from_url
para qualquer url de musica do Letras.com já teremos, em formato de string, a letra desta música.
Agora já temos um método que captura todas as músicas de um determinado músico e um outro método que para o link dessa musica captura sua letra. Para não me alongar muito esse post fica por aqui. Eu pretendo ainda usar esse código para trabalhar com algum texto sobre processamento de linguagem natural e visualização de dados mas isso fica para o futuro.
Esse é o código final de todo o nosso trabalho, com o bônus que ainda gera um arquivo json armazenado tudo que foi capturado!
import json
import requests
from bs4 import BeautifulSoup
def get_all_musics(musician):
all_musics = []
# Url que iremos fazer a raspagem, nesse caso, a url
# base do Letras + o nome do musico que queremos trabalhar.
url = "https://www.letras.com/{}".format(musician)
# Requisição web para a nossa url ja montada
# isso no retornara um resultado http
response = requests.get(url)
# Desse resultado, podemos pegar o seu conteudo, que sera uma lista de bytes
# representando o nosso html
html = response.content
# faz o 'parsing' para um objeto em que possamos trabalhar
soup = BeautifulSoup(html, 'html.parser')
# captura o elemento div que tenha a classe 'cnt-list--alp'
all_songs = soup.find('div', {'class': 'cnt-list--alp'})
# Do elemento armazenado em all_songs, procura em seus filhos por
# elementos de tag 'li' (aqui chegamos nas linhas da lista)
song_list = all_songs.find_all('li')
for song_elem in song_list:
# Note que o href esta dentro da tag 'a', que esta dentro do nosso item capturado 'li'
link = song_elem.find('a')['href']
name = song_elem.find('a').text
# Concatena com a url base
link = 'https://www.letras.com' + link
song = {
"url": link,
"name": name
}
all_musics.append(song)
return all_musics
def get_lyric_from_url(url):
response = requests.get(url)
soup = BeautifulSoup(response.content, 'lxml')
lyric = soup.find('div', 'cnt-letra').getText(separator=' ')
return lyric
musician_code = 'rincon-sapiencia'
songs = get_all_musics(musician_code)
for song in songs:
lyric = get_lyric_from_url(x[0]['url'])
song['lyric'] = lyric
with open('songs_{}.json'.format(musician_code), 'w') as file_o:
file_o.write(json.dumps(songs))
Um simples tutorial apresentando metodo de web-scrapping com BeautifulSoup
2018-09-01