首页
Search
1
解决 docker run 报错 oci runtime error
49,608 阅读
2
WebStorm2025最新激活码
28,204 阅读
3
互点群、互助群、微信互助群
23,060 阅读
4
常用正则表达式
21,664 阅读
5
罗技鼠标logic g102驱动程序lghub_installer百度云下载windows LIGHTSYNC
20,036 阅读
自习室
互通有无
搞钱日记
养生记
包罗万象
Search
标签搜索
职场副业
职业发展
副业赚钱
后端开发
内容创作
微服务
分布式系统
效率提升
DevOps
技能提升
流量变现
性能优化
云原生
高并发
编程学习
深度学习
人工智能
架构设计
机器学习
前端开发
loong
累计撰写
3,206
篇文章
累计收到
4
条评论
首页
栏目
自习室
互通有无
搞钱日记
养生记
包罗万象
页面
搜索到
1
篇与
的结果
2026-05-31
Python自动化脚本处理SEO批量数据实战教程:从关键词清洗到页面审计,新手也能跟做
欢迎来到本教程,今天我们将学习如何用 Python 自动化脚本处理 SEO 批量数据。如果你做过关键词整理、页面标题检查、Meta Description 缺失排查,应该很熟悉这种场景:几千行 CSV 数据摆在面前,Excel 能做,但做着做着就开始卡;筛选条件一多,公式复制错一格,结果就不可信;下周再来一批新数据,又要重复一遍。坦白讲,SEO 数据处理最烦人的不是难,而是重复、琐碎、容易出错。Python 的价值就在这里:它不替你做 SEO 判断,但可以把清洗、合并、去重、分类、检测、导出报告这些机械动作稳定地跑完。本教程适合初级到中级学习者。你不需要成为 Python 工程师,只要能看懂基础代码,就可以跟着这个步骤做出一个可复用的 SEO 批量数据处理脚本。你将学会什么完成本教程后,你会得到一个完整的小项目,能够处理常见 SEO 数据:批量读取关键词 CSV、页面抓取 CSV、排名数据 CSV清洗关键词空格、大小写、重复项识别标题过长、标题缺失、描述缺失等页面问题根据关键词意图做简单分类合并多份 SEO 数据,生成可阅读的 Excel 报告把脚本整理成以后可以反复使用的工具这里有个重要提醒:自动化脚本不是魔法。它能帮你提升效率,但判断某个页面是否值得优化、关键词是否有商业价值,仍然需要你的 SEO 经验。我们要做的是把时间从重复劳动里拿回来,留给真正需要判断的部分。前置准备:确保你已经装好这些工具开始之前,你需要准备:Python 3.10 或更高版本一个代码编辑器,推荐 VS Code基础命令行操作能力几份 CSV 文件,例如关键词表、URL 抓取表、排名表如果你还没有安装依赖,打开终端,在项目文件夹里执行:pip install pandas openpyxl本教程主要使用 pandas。它是处理表格数据非常常用的 Python 库,适合 CSV、Excel、批量清洗、数据合并等任务。建议你创建这样的项目结构:seo-python-demo/ ├── data/ │ ├── keywords.csv │ ├── pages.csv │ └── rankings.csv ├── output/ └── seo_batch_report.py你可以把 data 理解成原始数据区,output 理解成结果区,seo_batch_report.py 是我们要编写的脚本。示例数据应该长什么样为了方便学习,我们先约定三份文件的字段。你不一定要完全一样,但字段名越规范,脚本越容易维护。keywords.csv:关键词数据keyword,volume,difficulty python seo,500,35 seo automation,300,42 python seo,500,35 SEO Python Tutorial,150,28pages.csv:页面抓取数据url,title,meta_description,h1,status_code https://example.com/python-seo,Python SEO Guide,Learn Python SEO automation,Python SEO,200 https://example.com/old-page,,Old content page,Old Page,200 https://example.com/error-page,Error Page,,Error,404rankings.csv:排名数据keyword,url,position python seo,https://example.com/python-seo,8 seo automation,https://example.com/python-seo,15 python tutorial,https://example.com/python-tutorial,22真实工作里的数据通常更乱:字段名不统一、URL 带参数、关键词前后有空格、大小写混在一起。下一步很关键,我们先把这些脏数据清洗干净。步骤一:读取 CSV,并做基础检查在 seo_batch_report.py 中写入下面的完整代码。先不要急着加复杂逻辑,第一步只做读取和检查。from pathlib import Path import pandas as pd BASE_DIR = Path(__file__).resolve().parent DATA_DIR = BASE_DIR / 'data' OUTPUT_DIR = BASE_DIR / 'output' OUTPUT_DIR.mkdir(exist_ok=True) keywords_path = DATA_DIR / 'keywords.csv' pages_path = DATA_DIR / 'pages.csv' rankings_path = DATA_DIR / 'rankings.csv' keywords_df = pd.read_csv(keywords_path) pages_df = pd.read_csv(pages_path) rankings_df = pd.read_csv(rankings_path) print('关键词数据:', keywords_df.shape) print('页面数据:', pages_df.shape) print('排名数据:', rankings_df.shape) print(keywords_df.head())运行:python seo_batch_report.py如果你能看到每份数据的行数和列数,说明读取成功。完成这一步后,你已经建立了自动化处理的入口。很多新手一上来就想写复杂功能,结果报错后不知道哪里出了问题。我的建议是:每一步都先确认数据读进来了,再继续往下做。步骤二:清洗关键词,避免后续统计失真关键词清洗是 SEO 批量数据处理中最容易被低估的一步。比如:python seoPython SEOpython seo 后面带一个空格人眼看起来差不多,但程序会把它们当成不同值。关键词去重、排名合并、分组统计都会被影响。接着往下做,我们添加一个清洗函数:def clean_keyword(value): if pd.isna(value): return '' return str(value).strip().lower() keywords_df['keyword_clean'] = keywords_df['keyword'].apply(clean_keyword) rankings_df['keyword_clean'] = rankings_df['keyword'].apply(clean_keyword) keywords_df = keywords_df[keywords_df['keyword_clean'] != ''] keywords_df = keywords_df.drop_duplicates(subset=['keyword_clean']) print('清洗后的关键词数量:', len(keywords_df))这里做了三件事:把空值转成空字符串,避免报错去掉前后空格,并统一转成小写根据 keyword_clean 去重注意这个细节:我们没有直接覆盖原始 keyword 字段,而是新增 keyword_clean。这样做更安全,因为原始数据还能保留,后面检查问题时不容易说不清楚。步骤三:规范 URL,减少重复页面URL 也是 SEO 数据里的重灾区。同一个页面可能出现这些形式:https://example.com/page https://example.com/page/ https://example.com/page?utm_source=test是否要完全合并,取决于具体场景。对于基础审计,我们可以先做一个温和版规范化:去掉首尾空格,去掉末尾斜杠,但不强行删除参数。因为有些网站参数页确实需要单独分析。def clean_url(value): if pd.isna(value): return '' url = str(value).strip() if url.endswith('/'): url = url[:-1] return url pages_df['url_clean'] = pages_df['url'].apply(clean_url) rankings_df['url_clean'] = rankings_df['url'].apply(clean_url) pages_df = pages_df[pages_df['url_clean'] != ''] pages_df = pages_df.drop_duplicates(subset=['url_clean'])我不建议新手一开始就写太激进的 URL 规则,比如直接删除所有查询参数、统一 http 和 https。那样确实看起来干净,但可能把本来不同的页面合并掉。SEO 自动化最怕的不是慢一点,而是悄悄把数据处理错。步骤四:检测页面 SEO 基础问题现在我们来做页面审计。先从最常见、最容易自动化判断的项目开始:状态码是否为 200Title 是否缺失Title 是否过长Meta Description 是否缺失H1 是否缺失把下面的函数加入脚本:def text_length(value): if pd.isna(value): return 0 return len(str(value).strip()) pages_df['title_length'] = pages_df['title'].apply(text_length) pages_df['description_length'] = pages_df['meta_description'].apply(text_length) pages_df['h1_length'] = pages_df['h1'].apply(text_length) pages_df['issue_status'] = pages_df['status_code'].apply(lambda x: '非200状态' if x != 200 else '') pages_df['issue_title_missing'] = pages_df['title_length'].apply(lambda x: 'Title缺失' if x == 0 else '') pages_df['issue_title_long'] = pages_df['title_length'].apply(lambda x: 'Title可能过长' if x > 60 else '') pages_df['issue_description_missing'] = pages_df['description_length'].apply(lambda x: 'Meta描述缺失' if x == 0 else '') pages_df['issue_h1_missing'] = pages_df['h1_length'].apply(lambda x: 'H1缺失' if x == 0 else '') issue_columns = [ 'issue_status', 'issue_title_missing', 'issue_title_long', 'issue_description_missing', 'issue_h1_missing' ] pages_df['issues'] = pages_df[issue_columns].apply( lambda row: ';'.join([item for item in row if item]), axis=1 ) pages_df['has_issue'] = pages_df['issues'].apply(lambda x: '是' if x else '否')关于 Title 长度,很多教程会给一个固定标准。这里我更愿意说得谨慎一点:60 个字符只是常用参考,不是绝对规则。搜索结果展示会受像素宽度、语言、设备影响。脚本的作用是帮你筛出“可能需要检查”的页面,而不是替你下最终结论。步骤五:给关键词做简单意图分类关键词意图分类可以做得很复杂,也可以先做一个够用的基础版。对于新手,我建议从规则分类开始,因为它透明、可解释,出错了也容易调整。比如我们可以按词根判断:包含 how、tutorial、guide,归为信息型包含 price、cost、buy,归为交易型包含 best、vs、review,归为对比型其他归为待判断def classify_intent(keyword): kw = clean_keyword(keyword) informational_words = ['how', 'tutorial', 'guide', 'what', 'why'] transactional_words = ['buy', 'price', 'cost', 'discount', 'coupon'] comparison_words = ['best', 'vs', 'review', 'compare'] if any(word in kw for word in transactional_words): return '交易型' if any(word in kw for word in comparison_words): return '对比型' if any(word in kw for word in informational_words): return '信息型' return '待判断' keywords_df['intent'] = keywords_df['keyword_clean'].apply(classify_intent)这套规则对英文关键词更直接。如果你处理中文关键词,可以换成中文词根,例如:怎么、如何、教程、方法:信息型价格、多少钱、购买、优惠:交易型哪个好、对比、评测、推荐:对比型没有绝对答案。关键词意图和行业、页面类型、搜索结果页形态都有关系。我们先用脚本做初筛,再人工复核重点词,这才是更稳妥的工作流。步骤六:合并关键词、排名和页面数据进入下一环节,我们把三份数据串起来。这个步骤非常实用:你可以看到某个关键词对应哪个 URL、排名是多少、页面本身有没有 SEO 基础问题。keyword_ranking_df = rankings_df.merge( keywords_df[['keyword_clean', 'volume', 'difficulty', 'intent']], on='keyword_clean', how='left' ) full_report_df = keyword_ranking_df.merge( pages_df[['url_clean', 'title', 'title_length', 'meta_description', 'description_length', 'h1', 'status_code', 'issues', 'has_issue']], on='url_clean', how='left' )这里的 how='left' 很重要。它表示以排名数据为主,即使关键词表或页面表里找不到对应记录,也保留排名数据。你可能会问:为什么不直接用 inner join,只保留匹配成功的数据?因为在 SEO 排查中,“匹配不上”本身就是线索。比如排名工具里有 URL,但抓取工具没有抓到,可能是抓取范围不完整,也可能是 URL 规范化规则不一致。保留这些异常,后面才有机会发现问题。步骤七:生成 Excel 报告,而不是只导出一个 CSVCSV 适合机器继续处理,Excel 更适合人查看。我们可以把不同结果放到不同 Sheet:full_report:关键词、排名、页面问题总表page_issues:存在 SEO 问题的页面keyword_summary:按意图统计关键词数量继续添加:page_issues_df = pages_df[pages_df['has_issue'] == '是'].copy() keyword_summary_df = keywords_df.groupby('intent').agg( keyword_count=('keyword_clean', 'count'), avg_volume=('volume', 'mean'), avg_difficulty=('difficulty', 'mean') ).reset_index() output_file = OUTPUT_DIR / 'seo_batch_report.xlsx' with pd.ExcelWriter(output_file, engine='openpyxl') as writer: full_report_df.to_excel(writer, sheet_name='full_report', index=False) page_issues_df.to_excel(writer, sheet_name='page_issues', index=False) keyword_summary_df.to_excel(writer, sheet_name='keyword_summary', index=False) print('报告已生成:', output_file)运行脚本后,打开 output 文件夹,你应该能看到 seo_batch_report.xlsx。这一步完成后,你已经拥有一个基础但完整的 SEO 批量数据自动化脚本。它不花哨,但可维护、可扩展、能落地。完整脚本汇总:可以直接复制运行为了方便你对照,这里放一份完整版本。你可以先跑通,再根据自己的字段名调整。from pathlib import Path import pandas as pd BASE_DIR = Path(__file__).resolve().parent DATA_DIR = BASE_DIR / 'data' OUTPUT_DIR = BASE_DIR / 'output' OUTPUT_DIR.mkdir(exist_ok=True) keywords_path = DATA_DIR / 'keywords.csv' pages_path = DATA_DIR / 'pages.csv' rankings_path = DATA_DIR / 'rankings.csv' def clean_keyword(value): if pd.isna(value): return '' return str(value).strip().lower() def clean_url(value): if pd.isna(value): return '' url = str(value).strip() if url.endswith('/'): url = url[:-1] return url def text_length(value): if pd.isna(value): return 0 return len(str(value).strip()) def classify_intent(keyword): kw = clean_keyword(keyword) informational_words = ['how', 'tutorial', 'guide', 'what', 'why'] transactional_words = ['buy', 'price', 'cost', 'discount', 'coupon'] comparison_words = ['best', 'vs', 'review', 'compare'] if any(word in kw for word in transactional_words): return '交易型' if any(word in kw for word in comparison_words): return '对比型' if any(word in kw for word in informational_words): return '信息型' return '待判断' keywords_df = pd.read_csv(keywords_path) pages_df = pd.read_csv(pages_path) rankings_df = pd.read_csv(rankings_path) keywords_df['keyword_clean'] = keywords_df['keyword'].apply(clean_keyword) rankings_df['keyword_clean'] = rankings_df['keyword'].apply(clean_keyword) keywords_df = keywords_df[keywords_df['keyword_clean'] != ''] keywords_df = keywords_df.drop_duplicates(subset=['keyword_clean']) keywords_df['intent'] = keywords_df['keyword_clean'].apply(classify_intent) pages_df['url_clean'] = pages_df['url'].apply(clean_url) rankings_df['url_clean'] = rankings_df['url'].apply(clean_url) pages_df = pages_df[pages_df['url_clean'] != ''] pages_df = pages_df.drop_duplicates(subset=['url_clean']) pages_df['title_length'] = pages_df['title'].apply(text_length) pages_df['description_length'] = pages_df['meta_description'].apply(text_length) pages_df['h1_length'] = pages_df['h1'].apply(text_length) pages_df['issue_status'] = pages_df['status_code'].apply(lambda x: '非200状态' if x != 200 else '') pages_df['issue_title_missing'] = pages_df['title_length'].apply(lambda x: 'Title缺失' if x == 0 else '') pages_df['issue_title_long'] = pages_df['title_length'].apply(lambda x: 'Title可能过长' if x > 60 else '') pages_df['issue_description_missing'] = pages_df['description_length'].apply(lambda x: 'Meta描述缺失' if x == 0 else '') pages_df['issue_h1_missing'] = pages_df['h1_length'].apply(lambda x: 'H1缺失' if x == 0 else '') issue_columns = [ 'issue_status', 'issue_title_missing', 'issue_title_long', 'issue_description_missing', 'issue_h1_missing' ] pages_df['issues'] = pages_df[issue_columns].apply( lambda row: ';'.join([item for item in row if item]), axis=1 ) pages_df['has_issue'] = pages_df['issues'].apply(lambda x: '是' if x else '否') keyword_ranking_df = rankings_df.merge( keywords_df[['keyword_clean', 'volume', 'difficulty', 'intent']], on='keyword_clean', how='left' ) full_report_df = keyword_ranking_df.merge( pages_df[['url_clean', 'title', 'title_length', 'meta_description', 'description_length', 'h1', 'status_code', 'issues', 'has_issue']], on='url_clean', how='left' ) page_issues_df = pages_df[pages_df['has_issue'] == '是'].copy() keyword_summary_df = keywords_df.groupby('intent').agg( keyword_count=('keyword_clean', 'count'), avg_volume=('volume', 'mean'), avg_difficulty=('difficulty', 'mean') ).reset_index() output_file = OUTPUT_DIR / 'seo_batch_report.xlsx' with pd.ExcelWriter(output_file, engine='openpyxl') as writer: full_report_df.to_excel(writer, sheet_name='full_report', index=False) page_issues_df.to_excel(writer, sheet_name='page_issues', index=False) keyword_summary_df.to_excel(writer, sheet_name='keyword_summary', index=False) print('关键词数据:', keywords_df.shape) print('页面数据:', pages_df.shape) print('排名数据:', rankings_df.shape) print('报告已生成:', output_file)实践练习:把脚本改成适合你的网站现在我们来做几个练习。不要只复制代码,真正掌握自动化脚本的方法,是把它改成你的工作流。练习一:增加 Title 过短检测很多页面 Title 不缺失,但只有一两个词,也可能不够清晰。你可以增加规则:小于 15 个字符标记为 Title 可能过短。参考写法:pages_df['issue_title_short'] = pages_df['title_length'].apply(lambda x: 'Title可能过短' if 0 < x < 15 else '')记得把 issue_title_short 加入 issue_columns。练习二:识别排名在 11 到 20 的关键词排名 11 到 20 的词通常值得重点看,因为它们已经接近第一页,但还没拿到足够曝光。你可以这样筛选:near_page_one_df = full_report_df[ (full_report_df['position'] >= 11) & (full_report_df['position'] <= 20) ].copy()然后把它导出到新的 Sheet:near_page_one_df.to_excel(writer, sheet_name='near_page_one', index=False)练习三:给页面问题设置优先级并不是所有问题都同等重要。404 页面、非 200 页面通常比 Title 过长更值得优先处理。你可以添加一个优先级字段:def get_priority(row): if row['status_code'] != 200: return '高' if row['issue_title_missing'] or row['issue_description_missing']: return '中' if row['issues']: return '低' return '无' pages_df['priority'] = pages_df.apply(get_priority, axis=1)这就是自动化脚本真正有用的地方:它不只是列问题,还能帮你排序,让你知道先处理什么。检查验收:跑完后你应该看到什么完成所有步骤后,请按下面的清单检查:output 文件夹中生成了 seo_batch_report.xlsxfull_report Sheet 中能看到关键词、URL、排名、页面标题、问题字段page_issues Sheet 中只保留存在问题的页面keyword_summary Sheet 中按意图统计了关键词数量脚本重复运行不会报错,旧报告会被覆盖原始 CSV 文件没有被修改如果你做到这些,恭喜你完成了一个可复用的 Python SEO 自动化基础项目。常见报错与处理方法报错:No such file or directory通常是文件路径不对。检查 data 文件夹是否和 seo_batch_report.py 在同一级目录,CSV 文件名是否完全一致。报错:KeyError: keyword这说明 CSV 里没有 keyword 这个字段。打开文件检查表头,可能是 Keyword、关键词、keywords。你可以统一改 CSV 表头,也可以在代码里适配字段名。中文乱码怎么办如果 CSV 是从某些工具导出的,可能需要指定编码:pd.read_csv(keywords_path, encoding='utf-8-sig')如果还是不行,可以尝试 gbk,但不要盲目修改。先确认你的文件实际编码。Excel 打不开或文件损坏常见原因是脚本运行时 Excel 文件正处于打开状态。关闭 Excel 后重新运行脚本。FAQ:关于 Python 自动化处理 SEO 数据的几个真实问题需要学到什么程度才能用于 SEO 工作?不需要学完整个 Python 体系。你先掌握文件读取、pandas 表格处理、条件筛选、数据合并、Excel 导出,就足够覆盖很多 SEO 日常任务。Excel 已经能做,为什么还要用 Python?如果只是几十行数据,Excel 更快。如果是几千行、几万行,或者每周都要重复同样流程,Python 更稳定。关键不是炫技,而是减少重复劳动和人为错误。这个脚本能不能直接用于大型网站?可以作为起点,但大型网站还需要考虑更多因素,比如分页抓取、Canonical、robots、重定向链、日志文件、索引状态、模板聚类等。不要一口吃成胖子,先把基础数据流跑顺。是否可以接入 Ahrefs、Semrush、Search Console 数据?可以。只要能导出 CSV 或通过 API 获取数据,就可以用类似思路处理。建议新手先用 CSV 练熟,再接 API。API 会多出鉴权、限流、字段变化等问题。下一步怎么学更稳如果你已经跑通这个教程,下一步可以沿着三条线继续扩展:数据源扩展:加入 Search Console 查询词、点击、展示、CTR 数据页面审计扩展:检查 Canonical、图片 Alt、内链数量、重复标题报告自动化:按日期生成文件名,定时运行,自动发送邮件我认为学习 Python 自动化 SEO,最好的路径不是先啃厚书,而是围绕真实任务一点点加功能。今天先清洗关键词,明天合并排名,后天生成报告。每完成一个小脚本,你对 SEO 数据的掌控感都会更强。到这里,你已经完成了从数据读取、清洗、检测、合并到报告导出的完整流程。接下来,把示例 CSV 换成你的真实数据,仔细按照步骤调整字段名和规则。真正的学习,会从你第一次处理自己的脏数据开始。
2026年05月31日
5 阅读
0 评论
0 点赞