2012-06-30 24 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页面中的句子。