NER sui testi degli Iron Maiden
  • AI Chat
  • Code
  • Report
  • Beta
    Spinner

    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)