Rap Genius w/ Python 上的 Web Scraping Rap 歌词
Posted
技术标签:
【中文标题】Rap Genius w/ Python 上的 Web Scraping Rap 歌词【英文标题】:Web Scraping Rap lyrics on Rap Genius w/ Python 【发布时间】:2014-09-12 11:17:30 【问题描述】:我有点编码新手,我一直在尝试使用 Beautiful Soup(用于从 html 和 XML 文件中提取数据的 Python 库)从说唱天才http://genius.com/artists/Andre-3000 中抓取 Andre 3000 的歌词。我的最终目标是让数据采用字符串格式。这是我目前所拥有的:
from bs4 import BeautifulSoup
from urllib2 import urlopen
artist_url = "http://rapgenius.com/artists/Andre-3000"
def get_song_links(url):
html = urlopen(url).read()
# print html
soup = BeautifulSoup(html, "lxml")
container = soup.find("div", "container")
song_links = [BASE_URL + dd.a["href"] for dd in container.findAll("dd")]
print song_links
get_song_links(artist_url)
for link in soup.find_all('a'):
print(link.get('href'))
所以我需要其他代码方面的帮助。如何将他的歌词转换为字符串格式?然后我如何使用自然语言工具包 (NLTK) 来标记句子和单词。
【问题讨论】:
这是一个很棒的主意。你会生成新的歌词对吗?我正在考虑为 Tupac 做同样的事情。必须有一个工具可以根据他们现有的歌曲生成他们的声音。我的意思是,如果它是单词级别的,那么所有新生成的歌词都包含艺术家以前唱过的单词,因此需要对声波进行采样和扭曲,以使生成的声音听起来像你想要的那样。 【参考方案1】:即使你可以抓取网站,并不意味着你应该,而是你可以使用天才的API,只需从Genius API site创建访问令牌
import lyricsgenius as genius #calling the API
api=genius.Genius('youraccesstokenhere12345678901234567890isreallylongiknow')
artist=api.search_artist('The artist name here')
aux=artist.save_lyrics(format='json', filename='artist.txt',overwrite=True, skip_duplicates=True,verbose=True)#you can change parameters acording to your needs,i dont recommend using this file directly because it saves a lot of data that you might not need and will take more time to clean it
titles=[song['title'] for song in aux['songs']]#in this case for example i just want title and lyrics
lyrics=[song['lyrics'] for song in aux['songs']]
thingstosave=[]
for i in range(0,128):
thingstosave.append(titles[i])
thingstosave.append(lyrics[i])
with open("C:/whateverfolder/alllyrics.txt","w") as output:
output.write(str(thingstosave))
【讨论】:
【参考方案2】:GitHub / jashanj0tsingh / LyricsScraper.py 提供基本的从genius.com 上抓取歌词到文本文件中的功能,其中每一行代表一首歌曲。它将艺术家的名字作为输入。然后可以轻松地将生成的文本文件提供给您的自定义 nltk
或通用解析器以执行您想要的操作。
代码如下:
# A simple script to scrape lyrics from the genius.com based on atrtist name.
import re
import requests
import time
import codecs
from bs4 import BeautifulSoup
from selenium import webdriver
mybrowser = webdriver.Chrome("path\to\chromedriver\binary") # Browser and path to Web driver you wish to automate your tests cases.
user_input = input("Enter Artist Name = ").replace(" ","+") # User_Input = Artist Name
base_url = "https://genius.com/search?q="+user_input # Append User_Input to search query
mybrowser.get(base_url) # Open in browser
t_sec = time.time() + 60*20 # seconds*minutes
while(time.time()<t_sec): # Reach the bottom of the page as per time for now TODO: Better condition to check end of page.
mybrowser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
html = mybrowser.page_source
soup = BeautifulSoup(html, "html.parser")
time.sleep(5)
pattern = re.compile("[\S]+-lyrics$") # Filter http links that end with "lyrics".
pattern2 = re.compile("\[(.*?)\]") # Remove unnecessary text from the lyrics such as [Intro], [Chorus] etc..
with codecs.open('lyrics.txt','a','utf-8-sig') as myfile:
for link in soup.find_all('a',href=True):
if pattern.match(link['href']):
f = requests.get(link['href'])
lyricsoup = BeautifulSoup(f.content,"html.parser")
#lyrics = lyricsoup.find("lyrics").get_text().replace("\n","") # Each song in one line.
lyrics = lyricsoup.find("lyrics").get_text() # Line by Line
lyrics = re.sub(pattern2, "", lyrics)
myfile.write(lyrics+"\n")
mybrowser.close()
myfile.close()
【讨论】:
Try adding some context to your answer 这只是挂在艺术家的页面上。【参考方案3】:希望这仍然是相关的!我正在对 Eminem 的歌词做同样的事情,但来自于 Lyrics.com。它必须来自 Rap Genius 吗?我发现 Lyrics.com 更容易抓取。
要获得 Andre 3000,只需相应地更改代码。
这是我的代码;它获取歌曲链接,然后抓取这些页面以获取歌词并将歌词附加到列表中:
import re
import requests
import nltk
from bs4 import BeautifulSoup
url = 'http://www.lyrics.com/eminem'
r = requests.get(url)
soup = BeautifulSoup(r.content)
gdata = soup.find_all('div','class':'row')
eminemLyrics = []
for item in gdata:
title = item.find_all('a','itemprop':'name')[0].text
lyricsdotcom = 'http://www.lyrics.com'
for link in item('a'):
try:
lyriclink = lyricsdotcom+link.get('href')
req = requests.get(lyriclink)
lyricsoup = BeautifulSoup(req.content)
lyricdata = lyricsoup.find_all('div','id':re.compile('lyric_space|lyrics'))[0].text
eminemLyrics.append([title,lyricdata])
print title
print lyricdata
print
except:
pass
这将为您提供列表中的歌词。打印所有标题:
titles = [i[0] for i in eminemLyrics]
print titles
获取特定歌曲:
titles.index('Cleaning out My Closet')
120
要标记歌曲,请将值 (120
) 插入:
song = nltk.word_tokenize(eminemLyrics[120][1])
nltk.pos_tag(song)
【讨论】:
【参考方案4】:这里有一个例子,如何抓取页面上的所有歌曲链接,关注它们并获取歌词:
from urlparse import urljoin
from bs4 import BeautifulSoup
import requests
BASE_URL = "http://genius.com"
artist_url = "http://genius.com/artists/Andre-3000/"
response = requests.get(artist_url, headers='User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36')
soup = BeautifulSoup(response.text, "lxml")
for song_link in soup.select('ul.song_list > li > a'):
link = urljoin(BASE_URL, song_link['href'])
response = requests.get(link)
soup = BeautifulSoup(response.text)
lyrics = soup.find('div', class_='lyrics').text.strip()
# tokenize `lyrics` with nltk
注意这里使用了requests
模块。另请注意,User-Agent
标头是必需的,因为该站点在没有它的情况下返回 403 - Forbidden
。
【讨论】:
这很好,但是当我尝试运行它时出现此错误“ImportError: No module named bs4” @Ibrewster 你需要安装beautifulsoup4
:运行pip install beautifulsoup4
。
是的,我已经安装了 bs4,但它无法正常工作。所以我尝试重新安装它,它仍然无法正常工作。
因为您使用的是 Python 3。在这种情况下使用 pip3 install beautifulsoup4
我将它复制粘贴到一个 jupyter 单元格中,当我运行它时,似乎什么也没发生。【参考方案5】:
首先,对于每个链接,您需要下载该页面并使用 BeautifulSoup 对其进行解析。然后在该页面上寻找将歌词与其他页面内容区分开来的区别属性。我发现 很有帮助。然后在歌词页面内容上运行 .find_all 以获取所有歌词行。对于每一行,您可以调用 .get_text() 以从每行歌词中获取文本。
至于 NLTK,一旦安装,您就可以像这样导入它并解析句子:
from nltk.tokenize import word_tokenize, sent_tokenize
words = [word_tokenize(t) for t in sent_tokenize(lyric_text)]
这将为您提供每个句子中所有单词的列表。
【讨论】:
以上是关于Rap Genius w/ Python 上的 Web Scraping Rap 歌词的主要内容,如果未能解决你的问题,请参考以下文章
ElementNotVisibleException:Python + Selenium,W eb上的登录凭据