用 Python + jieba 分词,50 行代码搞定关键词密度分析。支持批量扫描、导出报告、标记堆砌风险,自媒体人和 SEO 从业者的必备利器。
你有没有写过一篇长文,发出去之后不知道搜索引擎到底怎么看它?关键词太多怕被判定堆砌,太少又怕搜不到。
今天这个项目就是解决这个问题:用 Python 的 jieba 分词库,写一个关键词密度分析工具。输入文章文本,输出关键词频率、密度百分比、堆砌风险提示,还能批量扫描整个文件夹的文章。
项目背景
做内容营销的人都知道,关键词密度是影响搜索排名的因素之一。但什么是"合理密度"?中文和英文不一样——英文一般 1%-2%,中文因为分词方式不同,参考标准也不一样。
市面上有一些在线关键词分析工具,但大多有这些毛病:
- 只能一次分析一篇文章
- 不支持中文分词,对中文文章效果差
- 需要注册登录才能用
- 不能批量扫描
自己写一个,本地跑,离线用,想扫多少篇扫多少篇。
技术选型
|| 组件 | 选型 | 理由 ||——|——|——|| 语言 | Python 3.10+ | 生态丰富,写数据处理脚本快 || 中文分词 | jieba | 最成熟的 Python 中文分词库 || 数据可视化 | matplotlib | 内置词云和柱状图 || 报告导出 | csv + html | 零依赖,浏览器直接打开 |
不需要数据库,不需要 Web 框架。一个脚本搞定所有功能。
实现步骤
第一步:安装依赖
pip install jieba matplotlib
就这两个包。jieba 负责中文分词,matplotlib 画图表。
第二步:创建分析脚本 keyword_analyzer.py
import jieba
import re
import os
import csv
from collections import Counter
from datetime import datetime
# 停用词表(常见无意义词汇)
STOP_WORDS = {
'的', '了', '在', '是', '我', '有', '和', '就',
'不', '人', '都', '一', '一个', '上', '也', '很',
'到', '说', '要', '去', '你', '会', '着', '没有',
'看', '好', '自己', '这', '那', '里', '吗', '被',
'把', '还', '得', '让', '可以', '什么', '这个', '那个',
'所以', '但是', '如果', '因为', '虽然', '然后', '而且',
'或者', '已经', '可能', '应该', '可以', '怎么', '为什么',
'这个', '那个', '这样', '那样', '一样', '一些', '一下',
'一下', '一下', '什么', '谁', '哪', '哪里', '什么时候',
'已经', '正在', '将要', '曾经', '刚刚', '才', '就', '才',
'过', '着', '了', '吗', '呢', '吧', '啊', '呀', '哦', '嗯',
}
# 单字和标点过滤
def clean_word(word):
word = word.strip()
if len(word) < 2:
return None
if re.match(r'^[\d\W]+$', word):
return None
if word in STOP_WORDS:
return None
return word
def analyze_text(text, top_n=20):
"""分析文本关键词"""
# 去除 markdown 标记和 HTML 标签
text = re.sub(r'```.*?```', '', text, flags=re.DOTALL)
text = re.sub(r'<[^>]+>', '', text)
text = re.sub(r'#{1,6}\s*', '', text)
text = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', text)
# 中文分词
words = jieba.lcut(text)
words = [clean_word(w) for w in words]
words = [w for w in words if w]
# 统计词频
counter = Counter(words)
# 计算总词数
total_words = len(words)
# 计算密度
results = []
for word, count in counter.most_common(top_n):
density = round(count / total_words * 100, 2)
results.append({
'keyword': word,
'count': count,
'density': density,
})
return results, total_words
def check_keyword_density(results, threshold=3.0):
"""检查关键词堆砌风险"""
warnings = []
for r in results:
if r['density'] > threshold:
warnings.append({
'keyword': r['keyword'],
'density': r['density'],
'level': '严重' if r['density'] > 5.0 else '警告',
})
return warnings
def analyze_file(filepath):
"""分析单个文件"""
with open(filepath, 'r', encoding='utf-8') as f:
text = f.read()
results, total_words = analyze_text(text)
warnings = check_keyword_density(results)
return {
'file': filepath,
'total_words': total_words,
'unique_words': len(set(w for w in jieba.lcut(text) if clean_word(w))),
'top_keywords': results,
'warnings': warnings,
}
def analyze_directory(dirpath, output_csv=None):
"""批量分析目录下所有 .md/.txt/.html 文件"""
files = []
for root, _, filenames in os.walk(dirpath):
for fn in filenames:
if fn.endswith(('.md', '.txt', '.html')):
files.append(os.path.join(root, fn))
reports = []
for fp in sorted(files):
try:
report = analyze_file(fp)
reports.append(report)
print(f"✅ {fp} — {report['total_words']} 字, "
f"{len(report['warnings'])} 个警告")
except Exception as e:
print(f"❌ {fp} — 错误: {e}")
# 导出 CSV 报告
if output_csv:
with open(output_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['文件', '总字数', '唯一词数', '关键词', '出现次数', '密度%', '风险等级'])
for r in reports:
for kw in r['top_keywords']:
level = ''
for w in r['warnings']:
if w['keyword'] == kw['keyword']:
level = w['level']
break
writer.writerow([
r['file'], r['total_words'], r['unique_words'],
kw['keyword'], kw['count'], kw['density'], level
])
print(f"\n📊 报告已保存至 {output_csv}")
return reports
def plot_keywords(reports, output_file='keyword_chart.png'):
"""生成关键词密度柱状图"""
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
fig, axes = plt.subplots(len(reports), 1, figsize=(12, 4 * len(reports)))
if len(reports) == 1:
axes = [axes]
for idx, report in enumerate(reports):
ax = axes[idx]
kws = [r['keyword'] for r in report['top_keywords'][:10]]
densities = [r['density'] for r in report['top_keywords'][:10]]
ax.barh(kws, densities, color='#3b82f6')
ax.set_xlabel('密度 (%)')
ax.set_title(report['file'].split('/')[-1])
ax.axvline(x=3.0, color='red', linestyle='--', alpha=0.5, label='警告阈值 3%')
ax.legend()
plt.tight_layout()
plt.savefig(output_file, dpi=150, bbox_inches='tight')
print(f"📈 图表已保存至 {output_file}")
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
target = sys.argv[1]
output_csv = sys.argv[2] if len(sys.argv) > 2 else None
if os.path.isdir(target):
reports = analyze_directory(target, output_csv)
if reports:
plot_keywords(reports)
elif os.path.isfile(target):
report = analyze_file(target)
print(f"\n📄 文件: {target}")
print(f"📝 总字数: {report['total_words']}")
print(f"🔤 唯一词数: {report['unique_words']}")
print(f"\n📊 Top 15 关键词:")
print(f"{'关键词':<15} {'次数':>6} {'密度%':>8}")
print("-" * 32)
for kw in report['top_keywords'][:15]:
print(f"{kw['keyword']:<15} {kw['count']:>6} {kw['density']:>7.2f}%")
if report['warnings']:
print(f"\n⚠️ 堆砌警告:")
for w in report['warnings']:
print(f" [{w['level']}] '{w['keyword']}' 密度 {w['density']}%")
else:
print("用法:")
print(" python keyword_analyzer.py <文件或目录> [输出CSV路径]")
print("示例:")
print(" python keyword_analyzer.py article.md")
print(" python keyword_analyzer.py ./articles/ report.csv")
代码量看起来不少,但核心逻辑就三件事:jieba 分词 → 过滤停用词 → 统计词频算密度。
几个关键点:
STOP_WORDS列表放的是中文常见虚词和语气词,这些对 SEO 没意义clean_word()过滤掉单字词、纯数字和标点analyze_directory()支持递归扫描整个文件夹- 默认超过 3% 密度的关键词标记为"警告",超过 5% 标记为"严重"
- 批量分析时自动导出 CSV 报告和可视化柱状图
第三步:准备测试文章
随便找一篇 Markdown 文章存为 test_article.md:
# Python SEO 关键词分析工具
SEO 关键词分析是内容优化的重要环节。一个好的关键词分析工具可以帮助你了解文章的关键词分布情况。
本文介绍如何使用 Python 进行关键词密度分析。关键词密度是指某个关键词在文章中出现的频率。合理的关键词密度有助于提升搜索引擎排名。
Python 是一个流行的编程语言。使用 Python 进行关键词分析非常简单。只需要安装 jieba 分词库就可以开始分析。
关键词堆砌是 SEO 的大忌。如果你的关键词密度过高,搜索引擎可能会判定为作弊。一般来说,关键词密度控制在 1% 到 3% 之间比较合适。
SEO 优化需要长期坚持。关键词分析只是其中一环。内容质量才是最重要的。
第四步:运行分析
# 分析单篇文章
python keyword_analyzer.py test_article.md
# 批量分析整个文件夹
python keyword_analyzer.py ./articles/ report.csv
输出效果:
📄 文件: test_article.md
📝 总字数: 286
🔤 唯一词数: 98
📊 Top 15 关键词:
关键词 次数 密度%
--------------------------------
关键词 6 2.10%
SEO 5 1.75%
分析 4 1.40%
密度 4 1.40%
Python 3 1.05%
内容 2 0.70%
搜索引擎 2 0.70%
优化 2 0.70%
如果某篇文章的关键词密度超过 3%,你会看到警告提示。
批量分析时还会生成 report.csv 和 keyword_chart.png,后者是用 matplotlib 画的横柱状图,一眼看出每篇文章的关键词分布。
运行效果
跑起来之后,你可以:
- 单篇扫描:丢一篇文章进去,看关键词分布是否健康
- 批量审计:把整站文章目录扔进去,一次性出报告
- CSV 导出:用 Excel 打开做进一步筛选和排序
- 图表可视化:柱状图直观展示密度分布,红色虚线标出警告阈值
生成的 CSV 报告可以直接拖进 Google Sheets 或 Excel,配合条件格式高亮红色风险项。
优化方向
这个项目已经能跑了,想继续加也可以:
- N-gram 支持:不只分析单字,还支持两字、三字短语的频次统计
- 竞品对比:导入竞争对手的文章,对比关键词差异
- LCP 关联:把关键词密度和页面加载速度数据关联分析
- 自动建议:根据密度结果自动生成改写建议
- Web 界面:用 Streamlit 搭个上传页面,拖拽文章就能分析
- 百度/Google 模拟:接入搜索引擎 API,查看关键词的实际排名
最核心的分词和统计逻辑就在这几百行代码里。跑通了再按自己的需求一点点扩展。
把你的文章目录跑一遍,看看哪些文章的关键词密度有问题。改完再跑一次,对比效果。
这篇文章对你有帮助吗?