Git钩子脚本如何检查SEO优化

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查SEO优化

  1. 核心检查清单(脚本需要验证的内容)
  2. 使用 Bash 脚本(适合简单检查)
  3. 使用 Node.js 脚本(更健壮,适合复杂逻辑)
  4. 使用 Python 脚本(适合 Python 项目)
  5. 如何部署钩子脚本到团队?
  6. 高级建议

Git 钩子脚本主要用于在代码提交前或推送前自动化执行检查,要检查 SEO 优化,通常需要结合 HTML 解析工具正则表达式来扫描修改或新增的 HTML/模板文件。

以下是几种常见场景的实现思路和核心检查逻辑:

核心检查清单(脚本需要验证的内容)

在编写脚本前,明确需要检查哪些 SEO 要素:

  1. Title 标签:是否存在?长度是否合理(50-60 字符)?
  2. Meta Description:是否存在?长度是否合理(150-160 字符)?
  3. H1 标签:是否唯一(一个页面只有一个 H1)?
  4. Alt 属性:图片 <img> 标签是否都有 alt 属性?
  5. Canonical 标签:是否指定了 rel="canonical"
  6. Robots 元标签:是否配置了 indexnoindex
  7. 死链/相对路径<a> 标签的 href 是否为 javascript:void(0) 或空?
  8. Open Graph 标签og:titleog:descriptionog:image 是否存在?

使用 Bash 脚本(适合简单检查)

.git/hooks/pre-commit 中(注意:git 钩子脚本默认不提交到仓库,需手动部署):

#!/bin/bash
# 检查暂存区中新增或修改的 .html 文件
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.html$')
if [ -z "$CHANGED_FILES" ]; then
    exit 0
fi
ISSUES_FOUND=0
for FILE in $CHANGED_FILES; do
    if [ ! -f "$FILE" ]; then
        continue
    fi
    echo "检查 SEO: $FILE"
    # 1. 检查 Title 标签
    if ! grep -q '<title>' "$FILE"; then
        echo "  ⚠️ 错误: 缺少 <title> 标签"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    fi
    # 2. 检查 Meta Description
    if ! grep -q 'name="description"' "$FILE"; then
        echo "  ⚠️ 错误: 缺少 meta description"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    fi
    # 3. 检查 H1 标签数量(应唯一)
    H1_COUNT=$(grep -c '<h1[^>]*>' "$FILE")
    if [ "$H1_COUNT" -eq 0 ]; then
        echo "  ⚠️ 错误: 缺少 <h1> 标签"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    elif [ "$H1_COUNT" -gt 1 ]; then
        echo "  ⚠️ 错误: 存在多个 <h1> 标签 (共 $H1_COUNT 个)"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    fi
    # 4. 检查图片 Alt 属性
    IMGS_WITHOUT_ALT=$(grep -oP '<img[^>]*>' "$FILE" | grep -vP 'alt="[^"]*"' | wc -l)
    if [ "$IMGS_WITHOUT_ALT" -gt 0 ]; then
        echo "  ⚠️ 错误: 有 $IMGS_WITHOUT_ALT 个 <img> 缺少 alt 属性"
        ISSUES_FOUND=$((ISSUES_FOUND + 1))
    fi
    # ... 其他检查类似:canonical、og:tags
done
if [ "$ISSUES_FOUND" -gt 0 ]; then
    echo ""
    echo "❌ SEO 检查发现 $ISSUES_FOUND 个问题,请修正后重新提交。"
    exit 1
fi
exit 0

使用 Node.js 脚本(更健壮,适合复杂逻辑)

如果项目使用 Node.js,可以编写 pre-commit.js 脚本,利用 cheerio 解析 DOM(比正则更准确)。

脚本示例 (pre-seo-check.js):

const { execSync } = require('child_process');
const fs = require('fs');
const cheerio = require('cheerio'); // npm install cheerio
// 获取暂存区中修改的 HTML 文件
const output = execSync('git diff --cached --name-only --diff-filter=ACM', { encoding: 'utf8' });
const files = output.split('\n').filter(f => f.endsWith('.html'));
let errors = [];
files.forEach(file => {
    if (!fs.existsSync(file)) return;
    const html = fs.readFileSync(file, 'utf8');
    const $ = cheerio.load(html);
    // Title 检查
    const title = $('title').text().trim();
    if (!title) {
        errors.push(`${file}: 缺少 Title 标签`);
    } else if (title.length > 60) {
        errors.push(`${file}: Title 长度 ${title.length} 字符,建议 ≤60`);
    }
    // Meta description 检查
    const desc = $('meta[name="description"]').attr('content');
    if (!desc) {
        errors.push(`${file}: 缺少 Meta Description`);
    } else if (desc.length > 160) {
        errors.push(`${file}: Description 长度 ${desc.length} 字符,建议 ≤160`);
    }
    // H1 检查
    const h1Count = $('h1').length;
    if (h1Count === 0) {
        errors.push(`${file}: 缺少 H1 标签`);
    } else if (h1Count > 1) {
        errors.push(`${file}: 存在 ${h1Count} 个 H1 标签,应唯一`);
    }
    // 图片 Alt 检查
    $('img').each((i, el) => {
        if (!$(el).attr('alt')) {
            errors.push(`${file}: 图片缺少 alt 属性 (src: ${$(el).attr('src')})`);
        }
    });
    // Canonical 检查
    const canonical = $('link[rel="canonical"]').attr('href');
    if (!canonical) {
        errors.push(`${file}: 缺少 canonical 标签`);
    }
    // Open Graph 基本检查
    if (!$('meta[property="og:title"]').length) {
        errors.push(`${file}: 缺少 og:title 标签`);
    }
});
if (errors.length > 0) {
    console.error('❌ SEO 检查失败:\n' + errors.join('\n'));
    process.exit(1);
} else {
    console.log('✅ SEO 检查通过');
}

使用 Python 脚本(适合 Python 项目)

利用 beautifulsoup4 库:

import subprocess
import sys
from bs4 import BeautifulSoup
# 获取暂存区文件
result = subprocess.run(
    ['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM'],
    capture_output=True, text=True
)
files = [f for f in result.stdout.split('\n') if f.endswith('.html')]
has_error = False
for file in files:
    with open(file, 'r', encoding='utf-8') as f:
        soup = BeautifulSoup(f.read(), 'html.parser')
    # 检查逻辑与 Node.js 类似
    if not soup.find('title') or not soup.find('title').get_text(strip=True):
        print(f"❌ {file}: 缺少 Title")
        has_error = True
    # ... 其他检查
if has_error:
    sys.exit(1)

如何部署钩子脚本到团队?

由于 .git/hooks/ 目录下的脚本不会被 Git 跟踪,需要手动同步到团队成员的仓库。

推荐两种方式:

  1. 存储在项目目录:将脚本放在项目根目录的 scripts/git-hooks/ 文件夹中,然后在 package.json 中使用 huskypre-commit 库自动安装。
  2. 结合 CI/CD:使用 pre-push 钩子在推送到远程仓库前触发检查,或者在 CI 流水线(GitHub Actions, GitLab CI)中直接运行,这比本地钩子更可靠,因为不会被开发者绕过。

高级建议

  • 增量检查:只检查本次修改的行,而不是整个文件(避免旧代码反复报错),使用 git diff --cached --unified=0 获取具体变更行。
  • 性能考虑:如果项目中 HTML 文件非常多,钩子会变得很慢,可以限制只检查 .html.ejs/.pug 等模板文件。
  • 配置化:允许在 seo-config.json 中自定义阈值(title 长度上限、是否强制需要 og 标签等)。

Git 钩子能有效在代码入库前拦截明显的 SEO 问题,最佳实践是本地钩子 + CI 双重校验,确保即使开发者跳过了本地钩子,CI 也能强制检查。

抱歉,评论功能暂时关闭!