网站标题 SEO 优化是件苦差事,尤其是页面多了之后,重复标题、过长标题和关键词缺失的情况防不胜防。主机选今天分享一个实战方案,利用 VPS 部署轻量级 AI Agent,结合 Python 脚本和 LLM API,自动巡检并生成诊断报告。这套方案不依赖昂贵的 SaaS 平台,完全运行在你的控制之下,适合拥有大量落地页或文章库的站长。

VPS部署AI工具进行网站标题自动检查
要实现自动检查,我们需要构建一个简单的 Agent 工作流:爬取网页 -> 提取 Title 标签 -> 调用 LLM 分析 -> 输出报告。这个过程在 VPS 上运行非常稳定,且成本极低。
Docker 环境准备与依赖安装
别直接在宿主机乱装环境,用 Docker 容器隔离最安全。假设你已经有一台安装了 Docker 的 VPS,我们先创建一个工作目录。
mkdir seo-agent-checker
cd seo-agent-checker
cat > requirements.txt << EOF
requests
beautifulsoup4
openai
EOF
这里我们使用 Python 配合 OpenAI 格式的 API(支持 OpenAI、DeepSeek、Moonshot 等),这样方便切换模型。新建 `Dockerfile`:
dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install –no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . .
CMD ["python", "check_titles.py"]
构建镜像前,先把核心逻辑写好。
Python 爬虫获取页面数据
新建 `check_titles.py`。这部分负责“看”网页,把标题抓下来。
python
import requests
from bs4 import BeautifulSoup
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("API_KEY"),
base_url=os.getenv("BASE_URL") # 例如 https://api.deepseek.com
)
def get_page_title(url):
try:
headers = {'User-Agent': 'Mozilla/5.0 (compatible; SEO-Agent/1.0)'}
response = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.content, 'html.parser')
return soup.title.string.strip() if soup.title else "无标题"
except Exception as e:
return f"抓取失败: {str(e)}"
urls = [
"https://example.com/page1",
"https://example.com/page2",
]
如果网站是 JS 渲染的,`requests` 拿不到内容,这时候就得换成 Selenium 或 Playwright,不过那会吃掉更多内存,普通 VPS 跑几个无头浏览器还行,多了扛不住。
编写 AI Agent 逻辑处理重复与缺失问题
有了标题,接下来是让 AI 像一个严格的 SEO 编辑一样去挑刺。我们要设计提示词,让它检查长度、是否重复、是否包含核心关键词。
接入 LLM API 分析标题质量
继续在 `check_titles.py` 中添加分析逻辑。这里有一个技巧:让 AI 返回 JSON 格式数据,方便后续处理或存入数据库。
python
import json
def analyze_title(title, target_keywords):
prompt = f"""
你是一个 SEO 专家。请分析以下网页标题:
标题内容:"{title}"
目标关键词:{target_keywords}
请检查以下问题:
1. 标题长度是否超过 60 个字符(百度建议)或 30 个中文字符?
2. 标题中是否缺失目标关键词?
3. 标题是否看起来是重复的(如果是单个标题分析,主要看是否为“首页-首页”这种无意义重复)?
请以 JSON 格式返回分析结果,包含字段:
– is_too_long (boolean)
– missing_keywords (array of strings)
– is_duplicate (boolean, 仅当标题明显无意义时为 true)
– suggestion (string, 优化建议)
不要输出 Markdown 格式,直接输出纯 JSON。
"""
try:
response = client.chat.completions.create(
model=os.getenv("MODEL_NAME", "gpt-3.5-turbo"), # 默认模型,可指定 deepseek-chat
messages=[
{"role": "system", "content": "你是一个 SEO 助手,只输出 JSON。"},
{"role": "user", "content": prompt}
],
temperature=0.2
)
content = response.choices[0].message.content
return json.loads(content)
except Exception as e:
return {"error": str(e)}
target_keywords = ["VPS教程", "主机选"] # 替换成你的关键词
all_titles = []
for url in urls:
title = get_page_title(url)
all_titles.append(title)
result = analyze_title(title, target_keywords)
print(f"URL: {url}")
print(f"Title: {title}")
print(f"Analysis: {json.dumps(result, ensure_ascii=False)}")
print("-" * 20)
注意,`all_titles` 列表在内存中保存了所有标题。如果你要检查全站重复标题,可以在爬取完所有 URL 后,再发一轮请求给 LLM,或者直接在 Python 里用集合去重,后者更省 Token。LLM 主要用来做语义上的“过长判断”和“关键词缺失”这种需要理解的活。
实战代码解析:标题长度与关键词匹配
上面的代码里,`analyze_title` 函数是核心。它通过 Prompt Engineering(提示词工程)约束 AI 的行为。`temperature=0.2` 是为了让输出更稳定,别今天说长,明天说短。
在 VPS 上跑的时候,记得设置环境变量,别把 API Key 硬编码在代码里。创建 `.env` 文件(记得加到 `.gitignore`):
API_KEY=sk-xxxxxxxxxxxxxx
BASE_URL=https://api.deepseek.com
MODEL_NAME=deepseek-chat
启动容器时挂载进去:
docker run -d –name seo-checker \
–env-file .env \
-v $(pwd):/app \
seo-agent-image
配置定时任务与日志监控
脚本写好了,总不能天天手动敲命令。用 Cron 或者是 n8n 这种自动化工具都可以。这里直接用系统自带的 Crontab,最轻量。
Crontab 定时任务配置
编辑 crontab:
crontab -e
添加一行,每天凌晨 3 点跑一次,把结果存到 log 文件里:
0 3 * * * cd /root/seo-agent-checker && /usr/bin/docker start seo-checker > /var/log/seo-check.log 2>&1
注意,这里用了 `docker start`,前提是你的容器配置是 `CMD ["python", "check_titles.py"]` 且跑完就退出的。如果容器一直运行,你应该用 `docker exec` 或者把脚本放进容器里的 crontab。
常见报错与日志排查
脚本跑起来了,不代表万事大吉。经常遇到的问题有几个:
1.JSON 解析失败:LLM 有时候会不听话,多输出几句废话。代码里加了 `json.loads` 的异常捕获,如果报错,检查一下 API 返回的原始内容,可能需要优化 Prompt,加上“严禁输出任何解释性文字”。
2.网络超时:目标网站响应慢,或者你的 VPS 网络抽风。`requests.get` 里的 `timeout` 参数必须设,不然一个卡住全盘皆输。
3.API 余额不足:DeepSeek 或 OpenAI 没钱了。先去控制台看一眼余额,别折腾半天发现是欠费。
4.内存溢出:如果你一次性爬取几万个 URL 存列表,Python 内存会爆。建议分批处理,比如每次处理 1000 个。
老鸟叮嘱
这套方案虽然能跑,但有几个坑得提前说清楚。
不要用 Root 跑脚本。虽然方便,但一旦代码有漏洞,或者被注入恶意命令,你的 VPS 就裸奔了。新建一个普通用户,专门跑 Docker。
API Key 别乱传。`.env` 文件权限设为 `600`。如果你用 Git 管理代码,`.env` 必须加到 `.gitignore`,千万别把 Key 提交到 GitHub 公开仓库,那是公开帮别人买单。
频率控制。别一上来就每秒爬 10 个页面。很容易被目标网站的防火墙(WAF)拉黑。在循环里加个 `time.sleep(2)`,礼貌爬取。
AI 不是万能的。LLM 判断“关键词缺失”很准,但判断“重复标题”有时候会误判(比如系列文章标题本来就相似)。对于重复项,建议还是先用 Python 的 `Counter` 统计字面重复,再用 AI 辅助判断是否属于“恶意堆砌”。
成本考量。如果网站有 10 万个页面,全丢给 GPT-4 分析,Token 费用够你买台新服务器。这种大规模场景,建议用 DeepSeek 或其他高性价比模型,或者先用正则规则过滤一遍,只把“疑似有问题”的标题发给 AI。
FAQ
1. 这个方案能检测 JS 渲染的 SPA 网站吗?
不能直接用 `requests`。需要替换爬虫部分为 Playwright 或 Selenium,但这会显著增加 VPS 内存和 CPU 占用。如果是 Vue/React 单页应用,建议直接调用 SSR 接口或者使用 Puppeteer。
2. 除了标题,能顺便检测 Description 吗?
可以。修改 `get_page_title` 函数,同时提取 `meta[name="description"]` 的 content,然后丢给 LLM 一起分析。
3. 必须用 Docker 吗?
不是必须,但强烈推荐。Docker 保证了 Python 环境的一致性,换服务器或者迁移的时候,直接打包镜像就行,省去重装依赖的麻烦。
4. 如果没有 API Key,能用本地模型吗?
可以。在 VPS 上部署 Ollama,拉取 `qwen:7b` 或 `llama3` 等模型,然后修改 `base_url` 指向 Ollama 的地址(通常是 `http://localhost:11434/v1`)。不过这对 VPS 配置要求较高,建议至少 4GB 以上内存。
5. 检测结果怎么通知我?
可以在脚本最后加一段代码,调用钉钉、飞书或者 Telegram 的 Webhook,把分析结果推送到手机。或者简单点,让 Python 发一封邮件给自己。
这套自动化流程把繁琐的人工巡检变成了后台静默运行的任务,每天早上醒来看报告就行,效率提升不是一点半点。
转载请注明出处:https://www.zhujixuan.com/jishujiaocheng/10233.html 商家投稿邮箱:zhujixuanblog@qq.com
