Beta
NER sui testi degli Iron Maiden con NLTK e Spacy
Introduzione
Il progetto ha come obiettivo quello di individuare le categorie semantiche principali nei testi della celebre band heavy metal britannica attraverso un algoritmo di NER (Named Entity Recognition). Per farlo, andremo a estrarre i dati necessari dal web e li processeremo con alcuni strumenti offerti dalle librerie nltk e spacy.
Fonte testi: http://www.darklyrics.com/i/ironmaiden.html
# Installa la libreria scrapy per il Web Scraping
!pip install scrapy
Hidden output
# Importa i moduli necessari
import requests
from scrapy import Selector
import pandas as pd
import matplotlib.pyplot as plt
import nltk
import spacy
# Scarica il modello en_core_web_lg di spacy
spacy.cli.download("en_core_web_lg")
# Scarica i moduli punkt e stopwords di nltk
nltk.download('punkt')
nltk.download('stopwords')
Hidden output
Web Scraping
# Crea un dizionario vuoto
diz = {}
# Url di partenza
url = "http://www.darklyrics.com/i/ironmaiden.html"
# Connessione al sito
html = requests.get(url).content
sel = Selector(text=html)
# Estrae i link di ogni singolo album
links = sel.xpath('//div[@class = "album"]//a/@href').extract()
# Inserisce in una lista i link degli album individuati
urls = ["http://www.darklyrics.com" + link.replace("..", "") for link in links if link[-2:] == "#1"]
for url in urls:
# Connessione alla pagina dell'album
html = requests.get(url).content
sel = Selector(text=html)
try:
# Estrae il nome dell'album
album = sel.xpath('//title/text()').extract()[0].split('"')[1]
# Estrae i titoli dei brani
titles = sel.xpath('//div[@class="albumlyrics"]/a/text()').extract()
# Estrae il testo dei brani
lyrics = sel.xpath('//div[@class="lyrics"]/text()').extract()
# Pulisce il testo dei brani
lyrics = [x.replace("\n", "") for x in lyrics]
lyrics = [x for x in lyrics if len(x) > 0 and x != "\r"]
# Inserisce album, titoli dei brani e testi dei brani nel dizionario
diz[album] = {"titles" : titles, "lyrics" : lyrics}
except:
pass
# Mostra gli album estratti
display(list(diz.keys()))
# Mostra i brani dell'album Piece Of Mind
display(diz["Piece Of Mind"]["titles"])
# Mostra le prime 15 righe dei testi dell'album Piece Of Mind
display(diz["Piece Of Mind"]["lyrics"][0:15])
Preprocessing dei dati
# Crea una lista unica con tutti i testi
all_lyrics_list = [pd.Series(diz[x]["lyrics"]) for x in diz.keys()]
# Concatena tutti i testi in un'unica stringa
all_lyrics_string = " ".join([" ".join(x) for x in all_lyrics_list])
# Lunghezza della stringa
display(len(all_lyrics_string))
Named Entity Recognition
# Carica il modello di spacy per il nlp sulla lingua inglese
nlp = spacy.load('en_core_web_lg')
# Crea una lista di stop-words della lingua inglese
stopwords = nltk.corpus.stopwords.words("english")
# Tokenizza le singole parole e le inserisce in una lista escludendo i caratteri non alfabetici e le stop-words
words = [word for word in nltk.word_tokenize(all_lyrics_string.lower())
if word.isalpha() and word not in stopwords]
# Utilzza il modello di nlp sulle parole individuate
doc = nlp(" ".join(words))
# Crea un dataframe vuoto
df = pd.DataFrame()
# Inserisce parole e categorie semantiche nel dataframe
df["word"] = [str(x) for x in doc.ents]
df["label"] = [x.label_ for x in doc.ents]
# Rimuove i duplicati
df.drop_duplicates(inplace=True)
# Mostra le prime 5 righe del dataframe
display(df.head())
# Conteggia le categorie semantiche e genera un grafico
df.label.value_counts().sort_values().plot(kind="barh")
plt.xlabel("Frequenza")
plt.ylabel("Categoria");
# Mostra le parole che hanno come categoria semantica un luogo
display(df[df.label == "LOC"].word)
# Mostra le parole che hanno come categoria una nazionalità o un gruppo politico-religioso
display(df[df.label == "NORP"].word)