2012-06-30 10 views
5

Come si procede all'analisi di una pagina HTML con testo, elenchi, tabelle, intestazioni, ecc., In frasi libere?Analisi di HTML in frasi - come gestire tabelle/elenchi/intestazioni/ecc.?

Prendere ad esempio this wikipedia page. C'è/sono:

Dopo fare in giro con il pitone NLTK, voglio testare tutti questi diversi metodi di annotazione del corpus (da http://nltk.googlecode.com/svn/trunk/doc/book/ch11.html#deciding-which-layers-of-annotation-to-include):

  • Tokenizzazione parola: la forma ortografica del testo non identifica in modo univoco i token. Una versione tokenizzata e normalizzata, oltre alla versione ortografica convenzionale, può essere una risorsa molto conveniente.
  • Frase Segmentazione: Come abbiamo visto nel capitolo 3, frase segmentazione può essere più difficile di quanto sembri. Alcuni corpora utilizzano quindi annotazioni esplicite per contrassegnare la segmentazione della frase.
  • Paragrafo Segmentazione: I paragrafi e altri elementi strutturali (titoli, capitoli, ecc) possono essere esplicitamente annotati.
  • Parte del discorso: La categoria sintattica di ogni parola in un documento.
  • struttura sintattica: Una struttura ad albero che mostra la struttura costituente di una frase.
  • Semantica Shallow: nome di entità e coreference annotazioni, etichette ruolo semantico.
  • dialogo e del discorso: dialogo tag atto, struttura retorica

Una volta che si interrompe un documento in frasi sembra abbastanza semplice. Ma come si fa a scomporre qualcosa come l'HTML da quella pagina di Wikipedia? Ho molta familiarità con l'utilizzo di parser HTML/XML e l'attraversamento dell'albero, e ho provato a rimuovere i tag HTML per ottenere il testo normale, ma poiché la punteggiatura manca dopo la rimozione dell'HTML, NLTK non analizza le cose come le celle della tabella, o anche elenchi, correttamente.

Esiste qualche best practice o strategia per analizzare tali elementi con la PNL? O devi semplicemente scrivere manualmente un parser specifico per quella singola pagina?

Solo cercando alcuni puntatori nella giusta direzione, voglio davvero provare questo NLTK!

+0

Hai provato a usare Punkt (è implementato in NLTK) sul testo messo a nudo per vedere se questo ti porta ovunque? – dmh

+1

La mia osservazione informale è che in genere i parser sono cattivi nel gestire e rappresentare il testo visualizzato (al contrario della prosa in esecuzione). Se trovi o escogiti una buona soluzione, ti preghiamo di seguire qui! – tripleee

risposta

1

Sembra che tu stai nudo tutti HTML e la generazione di un documento piatta, che confonde il parser in quanto i pezzi sfusi sono bloccati insieme. Dato che hai esperienza con XML, ti suggerisco di mappare i tuoi input su una semplice struttura XML che mantiene separati i pezzi. Puoi renderlo semplice come vuoi, ma forse vorrai conservare alcune informazioni. Ad esempio, può essere utile contrassegnare titoli, intestazioni di sezione ecc. Come tali. Quando hai un albero XML funzionante che mantiene separati i blocchi, utilizza XMLCorpusReader per importarlo nell'universo NLTK.

1

Ho dovuto scrivere regole specifiche per i documenti XML che stavo analizzando.

Quello che ho fatto è stato avere una mappatura dei tag html in segmenti. Questa mappatura si basava sullo studio di diversi documenti/pagine e sulla determinazione di ciò che rappresentano i tag html. Es. <h1> è un segmento di frase; <li> sono paragrafi; <td> sono token

Se si desidera lavorare con XML, è possibile rappresentare i nuovi mapping come tag. Es. <h1> a <frase>; <li> a <paragrafo>; <td>-<gettone>

Se si desidera lavorare su testo normale, è possibile rappresentare le mappature come un insieme di caratteri (es. [PHRASESTART] [PHRASEEND]), proprio come POS o l'etichettatura EOS.

0

È possibile utilizzare strumenti come python-goose che mira a estrarre articoli da pagine html.

Altrimenti ho fatto la seguente piccolo programma che dà tipo di buoni risultati:

from html5lib import parse 


with open('page.html') as f: 
    doc = parse(f.read(), treebuilder='lxml', namespaceHTMLElements=False) 

html = doc.getroot() 
body = html.xpath('//body')[0] 


def sanitize(element): 
    """Retrieve all the text contained in an element as a single line of 
    text. This must be executed only on blocks that have only inlines 
    as children 
    """ 
    # join all the strings and remove \n 
    out = ' '.join(element.itertext()).replace('\n', ' ') 
    # replace multiple space with a single space 
    out = ' '.join(out.split()) 
    return out 


def parse(element): 
    # those elements can contain other block inside them 
    if element.tag in ['div', 'li', 'a', 'body', 'ul']: 
     if element.text is None or element.text.isspace(): 
      for child in element.getchildren(): 
       yield from parse(child) 
     else: 
      yield sanitize(element) 
    # those elements are "guaranteed" to contains only inlines 
    elif element.tag in ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']: 
     yield sanitize(element) 
    else: 
     try: 
      print('> ignored', element.tag) 
     except: 
      pass 


for e in filter(lambda x: len(x) > 80, parse(body)): 
    print(e) 
0

Come alexis risposto, python-goose può essere una buona opzione.

C'è anche HTML Sentence Tokenizer, una (nuova) libreria che ha lo scopo di risolvere questo problema esatto. La sua sintassi è molto semplice. In una riga, parsed_sentences = HTMLSentenceTokenizer().feed(example_html_one), è possibile ottenere le frasi in una pagina HTML memorizzata nell'array parsed_sentences.