第三章:处理原始文本

最重要的文本资源无疑是web上的文本,直接利用现成的文本集合来进行探索固然是很方便(就像前几章使用nltk自带的语料库一样),但是你脑海中很可能已经有了想要使用的文本资源,并且需要学习如何去获取它们。

本章的目标是回答如下几个问题:

  1. 我们如何编程去获取本地文本资源和网络文本资源,以便我们能够利用无限多的语言/文本资源?
  2. 我们如何把文档切分成一个个独立的单词和标点符号,以便我们可以像前几章那样对文本做一些分析?
  3. 我们如何编程去生成一些格式化的输出,并且把输出保存到文件中?

为了解决上述问题,我们将会接触到NLP的关键概念,包括分词(tokenization)和剪枝(stemming,也即词干提取)。同时你也将会巩固你的Python相关知识并且学习字符串处理、文件处理和正则表达式。由于很多web文本是以HTML格式存放的,我们也会了解如何清理HTML标记符。


Note

重要:从本章开始,我们所有程序样例都假定你已经事先导入了如下包/模块:

>>> from__future__ import division #该条导入语句仅限python 2

>>> import nltk, re, pprint

>>> from nltk import word_tokenize


3.1 从Web和磁盘获取文本

电子书

古滕堡项目的一小部分样例文本出现在了NLTK的语料库集合中,但是你可能对分析古滕堡项目的其他文本感兴趣。你可以在http://www.gutenberg.org/catalog/ 浏览25,000本免费电子书,也可以获得对应改电子书的文本文件(编码是ASCII)的URL。尽管古滕堡项目的90%的文本是英文文本,但是事实上它包含了超过50种语言的素材,包括加泰罗尼亚语、中文、荷兰语、芬兰语、法语、德语、葡萄牙语和西班牙语等等(每种大概有超过100个文本)。

第2554号文本是《罪与罚》的英文译本,我们可以像下面这样获取该文本:

译者注:原文中提供的url已经不能使用了,需要替换成如下url:http://www.gutenberg.org/files/2554/2554-0.txt


Note:read()函数需要花费几秒钟去下载该文件。如果正在使用网络代理(没有被python识别出来的话),在进行urlopen之前,你可能需要手去指定这个代理,像下面这样:


变量raw是一个含有1,176,893个字符的字符串。(通过type(raw)我们可以看到raw是一个字符串。)这是这本书的原始内容,包含了诸如空白符、换行符和空行等我们并不感兴趣的内容。请注意,文件中行尾的\r\n,这是Python用来显示特殊的回车和换行字符的方式(这个文件一定是在Windows 机器上创建的)。为了处理该语言文本,我们要将字符串分解为词和标点符号。这个步骤被称为分词(tokenization),它会生产我们所熟悉的列表结构,即一个词汇和标点符号的列表。

请注意,上面的分词需要用到nltk库,但是之前的操作(比如打开一个URL、读取内容到字符串中)都没有用到nltk。如果我们进一步从上面得到的列表tokens(包含单词和标点符号)来创建一个NLTK 文本NLTK Text,NLTK库自定义的一种数据类型),我们就可以进行很多前几章演示的语言学处理操作,同时也包含常规的列表可以进行的操纵(比如切片):

请注意,'Project Gutenberg'在上面的输出中以一个固定搭配的形式出现。这是因为从古腾堡项目下载的每个文本都包含一个首部,里面有文本的名称、作者、扫描和校对文本的人的名字、许可证等信息,有时这些信息也可能出现在文件末尾处。我们很难让程序自动自动识别出正文内容从哪里开始、又在哪里结束,因此在修剪(trimming)原始文本raw以得到不掺杂其他内容的正文内容之前,我们需要手工检查文件以发现标识正文内容开始和结束的独特的字符串:

上面的方法find()rfind()(reverse find,即“反向查找”)帮助我们找到了给字符串切片需要用到的索引值。我们用这个切片重新给raw赋值,所以现在raw包含从“PART I”开始一直到(但不包括)标记内容结尾的句子文本。

译者注:上面rfind()的参数‘End of Project Gutenberg‘s Crime’中s前面的单引号是中文单引号(很奇怪的一点)。

这是我们第一次接触到Web的实际情况:在Web上找到的文本可能含有不必要的内容,并没有一个自动的方法来去除它。但只需要少量的额外工作,我们就可以提取出所需要的文本材料。

处理HTML

网络上的文本大部分是HTML文件的形式。你可以使用浏览器将网页作为文本保存为本地文件,然后按照后面关于文件的小节描述的那样来访问它。不过,如果你要经常这样做,最简单的办法是直接让Python来做这份工作。第一步是像以前一样使用urlopen。为了有意思一点,我们将挑选标题为“Blondes to die out in 200 years”的BBC新闻故事,这是一个作为确立的科学事实被BBC流传下来的都市传奇:

译者注:不幸的是,在国内很可能无法正常访问BBC的网站,但是你可以选择其他的Web页面进行试验,比如网易、新浪、百度等等。

通过输入print(html)可以看到html的全部内容,包括meta元标签、图像映射、JavaScript代码、表单和表格等等。

要从HTML格式的文件中得到文本内容,我们可以使用一个叫做BeautiSoup的Python库,这个库的获取地址是:http://www.crummy.com/software/BeautifulSoup/

这样的得到的结果仍然含有我们不感兴趣的内容(比如网页导航文本和相关故事文本),但是通过几次尝试,可以找到正文内容的起始点和终止点,然后就可以像上面介绍的那样挑选出感兴趣的正文部分了。

处理搜索引擎的检索结果

Web可以被看作一个超大型的未经标注的文本语料库。网络搜索引擎可以高效地搜索大量文本作为相关的语言学例子。搜索引擎的主要优势是规模:因为在这样一个庞大的文档集合中,你会更容易找到你感兴趣的语言学模式。而且,使用非常特定的模式,在可能较小的文档范围内仅仅只能匹配一两个例子,但在Web上可能匹配成千上万的例子。网络搜索引擎的第二个优势是容易使用。因此它是一个用来快速检查一个理论是否合理的方便工具。

表3.1是如下固定搭配的Google检索命中数:纵坐标的单词在前,横坐标的单词在后,比如“absolutely adore“、“definitely like”等(Liberman, in LanguageLog, 2005):

不幸的是,搜索引擎有一些显著的缺点。首先,被允许的搜索模式的范围受到严格限制。不同于本地语料库,你可以编写程序来搜索任意复杂的模式,搜索引擎一般只允许你搜索单个词或一串词,有时也允许使用通配符。其次,搜索引擎给出的结果不具有一致性,并且在不同的时间或在不同的地理区域会给出非常不同的结果,当内容在多个站点重复时,搜索结果会增加。最后,搜索引擎返回的结果中的标记符可能会不可预料地改变,改变之后原来的基于模式来定位特定内容的方法将无法使用(通过使用搜索引擎的API可以改善这个问题)。

译者注:由于网站更新或改版等原因会更改很多HTML标记符的结构,导致之前写的目标文本提取程序失效。


Note:利用搜索引擎搜索"the of"(有英文引号),基于搜索结果,我们能否得出'the of'是英语中的一个常用固定搭配?


results matching ""

    No results matching ""