2014-07-21 11 views
7

Sono un po 'novizio di programmazione e ho cercato di raschiare i testi di Andre 3000 al genio Rap, http://genius.com/artists/Andre-3000, usando Beautiful Soup (Una libreria Python per estrarre i dati da File HTML e XML). Il mio obiettivo finale è avere i dati in un formato stringa. Ecco cosa ho finora:Testo di Web Scraping Rap su Rap Genius w/Python

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')) 

Quindi ho bisogno di aiuto con il resto del codice. Come faccio a ottenere i suoi testi in formato stringa? e poi come uso il kit di strumenti della lingua nazionale (nltk) per inviare token alle frasi e alle parole.

risposta

3

Ecco un esempio, come per afferrare tutti i link dei brani sulla pagina, li seguono e ottenere i testi delle canzoni:

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 

Nota che il modulo requests è qui utilizzato. Si noti inoltre che è richiesta l'intestazione User-Agent poiché il sito restituisce 403 - Forbidden senza di esso.

+0

questo è grande, ma ottengo questo errore quando provo a farlo funzionare "ImportError: No module named BS4" – Ibrewster

+0

@Ibrewster è necessario installare 'beautifulsoup4': run 'pip installa beautifulsoup4'. – alecxe

+0

sì, avevo già installato bs4 e non funzionava. così ho provato a reinstallarlo e ancora non funziona. – Ibrewster

1

Innanzitutto, per ogni collegamento è necessario scaricare tale pagina e analizzarla con BeautifulSoup. Quindi cerca un attributo distintivo in quella pagina che separa i testi dagli altri contenuti della pagina. Ho trovato < un data-editorial-state = "accettato" data-classification = "accettato" data-group = "0" > per essere utile. Quindi esegui un file .find_all sul contenuto della pagina dei testi per ottenere tutte le linee dei testi. Per ogni riga puoi chiamare .get_text() per ottenere il testo da ogni riga di testo.

Per quanto riguarda NLTK, una volta installato è possibile importare e analizzare le frasi in questo modo:

from nltk.tokenize import word_tokenize, sent_tokenize 
words = [word_tokenize(t) for t in sent_tokenize(lyric_text)] 

Questo vi darà un elenco di tutte le parole in ogni frase.

0

Spero che questo sia ancora rilevante! Sto facendo la stessa cosa con i testi di Eminem, ma da lyrics.com. Deve essere di Rap Genius? Ho trovato testi.com più facili da raggirare.

Per ottenere Andre 3000 è sufficiente modificare il codice di conseguenza.

Ecco il mio codice; diventa collegamenti canzone e poi raschia quelle pagine per ottenere testi e il testo di una lista aggiunge:

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 

Questo vi darà i testi in una lista. Per stampare tutti i titoli:

titles = [i[0] for i in eminemLyrics] 
print titles 

Per ottenere un brano specifico:

titles.index('Cleaning out My Closet') 
120 

Per tokenize la canzone, inserire tale valore (120) in:

song = nltk.word_tokenize(eminemLyrics[120][1]) 
nltk.pos_tag(song) 
1

GitHub/jashanj0tsingh/LyricsScraper.py fornisce raschiatura di base del testi di genius.com in un file di testo in cui ogni riga rappresenta una canzone. Prende il nome dell'artista come input. Il file di testo generato può quindi essere facilmente inviato al tuo custom nltk o al parser generale per fare ciò che vuoi.

Il codice è qui sotto:

# 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() 
+0

[Prova ad aggiungere un contesto alla tua risposta] (https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain- link-altrove-davvero-bene-risposte) – alex