词频分析实战:jieba + nltk 双引擎,中英文词频词性一站搞定

词频分析是 NLP 最基础也最实用的工具——看用户天天在聊什么、竞品文案高频用词、专业领域术语识别。但中文和英文要的工具完全不一样:

老板们最常踩的坑:用错工具。给英文文本跑 jieba(不切空格)= 一个字母一个词;给中文跑 nltk(按空格分)= 整句算 1 个词。

我们的 词频分析软件 智能识别语言自动切换引擎:TXT/WORD/EXCEL 三种输入一键搞定。

一、词频分析能干什么?

二、中文词频:jieba 全流程

1. 基础词频

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
import jieba
from collections import Counter
import re

# 读 TXT
with open('zh_comments.txt', encoding='utf-8') as f:
texts = [line.strip() for line in f if line.strip()]

# 简单分词
words = []
for text in texts:
words.extend(jieba.lcut(text))

# 过滤:去掉标点、单字、停用词
stopwords = set(open('cn_stopwords.txt', encoding='utf-8').read().split())
filtered = [
w for w in words
if len(w) > 1
and w not in stopwords
and not re.match(r'^[\W\d]+$', w) # 不要纯标点/数字
]

# 统计
freq = Counter(filtered)
top50 = freq.most_common(50)

for word, count in top50:
print(f'{word:8s} {count:5d}')

2. 加自定义词典(重要!)

1
2
3
4
5
6
7
8
# 行业词典(品牌、型号、专业术语)
custom_words = [
'小米手机', '华为Mate60', 'iPhone15', '遥遥领先',
'国货之光', '智商税', '种草', '拔草', '退退退',
'绝绝子', 'yyds', '栓Q', '芭比Q'
]
for w in custom_words:
jieba.add_word(w, freq=10000) # freq 越大越不容易被切散

踩坑:不加载自定义词典,”华为 Mate60” 会被切成 “华为 / Mate / 60”,统计出 3 个无意义词。

3. 词性标注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import jieba.posseg as pseg

text = '小米手机续航不错,客服态度也挺好'
words = pseg.lcut(text)
for w, flag in words:
print(f'{w:8s} {flag}')
# 小米手机 n
# 续航 v
# 不错 a
# , x
# 客服 n
# 态度 n
# 也 d
# 挺好 a
# . x

jieba 词性对照表(常用):

flag 含义 flag 含义
n 普通名词 v 动词
a 形容词 d 副词
nr 人名 ns 地名
nt 机构名 nz 其他专名
r 代词 c 连词
p 介词 x 标点

业务用法:只要名词 + 形容词 → 关键词候选:

1
2
3
# 只要名词和形容词
keywords = [w for w, flag in pseg.lcut(text) if flag.startswith('n') or flag.startswith('a')]
# ['小米手机', '续航', '不错', '客服', '态度', '挺好']

三、英文词频:nltk 全流程

1. 基础词频

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
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from collections import Counter

# 第一次用要下载:nltk.download('punkt'); nltk.download('stopwords')
nltk.download('punkt', quiet=True)
nltk.download('stopwords', quiet=True)

with open('en_reviews.txt', encoding='utf-8') as f:
texts = [line.strip() for line in f if line.strip()]

# 1. 分词
tokens = []
for text in texts:
tokens.extend(word_tokenize(text.lower())) # 全部转小写

# 2. 过滤标点 + 停用词
stop_words = set(stopwords.words('english'))
filtered = [
w for w in tokens
if w.isalpha() # 只要字母(去标点数字)
and w not in stop_words # 去停用词
and len(w) > 2 # 至少 3 个字母
]

# 3. 统计
freq = Counter(filtered)
top50 = freq.most_common(50)
for word, count in top50:
print(f'{word:12s} {count:5d}')

2. 词形归一(lemmatization)

英文一个词有多种形式(run/ran/running/runs),统计时要把它们归一:

1
2
3
4
5
6
7
8
9
10
from nltk.stem import WordNetLemmatizer
nltk.download('wordnet', quiet=True)

lemmatizer = WordNetLemmatizer()

# 跑 / 跑了 / 跑步中 全部归一为 run
print(lemmatizer.lemmatize('running', pos='v')) # run
print(lemmatizer.lemmatize('ran', pos='v')) # run
print(lemmatizer.lemmatize('runs', pos='v')) # run
print(lemmatizer.lemmatize('better', pos='a')) # good

pos 参数:v=动词, n=名词, a=形容词, r=副词。

进阶版:用 nltk 词性标注自动确定 pos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from nltk.tag import pos_tag
nltk.download('averaged_perceptron_tagger', quiet=True)

def lemmatize_with_pos(text):
tokens = word_tokenize(text.lower())
tagged = pos_tag(tokens) # 词性标注
out = []
for word, tag in tagged:
if not word.isalpha() or word in stop_words or len(word) <= 2:
continue
# nltk 词性转 WordNet 词性
wn_tag = tag[0].lower()
wn_tag = wn_tag if wn_tag in 'nvars' else 'n'
lemma = lemmatizer.lemmatize(word, pos=wn_tag)
out.append(lemma)
return out

3. 英文词性

1
2
3
4
5
6
7
8
9
10
11
12
13
text = 'The quick brown fox jumps over the lazy dog'
tagged = pos_tag(word_tokenize(text))
for w, t in tagged:
print(f'{w:8s} {t}')
# The DT (限定词)
# quick JJ (形容词)
# brown JJ
# fox NN (名词)
# jumps VBZ (动词)
# over IN (介词)
# the DT
# lazy JJ
# dog NN

四、中英文混合文本

现实里很多文本是中英混合的(如产品评论、社交媒体)。策略:先识别语种,再分别处理

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
import re

def is_chinese(char):
return '\u4e00' <= char <= '\u9fff'

def split_zh_en(text):
"""把中英混合文本拆成中文段和英文段"""
segments = []
current = []
current_lang = None # 'zh' or 'en'
for char in text:
lang = 'zh' if is_chinese(char) else ('en' if char.isalpha() else None)
if lang is None:
# 标点空格等,跳过
continue
if current_lang is None or current_lang == lang:
current.append(char)
current_lang = lang
else:
segments.append((current_lang, ''.join(current)))
current = [char]
current_lang = lang
if current:
segments.append((current_lang, ''.join(current)))
return segments

text = '这个iPhone15手感很好,但是battery续航一般'
parts = split_zh_en(text)
# [('zh', '这个'), ('en', 'iPhone'), ('zh', '手感很好但是'), ('en', 'battery'), ('zh', '续航一般')]

# 分别处理
zh_words = []
en_words = []
for lang, segment in parts:
if lang == 'zh':
zh_words.extend(jieba.lcut(segment))
else:
en_words.extend(word_tokenize(segment.lower()))

print(zh_words) # ['这个', 'iPhone', '手感', '很好', '但是', '续航', '一般']
print(en_words) # ['iphone'] # battery 进了 zh_words 因为是夹在中文里

:纯字母但被中文包裹(如”这个iPhone手感”)会被当成中文处理。进阶用 langid 库做语种识别

1
2
3
4
5
6
# pip install langid
import langid
text = '这个iPhone手感很好'
print(langid.classify(text)) # ('zh', 0.99)
text2 = 'battery life is great'
print(langid.classify(text2)) # ('en', -126.7)

五、词性分析 + 词频组合拳

很多业务场景需要”特定词性”的高频词:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 场景1: 找竞品高频形容词(用于文案优化)
zh_adjectives = [w for w, flag in pseg.lcut('\n'.join(texts))
if flag == 'a' and len(w) > 1]
top_adjectives = Counter(zh_adjectives).most_common(20)
# 输出: [('不错', 234), ('好', 198), ('差', 156), ...]

# 场景2: 找竞品高频专有名词(用于品牌识别)
zh_proper_nouns = [w for w, flag in pseg.lcut('\n'.join(texts))
if flag in ('nr', 'ns', 'nt', 'nz')]
top_brands = Counter(zh_proper_nouns).most_common(20)
# 输出: [('小米', 234), ('华为', 198), ('北京', 156), ...]

# 场景3: 找高频动词(用于用户行为分析)
zh_verbs = [w for w, flag in pseg.lcut('\n'.join(texts))
if flag == 'v' and len(w) > 1]
top_actions = Counter(zh_verbs).most_common(20)
# 输出: [('买', 234), ('退', 198), ('换', 156), ...]

六、踩坑大全

1. nltk 数据包没下载LookupErrornltk.download('xxx') 解决。

2. 中文编码:读 TXT 时必须显式 encoding='utf-8',否则 Windows 默认 GBK 读中文会乱码。

3. WORD/EXCEL 读入:用 python-docx 读 .docx,用 pandas 读 .xlsx。

4. 停用词库:推荐使用哈工大停用词表(2000+ 词)+ 百度停用词表(1200+ 词),合并去重,覆盖率 95%。

5. 自定义词典冲突:jieba 词典冲突时 add_word(freq=10000) 不一定管用。可以用 jieba.suggest_freq('华为Mate60', tune=True) 让 jieba 自动调优。

6. 大文件处理:百万行评论不要一次性 extend,会爆内存。用生成器或 Counter.update 增量统计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def process_in_chunks(file_path, chunk_size=10000):
freq = Counter()
with open(file_path, encoding='utf-8') as f:
chunk = []
for line in f:
chunk.append(line.strip())
if len(chunk) >= chunk_size:
words = jieba.lcut(' '.join(chunk))
freq.update([w for w in words if len(w) > 1])
chunk = []
if chunk:
words = jieba.lcut(' '.join(chunk))
freq.update([w for w in words if len(w) > 1])
return freq

七、典型业务应用


我们的 词频分析软件 把上面所有代码封装成可视化界面:支持 TXT/WORD/EXCEL 三种输入格式,中英文自动识别,jieba/nltk 双引擎切换,一键输出词频表 + 词性表 + 词云图。支持自定义词库、停用词库——业务人员不用学 Python 也能做专业词频分析。