0.背景说明
前段时间cert举办的技术对抗赛上,提供了一个数据样本,全部是html文件。正好有个同事正在研究机器学习的文本分类,就琢磨的看看能不能提取到一些有用的样本信息。因为要提取文本,就想到需要一个好的html文本提取函数来进行。
通过上网查询,发现目前采用的方式有如下几种:
- Python-goose
- BeautifulSoup
- html2text
- nltk
- plaintext
下面就以下几种方式做一个初步的探索
1. 简单实验
- 首先是Python-goose,goose这个工原来是用Java写的文章提取工具,后来用python进行了重写,就形成了Python-goose。它不仅提取出文章的主体,同时提取出所有元信息以及图片等信息,支持中文网页。更多介绍看这里:点击这里传送。
话不多说,上一小段代码(注意这里只提取文本和标题):
def extract_text_by_goose(doc_text):
title, text = '', ''
g = Goose({'parser_class': 'lxml', 'stopwords_class': StopWordsChinese})
try:
article = g.extract(raw_html=doc_text)
except Exception as error:
print error
pass
else:
title = article.title
text = article.cleaned_text
return title, text
经过尝试,发现googse解析的信息不错,但是存在一个问题是,对于某些网站(图片、视频资源比较多)解析速度非常慢,甚至达到了不能容忍的地步。
- 其次是BeautifulSoup,这也是目前最主流和最大众的方法。
def extract_text_by_bs(doc_text):
"""提取html页面的所有文本信息。
参考:
http://stackoverflow.com/questions/328356/extracting-text-from-html-file-using-python
"""
title, text = '', ''
soup = BeautifulSoup(doc_text, 'lxml')
try:
for script in soup(["script", "style"]):
script.extract()
except Exception as error:
print error
pass
else:
try:
# get text
title = soup.title.string
except Exception as error:
print error
pass
text = soup.get_text()
lines = (line.strip() for line in text.splitlines())
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
text = ' '.join(chunk for chunk in chunks if chunk)
return title, text
进过尝试,这个方法解析的信息不错,并且速度还是比较快的。目前分析采用了这种方式。
3.html2text,这个是一个github项目点击这里传送。这个项目还是比较简单易用的,而且可以传入多种参数进行组合调整。
import html2text
def extract_text_by_h2t(doc_text):
h = html2text.HTML2Text()
h.ignore_links = True
h.bypass_tables = False
h.unicode_snob = False
text = h.handle(doc_text)
return text
经过尝试,这个方法对中文编码混乱的情况容错性没有BeautifulSoup好,会产生乱码的行为(可能是研究不到位)。
4.nltk,一个python的自然语言处理库,可以很方便的完成很多自然语言处理(NLP)的任务,包括分词、词性标注、命名实体识别(NER)及句法分析。非常知名,这里就不做过多描述了。
from nltk.tokenize import word_tokenize, sent_tokenize
def extract_text_by_nltk(doc_text):
tokens = [word for sent in sent_tokenize(doc_text) for word in word_tokenize(sent)]
return filter(lambda word: word not in ',-', tokens)
这是 stackoverflow上面人介绍到的一种方式,这个方法用的很普遍,这里也做了尝试,短期快速上手难度大,并且中文这方面需要一些其他库。时间上研究的比较少,有用过的可以指导一下。
5.pattern.web点击这里传送,这个库看文档说明很强大,包含了解析和爬取等等功能。
from pattern.web import plaintext
def extract_text_by_pattern(doc_text):
text = plaintext(doc_text)
return text
同第3个方法经过尝试,这个方法对中文编码混乱的情况容错性没有BeautifulSoup好,不过比html2text好一些,会产生乱码的行为(可能是研究不到位)。
3. 总结
通过上述实验,实际上,如果是进行简单的文本样本分析,无外乎希望两点:
- 容错性好
- 速度快
所以,实际上研究表明还是希望BeautifulSoup这种方式,但是实际生产中,可能上诉的几种库还有更高级的用法,所以也值得研究。另外,在网上看到一种用正则表达式去提取样本的方法,也是满足目前需求的,速度也还可以。
PS
本文只是一个简单的研究,并没有经过系统专业的测试,可能提到的观点有错误,还望能交流指出。
网友评论