
简介利用Python进行SEO数据分析的自动化工具资源适合SEO专员、网站运营人员以及Python爬虫初学者。资源包内共6个文件包含可直接运行的exe程序、说明类txt文档、实用htm导航页以及ini配置文件整体仅786KB轻量易部署。已有375人学习下载。通过该工具可完成关键词收集、元信息检测、链接结构分析、死链排查等常见SEO任务txt说明文档提供了详细的使用指引htm导航页汇聚了SEO与爬虫相关网址能帮助读者快速上手并理解爬虫在SEO场景中的落地方法。整包设计紧凑适合希望借助现成工具提升站点搜索排名的实践者。 做SEO这一行天天和排名波动、页面收录、死链打交道时间一长你一定会冒出这个念头这些重复性的检查能不能让程序自动跑我自己就是在手动排查了上百个页面的TDK之后下定决心用Python写了个爬虫程序来干这件事。这篇博文就围绕“SEO python 爬虫程序”这件事把我的完整思路、可复现的代码、以及一堆踩坑经验分享出来。无论你是刚接触Python的SEO运营还是想了解SEO场景下爬虫怎么落地的开发者这篇文章都能给你一套直接能用的方案。很多人一听到“爬虫”就觉得门槛高其实SEO场景里用到的东西非常有限核心就是三件事批量抓取网页信息、解析关键字段、把结果整理成表格。用Python做这件事requests负责请求网页BeautifulSoup负责解析内容pandas负责输出数据加一起不到一百行代码却能替代你一整天的体力活。1. SEO与自研爬虫工具的结合逻辑1.1 SEO日常工作中的高频重复环节先梳理一下SEO日常工作里哪些场景最适合交给爬虫程序。我把它们分成四类每类都是真实会发生的需求。第一类是页面信息批量检查。一个稍微像样点的网站页面数量少则几十多则成百上千。每个页面的Title、Description、H1标签有没有写、长度合不合理、有没有重复正常做法是一个个打开页面查看源代码效率极低。这种场景最适合写一个Python脚本把URL列表扔进去自动输出每个页面的TDK信息。第二类是死链巡检。网站运营一段时间后因为改版、删除旧页面、外部链接失效等原因会产生404页面。搜索引擎对死链的容忍度很低大量死链会影响整站权重。你可以用爬虫批量请求网站内链把返回404、500状态码的URL全部过滤出来形成一份待处理清单。第三类是关键词排名监控。虽然市面上有各种排名查询工具但免费版通常有次数限制数据也不一定准。自己写一个脚本模拟搜索引擎搜索结果页的抓取在结果页里定位自己的域名出现的位置和排名定时跑一次就能记录波动趋势。第四类是竞品监控。定期抓取竞争对手的首页、栏目页记录他们的Title写法、关键词布局、新发内容方向可以作为自己优化策略的参考。1.2 为什么选择Python而不是现成工具市面上其实有不少现成的SEO工具比如各种站长工具、站点体检平台那为什么还要自己写我自己用下来的体验是现成工具存在三个问题。第一个问题是不够灵活。工具能查什么功能是固定的我想把“抓取Title的同时检查页面里是否有重复H1”这种个性化规则加进去工具往往做不到或者要付费开高级版。第二个问题是数据不透明。工具背后的抓取逻辑、判定标准你完全不知道数据出现异常时很难判断是网站问题还是工具问题。自己写的程序每一步做了什么清清楚楚。第三个问题是批量规模受限。免费工具通常限制每天查询次数对大量URL的巡检需求根本不够用。自己用Python写只要对方服务器不限制跑几千个URL也就是几分钟的事。选择Python还有一个实际原因它是目前最友好的一门编程语言。语法接近自然语言不需要像Java那样写一堆类定义SEO运营这类非程序员背景的人也能在一个下午看懂基本逻辑。而且Python在网页抓取这块的第三方库生态非常成熟requests、BeautifulSoup、pandas三件套组合解决90%的SEO数据抓取需求完全没问题。1.3 自研爬虫的边界与合规底线这里必须先说一个重要原则爬虫不是万能的也不是可以随便抓的。自己写爬虫做SEO数据监控和恶意爬取是两码事但边界要拎清楚。最基本的一条尊重目标网站的robots.txt文件。这是网站通过一种约定俗成的协议告诉爬虫哪些路径可以抓、哪些不能抓。另外要控制请求频率我的经验是请求之间至少间隔0.5到1秒不要让自己看起来像在攻击服务器。还有一点抓取的数据只能用于内部运营分析不要整站采集别人的内容直接发布这是原则问题。我见过有些新手一上来就设计高并发爬虫几十个线程同时请求一个网站结果IP被封连自己正常访问都受影响。在SEO这种应用场景里追求的是稳定可靠不是速度极限。2. 动手前的环境准备2.1 安装Python与配置环境变量如果你已经装好Python并能在命令行里跑通这一节可以直接跳过。但我接触过不少SEO同行卡在环境安装这一步就放弃了所以还是把关键步骤讲清楚。Windows系统推荐去Python官网下载安装包装的时候有一个坑非常关键一定要勾选“Add Python to PATH”这个选项。很多人装完Python之后在命令行输入python提示找不到命令就是因为没勾这个框没有把Python加到系统环境变量里。如果已经装完了才发现没加也可以手动添加在“系统属性-环境变量”里找到Path变量把Python安装目录和Scripts子目录都加进去。Linux系统的情况简单一些。Ubuntu/Debian系一般执行sudo apt update sudo apt install python3 python3-pip安装完成后在终端输入python3 --version或者python --version能看到版本号就说明环境没问题。安装完成后建议顺手升级一下pip避免后续装库时遇到版本兼容问题python -m pip install --upgrade pip2.2 创建虚拟环境并安装核心库为什么要用虚拟环境我自己早期吃过这方面的亏把各种第三方库直接装到系统Python里后来不同项目对同一个库的版本要求冲突解决起来非常痛苦。所谓虚拟环境就是为每一个项目单独创建一套独立的Python运行空间项目A装什么库都不影响项目B。创建虚拟环境其实就两行命令python -m venv seo_envWindows下激活虚拟环境seo_env\Scripts\activatemacOS和Linux下激活方式不同source seo_env/bin/activate激活成功之后命令行前面会出现(seo_env)这样的标记说明你已经进入了这个项目的独立环境。每次要跑爬虫脚本时先激活这个环境就行。接下来安装依赖库。先说明一下网络热词里很多人搜“python安装numpy库的方法”“comfyui工作流请安装缺失的包”这些在普通数据抓取场景里不一定用得上SEO爬虫的核心依赖其实就三个requests负责发HTTP请求beautifulsoup4负责解析网页pandas负责整理数据输出。后面代码里如果要把结果保存成Excel还需要openpyxl。安装命令pip install requests beautifulsoup4 pandas openpyxl如果下载速度很慢可以临时切换成国内镜像源实测会快很多pip install requests beautifulsoup4 pandas openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple这里多提一句很多初学者装库失败要么是没有激活虚拟环境要么是pip版本太旧先执行python -m pip install --upgrade pip升级一下再装能解决大部分问题。3. 完整代码实现批量抓取页面TDK与状态码3.1 需求定义与代码结构这一节我们实现一个非常贴近实际运营需求的工具就叫它“页面TKD巡检工具”。需求是这样的你准备好一份URL清单程序逐个请求这些URL抓取每个页面的HTTP状态码、Title、Description、H1标签最后把所有结果导出到一个文件里。我选这个功能作为完整实例是因为它实用性最强代码量又能控制在合理范围内。能把这套逻辑跑通后面扩展成死链巡检、关键词排名监控都只是在它的基础上做修改。代码的整体结构分成三块网络请求与解析函数、主流程控制、结果导出。这样拆分的意义在于以后你想把抓取逻辑更换成更复杂的Selenium方案时只需要改第一个函数不需要动其他部分。3.2 完整代码与逐段注释import time import pandas as pd import requests from bs4 import BeautifulSoup # 伪装成浏览器访问 HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } def fetch_page_info(url: str) - dict: 请求单个页面提取状态码、Title、Description、H1 info {url: url} try: resp requests.get(url, headersHEADERS, timeout10) info[status_code] resp.status_code # 根据响应内容自动识别编码避免中文乱码 resp.encoding resp.apparent_encoding soup BeautifulSoup(resp.text, html.parser) title_tag soup.find(title) info[title] title_tag.get_text(stripTrue) if title_tag else desc_tag soup.find(meta, attrs{name: description}) info[description] desc_tag.get(content, ).strip() if desc_tag else h1_tags soup.find_all(h1) info[h1_count] len(h1_tags) info[h1_text] h1_tags[0].get_text(stripTrue) if h1_tags else except requests.RequestException as e: info[status_code] f请求失败: {e} return info def load_urls(file_path: str) - list: 从文件读取URL列表自动跳过空行 urls [] with open(file_path, r, encodingutf-8) as f: for line in f: line line.strip() if line: urls.append(line) return urls def main(): urls load_urls(urls.txt) print(f共读取 {len(urls)} 个URL开始巡检...) results [] for index, url in enumerate(urls, start1): print(f[{index}/{len(urls)}] 正在抓取: {url}) results.append(fetch_page_info(url)) # 控制请求频率避免给对方服务器造成压力 time.sleep(1) df pd.DataFrame(results) output_file seo_check_result.xlsx df.to_excel(output_file, indexFalse) print(f巡检完成结果已保存到 {output_file}) print(df.head()) if __name__ __main__: main()代码分几个关键点说明一下。第一__name__ __main__这个判断。很多新手写脚本时把调用代码放在最外层一旦文件被其他模块导入这些代码就会立即执行产生不可预料的副作用。加上这个判断以后只有直接运行本文件时才会执行main()这是一个好习惯。第二resp.encoding resp.apparent_encoding这行不要省略。requests库用Headers里的charset判断编码但很多网站的charset是错的不及时设成apparent_encoding根据内容自动检测出的编码抓回来的Title就会是乱码。第三time.sleep(1)是关键的一行。每抓一个页面停一秒既能防止被对方服务器拒绝也能体现对目标网站的礼貌一举两得。3.3 运行方法、结果输出与效果说明运行前先在脚本同目录下建一个urls.txt每行放一个URL比如https://example.com https://example.com/about https://example.com/blog然后在虚拟环境里执行python seo_check.py运行过程会在终端实时打印进度。全部跑完之后同目录下会生成一个seo_check_result.xlsx文件里面包含URL、状态码、标题、描述、H1数量、H1内容六列数据。拿到这个表之后你可以在Excel里直接做数据分析比如用筛选功能找出状态码不是200的页面用条件格式标出Title长度超过30个汉字的页面用高亮重复值检查Title是否重复。我自己第一次跑的时候就发现网站有三个页面的Title一模一样这种问题靠人工翻源代码很难发现程序一跑就全暴露出来了。3.4 关于反爬机制的初步应对有些网站会检测请求来源返回一个验证页面而不是正常内容这时候状态码仍然可能显示200但Title字段会变成验证页的标题。判断方法很简单对比抓回来的Title和浏览器里手动看到的Title是否一致。应对方式有三种按性价比排序。第一种是更换更完整的User-Agent和Headers比如加上Referer、Accept-Language字段。第二种是使用Session对象保持会话连接模拟正常浏览器行为。第三种是升级为Selenium模拟浏览器操作但代价是速度慢、资源占用高SEO巡检这种轻量场景一般用不上。4. 高频问题排查爬虫运行不出内容的真相4.1 Process finished with exit code 0但不输出内容这个现象太典型了搜索热词里就有人专门搜这个问题“爬虫程序运行不出内容只显示Process finished with exit code 0”。从现象描述看代码确实完整执行了没有任何报错但程序没有产生预期的输出或文件。这里要解释一下exit code 0是什么。它是一个明确的信号程序从第一行执行到结束没有抛出任何异常以正常状态退出。换句话说Python认为自己的任务已经完成了。那为什么程序“觉得”完成了而你却什么都没看到根据我的经验出现这个现象基本逃不出以下几个原因。原因一是main()函数没有被调用。新手经常把代码写成def main(): print(Hello)然后看不到任何输出。这是因为你只是定义了main这个函数从来没有执行它。函数和普通代码不一样定义不等于执行。解决办法就一个加上if __name__ __main__: main()两行。原因二是读取的文件路径不对或者文件为空。比如代码里写open(urls.txt)但实际urls.txt放在别的目录里程序会抛出FileNotFoundError异常这在热词的“运行不出内容”现象里反而不常见。更隐蔽的是文件存在但内容是空的程序正常读取到空列表循环体完全没执行所以没有任何打印输出直接正常退出。原因三是print输出被IDE的缓冲区吞掉。有些集成开发环境的控制台对输出有缓冲机制程序执行太快时输出还没来得及刷新显示窗口就已经关闭了。解决办法是在代码里加import sys; sys.stdout.reconfigure(line_bufferingTrue)或者在程序末尾加一个input()等待用户按回车再退出。原因四是目标网站返回了空内容但程序本身逻辑正常跑完了。requests把网页请求回来后你只抓了固定的标签如果页面结构和你预期的不一样比如目标页面用JavaScript动态加载内容那个title标签可能是空的程序不报错、不打印最终输出就是一堆空字段。排查这类问题时我建议按这个顺序来先在程序最开头加一段测试代码打印从urls.txt读到的URL数量然后在循环里加打印确认每个URL都进入了抓取逻辑最后在抓取函数里把resp.text的前500个字符打印出来确认网页内容确实被抓回来了。一步一步缩小范围比盯着现象瞎猜效率高得多。4.2 请求超时、中文乱码与编码声明爬虫过程里最常见的异常是请求超时。正常的处理方式是在requests.get里加timeout参数比如timeout10表示超过10秒没有响应就放弃这个URL。不要省略这个参数否则遇到响应很慢的网站程序可能挂在那里几分钟不退出。加了timeout之后配合try...except捕获超时异常程序就能自动跳过问题URL继续跑后面的。中文乱码的问题前面提到过通过设置resp.encoding resp.apparent_encoding基本能解决。但必须注意一个细节这个赋值操作要在使用resp.text之前完成。requests的resp.text属性是惰性加载的第一次访问时才根据当前encoding解码如果之前已经读过resp.text再改encoding就不起作用了需要重新请求或者用resp.content.decode()手动解码。另外提醒一下写文件时的编码声明。有的读者可能不用Excel而是把结果保存成CSV这时候要写成df.to_csv(result.csv, indexFalse, encodingutf-8-sig)注意这里用的是utf-8-sig而不是utf-8。UTF-8的CSV文件在Excel里打开容易乱码utf-8-sig会在文件开头加一个BOM标记Excel打开就正常了。这个小细节卡住过不少人。4.3 抓不到数据的常见防爬策略识别还有一个高频场景代码没有任何问题但抓回来的数据全是空的。这时候要警惕目标网站是否用了防爬策略。最容易碰到的是请求头检查不带User-Agent或者User-Agent太普通服务器直接返回403或者一个空壳页面。解决办法是使用我在代码里给出的完整Headers配置。再高级一点的网站会校验Cookie第一次访问会设置一个Cookie然后跳转到真正的页面。对于这种情况用requests.Session就能应对session requests.Session() session.get(url) # 第一次请求获取Cookie resp session.get(url) # 带Cookie再次请求还有一种是通过JS在浏览器端动态渲染内容静态请求返回的HTML里根本没有目标字段。这种情况requests就无能为力了需要换Selenium或者Playwright等措施。但说实话在SEO巡检这种场景里这种级别的网站很少见真遇到了用Selenium处理吧。5. 从单次脚本到自动化工具的进阶方向5.1 定时自动运行与结果对比脚本跑通一次之后你会发现每周手动跑一遍也挺烦的。这时候可以把程序做成定时任务让它自动运行每次生成一份带日期的结果文件。Windows上可以用“任务计划程序”创建基本任务在“操作”里填程序路径和参数。举一个具体例子我自己的脚本路径是D:\seo_project\run.pyPython环境路径是D:\seo_project\seo_env\Scripts\python.exe那么“程序或脚本”填后者“添加参数”填前者触发器设置为每周一早上9点运行。Linux系统更简单在终端执行crontab -e然后添加一行0 9 * * 1 cd /path/to/project /path/to/seo_env/bin/python run.py log.log 21这行的含义是每周一早上9点切换到项目目录用虚拟环境里的Python执行run.py并把输出和错误日志都追加到log文件里。每次巡检生成的结果文件名最好带上日期格式如seo_check_20250120.xlsx这样可以直接对比两周之间的数据变化。对比方法用Excel的SUMIF或VLOOKUP函数就能搞定不需要额外写代码。5.2 更多SEO场景的扩展思路这套基础架构跑通之后可以往很多方向扩展。我列三个最实用的方向你可以在当前代码基础上改。方向一是标题长度批量分析。搜索引擎结果页通常只显示一定长度的Title超出部分会被截断。你可以在抓取Title元素之后用len(title)计算字符数把过长的Title标记出来。针对中文站点经验值是一个Title控制在30个汉字左右太短或太长都要优化。方向二是死链巡检。把代码里的fetch_page_info改成只请求HEAD方法或者只获取状态码不解析正文速度会快很多。跑完整站URL清单后把所有状态码不是200的URL导出成“死链待处理”报表交给自己或开发同事逐条处理。方向三是排名监控。用requests抓取搜索引擎搜索结果页面在HTML里查找你的域名是否出现在结果列表中然后记录位置。这个方向的代码量会大一些因为搜索引擎的页面结构更复杂可能还需要处理分页和地域定向问题。但核心思路和上面的巡检代码是一模一样的。5.3 数据分析环节的常见依赖抓回来的数据如果要做深度分析pandas库和numpy库几乎绕不开。热词里有人专门搜“python安装numpy库的方法”这个问题我在前面环境准备部分已经涉及了直接pip install pandas numpy就能同时装好。在SEO巡检的场景里numpy的使用频率不算高但pandas真的是数据分析利器。比如你想知道所有被抓页面Title的平均长度一行代码import pandas as pd df pd.read_excel(seo_check_result.xlsx) print(df[title].str.len().mean())你想找出Title重复的页面duplicated_titles df[df.duplicated(title, keepFalse)] print(duplicated_titles)这些操作如果纯靠手工在Excel里做几十个页面还行几百上千个就很费劲。把pandas列入环境依赖里后续做数据分析会轻松非常多。最后分享一个我个人很受用的使用习惯。我每次优化完一批页面的TDK之后不会立刻刷新数据而是等到搜索引擎正常收录更新后再跑一轮巡检前后对比Title长短分布的变化。这样既能验证优化效果也能判断搜索引擎对改版的反应周期。用这套Python爬虫方案我帮自己和朋友的站点做过好几轮全站内容巡检每次都能发现几个隐藏的SEO问题。如果你正被重复的检查工作困扰从今天这份代码开始动手两三个小时后你就能拥有一份属于自己的SEO巡检小工具。本文还有配套的精品资源点击获取