用 Python 批量整理亚马逊关键词表格:去重、分组与导出 CSV 实战
做亚马逊运营,关键词表格几乎每周都要整理一次:从广告报表、搜索词报告、竞品标题里导出的词少则几百,多则上万。词和词之间长得很像——大小写不同、多了个空格、单复数不同、词序调换,人工去重既慢又容易漏;不分组就更没法用,几千个词堆在一起,分不清哪些是核心大词、哪些是长尾修饰词,也不知道该放进标题、五点描述还是广告活动里。
这篇文章讲一个能直接落地的办法:用 Python 把这件事做成一条流水线,输入一份原始关键词表格,输出一份干净、去重、分组好的 CSV。整个过程不需要装复杂的工具,标准库加一个 pandas 就够了,跑一次几秒钟,逻辑讲清楚之后,照着改一改就能用在自己的类目上。
先说整体思路,一共五步:第一步读入原始表格,不管它是 Excel 还是 CSV;第二步做规范化清洗,把大小写、空格、标点这些表面差异先抹平;第三步按规范化后的词去重,同时把被合并掉的原始词和它的搜索量、订单量等数据保留下来;第四步按规则分组,常见的分法是核心词、属性词、场景词和长尾词;第五步按分组导出 CSV,文件名和列顺序固定,方便下次直接复用。
我们先看一份典型的原始数据长什么样。假设从后台导出的表格有四列:关键词、搜索量、点击量、转化率。举几个真实会遇到的问题:同一行里出现“wireless earbuds”“Wireless Earbuds”“ wireless earbuds ”,这三行其实是同一个词;“bluetooth earphones” 和 “bluetooth earphone” 只有单复数差别,搜索意图基本一致;“earbuds for running” 和 “running earbuds” 词序不同,但用户想找的东西是一样的。如果不做处理,直接拿去投广告,同一个词会被重复出价,预算就白白分流了。
所以第一条原则是:在动手写代码之前,先把原始文件原样备份一份,输出永远写到新文件里。这样即使清洗规则调错了,也能随时从头再来。第二条原则是:去重只删“重复的表达”,不要删“重复的意图”,比如 “waterproof earbuds” 和 “water resistant earbuds” 虽然意思接近,但搜索量和转化表现可能差很多,这类词应该进入分组环节人工复核,而不是被程序悄悄合并掉。
一、准备工作:先把环境和文件理顺
开始之前只做两件事。第一,装好 Python 3.10 以上版本和 pandas,命令行执行 pip install pandas openpyxl 即可,openpyxl 是用来读 Excel 的;如果只需要处理 CSV,连 openpyxl 都可以不装,只用 Python 自带模块也够。第二,把原始文件放进一个固定文件夹,比如 keywords/raw/,输出放到 keywords/output/,并在文件名里带上日期,例如 keywords_20261112_raw.xlsx,这样每次整理都能按日期追溯,不会把新旧文件搞混。
读文件时最容易踩的坑是编码和表头。亚马逊后台导出的 CSV 有时是带 BOM 的 UTF-8,有时是 GBK,直接用默认编码读会报 UnicodeDecodeError,或者中文变成乱码。稳妥的做法是先尝试 utf-8-sig,失败再试 gbk;Excel 则直接用 pandas 的 read_excel,表头行不一定是第一行,先打开文件看一眼,确认关键词列到底叫“关键词”“Search Term”还是“Customer Search Term”,再在代码里写死列名。
下面这段代码就是整个流水线的起点,只做一件事:把原始表格读进来,统一列名,去掉完全空白的行。
import pandas as pd
def load_keywords(path):
if path.endswith('.csv'):
try:
df = pd.read_csv(path, encoding='utf-8-sig')
except UnicodeDecodeError:
df = pd.read_csv(path, encoding='gbk')
else:
df = pd.read_excel(path, engine='openpyxl')
df.columns = [str(c).strip() for c in df.columns]
df = df.dropna(how='all')
return df
df = load_keywords('keywords/raw/keywords_20261112_raw.xlsx')
print(df.shape)
print(df.columns.tolist())
打印形状和列名这一步别省。表格大了之后,最常见的错误不是算法错,而是列名里多了个空格、关键词列被读成了数字,导致后面整段逻辑都在空跑。先看到行数和列名对得上,再往下走。
二、规范化清洗:先把“长得不一样”的词变成“同一个词”
去重之前必须先规范化,否则程序根本认不出 “Wireless Earbuds” 和 “wireless earbuds” 是同一个词。规范化的规则要写成一个函数,所有关键词都过一遍这个函数,得到一个新列 norm_keyword,后面所有的去重和分组都以它为准,原始词原样保留在另一列里,方便随时回查。
一个够用的规范化函数通常做五件事:转小写;去掉首尾和多余的中间空格;把全角标点和特殊符号统一成半角或空格;去掉首尾的连字符和多余标点;处理常见的单复数,例如词尾的 s 在特定词上可以去掉,但要留一个例外表。单复数这一步最容易过度处理,比如 “glass” 去掉 s 就变了意思,“class” 也一样,所以我的做法是只处理一份很小的、自己类目里确认过的词尾规则,例如 earbuds、earphones、headphones 这类词,其余一律不动,宁可少合并,也不多错杀。
import re
PLURAL_OK = {'earbuds', 'earphones', 'headphones', 'cases', 'covers'}
def normalize(kw):
s = str(kw).strip().lower()
s = re.sub(r'\s+', ' ', s)
s = re.sub(r'[^a-z0-9\s\-]', ' ', s)
s = re.sub(r'\s+', ' ', s).strip(' -')
words = []
for w in s.split(' '):
if w.endswith('s') and w in PLURAL_OK:
w = w[:-1]
words.append(w)
return ' '.join(words)
df['norm_keyword'] = df['关键词'].apply(normalize)
这里还有一个容易被忽略的细节:词序。像 “earbuds for running” 和 “running earbuds” 这种词序不同的词,严格说不是同一个字符串,但对运营来说意图高度重合。我的做法是不在规范化阶段动词序,而是单独加一个“排序后关键词”列,把词按字母排序后拼接,只用来发现候选重复,把候选名单导出来人工看一眼再决定合并不合并。机器负责找候选,人负责拍板,准确率比全自动高得多。
三、去重:合并重复行,但别把数据丢了
规范化之后去重本身只有一行代码:按 norm_keyword 分组。但直接 drop_duplicates 有一个毛病——被删掉的那些行可能带着更高的搜索量或订单,粗暴删除等于丢数据。正确的做法是先聚合再去重:同一个规范化关键词对应多行时,搜索量和点击量取最大值或求和,原始写法用分号拼在一起,转化率取加权平均,最后只留一行。这样既消灭了重复,又保留了全部信息,事后还能查到每个词都是从哪些写法合并来的。
agg = df.groupby('norm_keyword').agg(
原始关键词=('关键词', lambda x: '; '.join(sorted(set(x)))),
搜索量=('搜索量', 'max'),
点击量=('点击量', 'sum'),
出现次数=('关键词', 'count'),
).reset_index()
agg = agg.sort_values('搜索量', ascending=False)
print(f'去重前 {len(df)} 行,去重后 {len(agg)} 行')
这里搜索量取最大值而不是求和,是因为同一关键词在不同报表里出现时,搜索量是同一个时间段的统计值,相加会虚高;点击量求和则是因为广告报表里的点击是分渠道累计的。每一列怎么聚合没有统一答案,关键是先想清楚这个数字的业务含义再决定。打印去重前后的行数也很重要:正常情况下重复率在百分之十到三十之间,如果一行都没减少,说明规范化规则没生效;如果减少了一半以上,就要抽查是不是规则太激进,把本来不同的词也合并了。
四、分组:让词表变成能直接用的投放结构
去重后的词表仍然是一张大表,下一步是分组。分组的规则应当来自你的产品和使用场景,而不是凭感觉贴标签。以耳机类目为例,一套能直接用的分组是四类:核心词,例如 wireless earbuds、bluetooth earphones,这些词搜索量大、竞争也大,适合放在标题和核心广告活动里;属性词,例如 waterproof、noise cancelling、long battery,这些词描述产品特点,适合放进五点描述和卖点文案;场景词,例如 for running、for gym、for work,描述用户的使用场景,适合用来写场景化文案和做长尾广告组;长尾词,例如 best wireless earbuds under 50,词很长、搜索量小,但转化意图明确,适合单独建低价长尾广告活动。
实现时用一张关键词词典加规则匹配就够了,不需要机器学习。先定义每个分组的触发词,再写一个函数按优先级打标签:先看是不是长尾,长尾的判断标准是词数大于等于四个;再看是否包含属性词或场景词;最后剩下的、词数最短的就是核心词。
ATTR_WORDS = ['waterproof', 'noise cancelling', 'wireless', 'bluetooth']
SCENE_WORDS = ['running', 'gym', 'work', 'sleep', 'travel']
def group_kw(kw):
words = kw.split(' ')
if len(words) >= 4:
return '长尾词'
if any(w in kw for w in SCENE_WORDS):
return '场景词'
if any(w in kw for w in ATTR_WORDS):
return '属性词'
return '核心词'
agg['分组'] = agg['norm_keyword'].apply(group_kw)
print(agg['分组'].value_counts())
分组完成后一定要看各组的词数分布和搜索量总和。健康结构通常是核心词少而精,占搜索量的大头;属性词和场景词数量适中;长尾词数量最多,但单个词搜索量很小。如果某一组是空的,或者九成词都被打成同一组,说明词典里缺了这个类目的关键触发词,补上之后重新跑一遍就行,整个流程改起来成本很低。
五、导出 CSV:这一步决定表格能不能直接用
分组完成后导出很简单,但有三个细节决定导出的文件能不能被同事和 Excel 正常打开。第一是编码,一定要用 utf-8-sig 而不是 utf-8,带 BOM 的文件用 Excel 打开中文才不会乱码;第二是列顺序,把分组放在第一列,然后是规范化关键词、原始关键词、搜索量、点击量、出现次数,这样按分组排序后一眼就能看到每组的核心词;第三是按分组和搜索量排序导出,同一个分组的词排在一起,投放的时候可以直接按组复制到广告活动里。
out = agg[['分组', 'norm_keyword', '原始关键词', '搜索量', '点击量', '出现次数']]
out = out.rename(columns={'norm_keyword': '关键词', '出现次数': '合并原始词数'})
out = out.sort_values(['分组', '搜索量'], ascending=[True, False])
out.to_csv('keywords/output/keywords_20261112_clean.csv',
index=False, encoding='utf-8-sig')
print(out.head(10).to_string(index=False))
导出前先打印前十行看一眼,确认列名是中文、没有多余的索引列、分组齐全。之后这份 CSV 可以直接当作广告投放的词表,也可以再导回 Excel 做透视表,按分组统计每组的词数和搜索量占比。
六、上线前的检查清单与常见坑
把整套流程固化下来之后,每次整理只需要核对一张清单:原始文件是否已备份;关键词列名是否对得上;去重率是否在合理区间,一般是百分之十到三十;每个分组是否都有词,有没有九成词都挤进同一组;导出文件的编码是否为 utf-8-sig;导出后有没有用 Excel 打开验证一次中文是否正常。
最后说几个新手最容易踩的坑。第一个是直接在原文件上改,结果规则写错了连后悔的余地都没有,记住只读原始文件、只写新文件。第二个是把单复数处理做得太激进,合并了不该合并的词,单复数只放白名单,不放通用规则。第三个是搜索量求和,把同一个词在不同报表里的搜索量加了两遍,导出前按分组汇总核对一次总搜索量。第四个是完全不复核词序候选,机器找出来的词序相近的词一定要人工看一眼再合并。第五个是导出后不验证编码,文件发给别人打不开才发现是乱码。
这套办法的价值不在于代码有多复杂,而在于流程固定:每周导一次原始表,跑一次脚本,得到一份结构稳定的干净词表。词表干净了,广告分组、标题优化和五点描述才有可靠的依据。先把规则词典按自己的类目补齐,再把这段脚本存成固定模板,下次整理关键词,十分钟就能完成以前一下午的工作。
- 点赞
- 收藏
- 关注作者
评论(0)