原题再现

​题目描述:​使用NLTK完成英文文本的基础预处理流程,具体要求:

(1)给定一段英文文本(如新闻、句子),完成以下步骤:

1)分句(将文本拆分为多个句子);

2)分词(将每个句子拆分为单词);

3)词性标注(给每个单词标注词性,如名词n、动词v等);

4)停用词过滤(移除英文停用词,如the/a/an等);

5)词形还原(可选拓展:将单词还原为原型,如running→run)。

(2)按清晰格式输出每一步的处理结果;

(3)代码需包含异常处理,避免因文本格式问题崩溃。

提示:确保下载所需语料(首次运行需执行,只执行一次,再次执行需注释)

测试文本:

预期输出:如图1所示
图1 NLTK基础文本预处理输出示例


参考代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import nltk
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk import pos_tag

# 确保下载所需语料(首次运行需执行)
# nltk.download('punkt')
# nltk.download('averaged_perceptron_tagger')
# nltk.download('stopwords')
# nltk.download('wordnet')
# nltk.download('omw-1.4')

def text_preprocessing(text):
try:
if not text or not isinstance(text, str):
raise ValueError("输入文本不能为空且必须为字符串格式。")

print("===== 1. 分句结果 =====")
sentences = sent_tokenize(text)
for i, sent in enumerate(sentences):
print(f"句子{i+1}: {sent}")

print("\n===== 2. 分词结果 =====")
all_tokens = []
for sent in sentences:
tokens = word_tokenize(sent)
all_tokens.extend(tokens)
print(f"「{sent}」-> {tokens}")

print("\n===== 3. 词性标注结果 (前10个) =====")
tagged_tokens = pos_tag(all_tokens)
for word, tag in tagged_tokens[:10]:
print(f"{word} -> {tag}")

print("\n===== 4. 停用词过滤结果 =====")
stop_words = set(stopwords.words('english'))
# 过滤掉标点符号和停用词,并转为小写以匹配
filtered_tokens = [w.lower() for w in all_tokens if w.isalpha() and w.lower() not in stop_words]
print(f"过滤前词数: {len(all_tokens)}, 过滤后: {len(filtered_tokens)}")
print(filtered_tokens)

print("\n===== 5. 词形还原结果 (拓展) =====")
lemmatizer = WordNetLemmatizer()
# 注意:简单的词形还原默认按名词处理,这里演示基础用法
lemmatized_tokens = [lemmatizer.lemmatize(w) for w in filtered_tokens]
print(lemmatized_tokens)

except Exception as e:
print(f"代码运行出错: {e}")

raw_text = """Natural language processing (NLP) is a subfield of artificial intelligence.
It focuses on enabling computers to understand and process human language.
NLTK is a popular library for NLP in Python, which provides many useful tools."""

if __name__ == "__main__":
text_preprocessing(raw_text)

逐块精析

模块导入


1
2
3
4
5
import nltk
from nltk.tokenize import sent_tokenize, word_tokenize # 导入分句和分词工具
from nltk.corpus import stopwords # 导入停用词词库
from nltk.stem import WordNetLemmatizer # 导入词形还原工具
from nltk import pos_tag # 导入词性标注工具
  • sent_tokenize: 能够智能识别句子边界(如区分 Inc. 中的点和句子结尾的点)。
  • word_tokenize: 将句子拆分为单词和标点符号。
  • stopwords: 包含如 “the”, “a”, “in” 等在分析语义时通常需要剔除的高频词。
  • WordNetLemmatizer: 词形还原器,能基于英语词典将单词恢复原形(如 went -> go)。

函数定义与异常处理

1
2
3
4
def text_preprocessing(text):
try:
if not text or not isinstance(text, str):
raise ValueError("输入文本不能为空且必须为字符串格式。")
  • try...except: 这是一个防御性编程习惯,防止因为输入了非文本内容(如数字或 None)导致整个程序崩溃。

本题已经给出了raw_text,原则上不会产生报错,为使代码严谨,补充该内容。

  • raise ValueError: 手动触发错误,并在下方 except 块中捕获。

步骤 1:分句 (Sentence Tokenization)

1
2
3
4
print("===== 1. 分句结果 =====")
sentences = sent_tokenize(text)
for i, sent in enumerate(sentences):
print(f"句子{i+1}: {sent}")
  • 逻辑: 将输入的 raw_text 字符串切分为一个字符串列表 sentences
  • 输出: 每一行代表一个独立的句子。

步骤 2:分词 (Word Tokenization)

1
2
3
4
5
6
print("\n===== 2. 分词结果 =====")
all_tokens = []
for sent in sentences:
tokens = word_tokenize(sent)
all_tokens.extend(tokens)
print(f"「{sent}」-> {tokens}")
  • all_tokens.extend(tokens): 将每个句子分词后的列表合并到一个大列表 all_tokens 中,方便后续统一处理。
  • 注意: 此时标点符号(如 .()也会被当作独立的 “token” 保留。

步骤 3:词性标注 (POS Tagging)

1
2
3
4
print("\n===== 3. 词性标注结果 (前10个) =====")
tagged_tokens = pos_tag(all_tokens)
for word, tag in tagged_tokens[:10]:
print(f"{word} -> {tag}")
  • pos_tag: 对 all_tokens 中的每个单词分配一个词性标签。
  • 常见标签: JJ (形容词), NN (名词), VBZ (动词单三), IN (介词)。

步骤 4:停用词过滤 (Stopwords Removal)

1
2
3
4
5
6
7
print("\n===== 4. 停用词过滤结果 =====")
stop_words = set(stopwords.words('english'))

filtered_tokens = [w.lower() for w in all_tokens if w.isalpha() and w.lower() not in stop_words]

print(f"过滤前词数: {len(all_tokens)}, 过滤后: {len(filtered_tokens)}")
print(filtered_tokens)
  • w.lower(): 统一转为小写,因为停用词表全是小写。
  • w.isalpha(): 检查字符是否全是字母。它会自动过滤掉 ( ) . , 等标点符号。
  • not in stop_words: 剔除掉无意义的常用词。

步骤 5:词形还原 (Lemmatization)

1
2
3
4
5
print("\n===== 5. 词形还原结果 (拓展) =====")
lemmatizer = WordNetLemmatizer()

lemmatized_tokens = [lemmatizer.lemmatize(w) for w in filtered_tokens]
print(lemmatized_tokens)
  • lemmatize(w): 将单词还原为基本形式。例如,它会将 tools 变为 tool
  • 局限性: NLTK 的 WordNetLemmatizer 默认将所有词视为名词。如果要更精准(如还原动词),需要传入词性参数。

程序入口

1
2
3
4
5
except Exception as e:
print(f"代码运行出错: {e}")

if __name__ == "__main__":
text_preprocessing(raw_text)
  • if __name__ == "__main__":: 确保该脚本在被直接运行时才会执行测试代码,被作为模块导入时则不会运行。