2012-06-30 13 views
5

Jak przechodzisz do parsowania strony HTML z bezpłatnym tekstem, listami, tabelami, nagłówkami itp. Na zdania?Parsowanie HTML w zdania - jak obsługiwać tabele/listy/nagłówki/etc?

Weźmy na przykład this wikipedia page. Nie jest/są:

Po aprowizacji z pytona NLTK, chcę przetestować wszystkie te różne metody adnotacji korpusu (od http://nltk.googlecode.com/svn/trunk/doc/book/ch11.html#deciding-which-layers-of-annotation-to-include):

  • Tokenizacja słowa: Ortogonalna forma tekstu nie jednoznacznie identyfikuje jego tokenów. Tokenized i znormalizowana wersja, oprócz konwencjonalnej wersji ortograficznej, może być bardzo wygodnym zasobem.
  • 10 Segmentacja zdań: Jak widzieliśmy w rozdziale 3, segmentacja zdań może być trudniejsza niż się wydaje. Niektóre korporacje używają więc wyraźnych adnotacji do oznaczania segmentacji zdań.
  • Podział na akapity: Akapity i inne elementy strukturalne (nagłówki, rozdziały itp.) Mogą być wyraźnie przypisane.
  • Część mowy: Kategoria składniowa każdego słowa w dokumencie.
  • Struktura syntaktyczna: Struktura drzewa przedstawiająca strukturę zdania.
  • Płytka semantyka: Adnotacje nazw i odniesień do rdzenia, znaczniki ról znaczeniowych.
  • dialogu i dyskursu: dialog tagi Act, retoryczna konstrukcja

Po przerwie dokumentu do zdań wydaje się całkiem proste. Ale w jaki sposób chcesz przełamać coś takiego jak HTML z tej strony Wikipedii? Jestem bardzo obeznana z używaniem parserów HTML i XML oraz przechodzeniem przez drzewo i próbowałem po prostu rozebrać znaczniki HTML, aby uzyskać zwykły tekst, ale ponieważ po usunięciu HTML interpunkcja jest niedostępna, NLTK nie parsuje rzeczy takich jak komórki tabeli, lub nawet listy, poprawnie.

Czy jest jakaś najlepsza praktyka lub strategia do analizowania tego z NLP? Czy po prostu trzeba ręcznie napisać analizator składniowy dla danej strony?

Poszukuję wskazówek w dobrym kierunku, naprawdę chcę wypróbować to NLTK!

+0

Czy próbowali za pomocą Punkt (nie jest to realizowane w NLTK) na pozbawiony tekstu aby sprawdzić, czy dostaje się wszędzie? – dmh

+1

Moja nieoficjalna obserwacja jest taka, że ​​analizatory składniowe generalnie źle radzą sobie z wyświetlaniem tekstu (w przeciwieństwie do działającej prozy). Jeśli znajdziesz lub opracujesz dobre rozwiązanie, proszę wykonaj tutaj! – tripleee

Odpowiedz

1

Wygląda na to, że usuwasz cały kod HTML i generujesz dokument płaski, co powoduje pomylenie parsera, ponieważ luźne elementy są ze sobą sklejone. Ponieważ masz doświadczenie z XML, sugeruję odwzorowanie twoich danych wejściowych na prostą strukturę XML, która utrzymuje kawałki oddzielnie. Możesz uczynić to tak prostym, jak chcesz, ale być może będziesz chciał zachować pewne informacje. Np. Przydatne może być oznaczanie tytułów, nagłówków sekcji itp. Jako takich. Kiedy masz sprawne drzewo XML, które utrzymuje oddzielne kawałki, użyj XMLCorpusReader, aby zaimportować je do uniwersum NLTK.

1

miałem napisać przepisów szczególnych dotyczących Dokumenty XML byłem analizujących.

Co zrobiłem było mieć mapowanie znaczników HTML na segmenty. Mapowanie opierało się na analizie kilku dokumentów/stron i określeniu, co oznaczają tagi HTML. Przykł. <h1> to segment frazy; <li> są akapitami; <td> to tokeny

Jeśli chcesz pracować z XML, możesz reprezentować nowe mapowania jako znaczniki. Przykł. <H1> do < wyrażenie >; <li> do <akapit>; <td> do < żeton >

Jeśli chcesz pracować na zwykłym tekście, można reprezentować mapowania jako zestaw znaków (np. [PHRASESTART] [PHRASEEND]), podobnie jak POS lub etykietowania EOS.

0

Można użyć narzędzi, takich jak python-goose którego celem wydobycia artykuły ze stron html.

przeciwnym razie zrobiłem następujący mały program, który daje rodzaju dobrymi wynikami:

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

Jak alexis odpowiedział python-goose może być dobrym rozwiązaniem.

Istnieje również HTML Sentence Tokenizer, a (nowy) biblioteka, która ma na celu rozwiązać dokładnie ten problem. Jego składnia jest bardzo prosta. W jednym wierszu, parsed_sentences = HTMLSentenceTokenizer().feed(example_html_one), możesz uzyskać zdania na stronie HTML przechowywanej w tablicy parsed_sentences.