2012-06-30 47 views
5

你如何解析一個包含自由文本,列表,表格,標題等的HTML頁面到句子中?例如解析HTML爲句子 - 如何處理表/列表/標題/等?

this wikipedia page爲例。有/是:

與蟒蛇NLTK亂搞後,我想測試一下這些不同的語料庫註釋方法(從http://nltk.googlecode.com/svn/trunk/doc/book/ch11.html#deciding-which-layers-of-annotation-to-include):

  • 單詞標記:正文形式的文本不能明確標識其標記。除了傳統的拼寫版本之外,標記化和標準化版本可能是非常方便的資源。
  • 句子分割:正如我們在第3章中看到的那樣,句子分割可能比看起來更難。因此一些語料庫使用明確的註釋來標記句子分段。
  • 段落分割:段落和其他結構元素(標題,章節等)可能被明確註釋。
  • 言語部分:文檔中每個單詞的句法分類。
  • 句法結構:顯示句子組成結構的樹形結構。
  • 淺語義:命名實體和共同註釋,語義角色標籤。
  • 對話與話語:對話行爲標籤,修辭結構

一旦你打破一個文檔分成句子似乎很簡單。但是,你如何去分解那些來自維基百科頁面的HTML?我非常熟悉使用HTML/XML解析器並遍歷樹,我試圖剝離HTML標籤來獲取純文本,但是因爲在刪除HTML之後缺少標點符號,所以NLTK不會解析表格單元格,甚至正確列出。

是否有一些最佳做法或NLP解析這些東西的策略?或者你是否需要手動編寫特定於該單獨頁面的解析器?

只是在正確的方向尋找一些指針,真的想試試這個NLTK了!

+0

您是否嘗試過在剝離的文本中使用Punkt(它在NLTK中實現)以查看是否可以讓您獲得任何位置? – dmh

+1

我的非正式觀察是解析器通常在處理和表示顯示文本方面不好(而不是運行散文)。如果你找到或設計出一個好的解決方案,請在這裏跟進! – tripleee

回答

1

聽起來就像你剝離了所有的HTML並生成一個平面文檔,由於鬆散的碎片粘在一起,這會使解析器混淆。由於您對XML有豐富的經驗,因此建議將輸入映射到一個簡單的XML結構,以保持各個部分獨立。你可以儘可能地簡單,但也許你會想保留一些信息。例如,標題標題,章節標題等可能是有用的。當你有一個可操作的XML樹使塊保持獨立時,使用XMLCorpusReader將其導入到NLTK Universe中。

1

我必須編寫特定於我正在分析的XML文檔的規則。

我所做的是將html標籤映射到段。該映射基於研究多個文檔/頁面並確定html標籤所代表的內容。例如, <h1>是一個短語段; <li>是段落; <td>是令牌

如果您想使用XML,則可以將新映射表示爲標記。例如, <h1>至<短語>; <li>至<段落>; <TD>到<令牌>

如果你想在純文本的工作,你可以代表映射爲一組字符的(例如:[PHRASESTART] [PHRASEEND]),就像POS或EOS標識。

0

你可以使用像python-goose這樣的工具,它旨在從html頁面中提取文章。

否則,我做了以下的小程序,讓好樣的結果:

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

由於alexis回答,python-goose可能是一個不錯的選擇。

也有HTML Sentence Tokenizer,一個(新)圖書館,旨在解決這個確切的問題。它的語法非常簡單。在一行parsed_sentences = HTMLSentenceTokenizer().feed(example_html_one)中,您可以獲取存儲在數組parsed_sentences中的HTML頁面中的句子。