搜索全站
主题 12 分钟阅读

WordPress 分页与 rel=next/prev 现状:替代做法与代码

还在给分页加 rel=next/prev?Google 2019 年起已不作为索引信号。本文讲清现状与替代方案,给出 paginate_links 自定义输出、canonical 与分页内容差异化的完整代码。

U
UFO_PF 2017-05-15 · 阅读 12 分钟
Wo 主题
阅读提示
本文约 4,662 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:照着老教程加的标签,早就不起作用了

搜索「WordPress 分页 SEO」,排名靠前的老教程几乎都会教你用插件或代码给分页加上 <link rel="next"> 和 <link rel="prev">,说这样能帮搜索引擎理解分页序列。于是不少人照做,有的还专门装了插件。但事实是:Google 在 2019 年就已公开确认不再将 rel=next/prev 作为索引信号,这个标签从那以后对 Google 的索引没有任何帮助。

这不是说分页不需要处理。恰恰相反,分页页面积累了大量容易被忽视的问题:第 2 页以后的标题重复、canonical 指向混乱、每页内容差异太小被判为低质量、分页链接没有可抓取的真实 URL(纯 AJAX 加载)。本文讲清「该放弃什么」和「该补什么」,并给出 paginate_links() 的自定义输出代码。

原理分析:分页为什么容易被判为低质量

问题 成因 后果
标题重复 每页 <title> 都是「文章列表」 搜索结果里多条重复标题
canonical 错误 第 2 页 canonical 指向第 1 页 第 2 页永远不被索引
内容差异小 摘要过短,页面主体几乎相同 被判为重复/低质量
链接不可抓取 用 JS 加载更多,无真实 URL 深层内容无法被发现
无序号提示 URL 里没有 page/2 之类的标识 抓取器难以理解序列

Google 的官方立场是:把每个分页页面当成独立页面来对待,不把它和第一页合并。这带来两个直接推论:第一,每页应有自己的、带页码的 <title> 和 <meta description>;第二,每页的 canonical 应该指向自己,而不是指向第一页。很多 SEO 插件默认把分页 canonical 指向第一页,这个默认行为值得检查。

至于 rel=next/prev,目前的状态是:Google 明确不用;HTML 规范里它仍是合法标签,保留不会有负面影响,但为它专门装插件或写代码的投入产出比为零。真正有用的是「可抓取的真实分页链接」加「清晰的页码上下文」。

保姆级实操

  1. 检查现有输出:查看源码里有没有 rel=next/prev,有的话不用急着删,把精力放到下面几步。
  2. 确认分页链接是真实 URL:the_posts_pagination() 默认输出带 /page/2/ 的真实链接,别改成纯 AJAX。
  3. 纠正 canonical:分页页的 canonical 应指向自身,检查 SEO 插件设置。
  4. 给分页页加页码标题:用 document_title_parts 过滤器追加页码。
  5. 保证内容差异:摘要放长一点,或每页露出文章首段,避免整页只有标题。
  6. 自定义分页 HTML:用 paginate_links() 控制输出,加 aria-label 和当前页标记。
  7. 首页静态页场景:注意 page_for_posts 页面的分页 URL 与 paged 参数的关系。
<?php
// 子主题 functions.php:给分页页追加页码到标题
add_filter( 'document_title_parts', 'mimangfei_paged_title' );
function mimangfei_paged_title( $parts ) {
    $paged = get_query_var( 'paged' );
    if ( $paged > 1 ) {
        $parts['title'] .= sprintf( ' - 第 %d 页', (int) $paged );
    }
    return $parts;
}
<?php
// 自定义分页输出:可抓取的真实链接 + 无障碍标记
function mimangfei_pagination( $query = null ) {
    global $wp_query;
    $query = $query ? $query : $wp_query;

    $total   = isset( $query->max_num_pages ) ? (int) $query->max_num_pages : 1;
    $current = max( 1, (int) get_query_var( 'paged' ) );

    if ( $total <= 1 ) {
        return '';
    }

    $links = paginate_links( array(
        'base'      => str_replace( PHP_INT_MAX, '%#%', esc_url( get_pagenum_link( PHP_INT_MAX ) ) ),
        'format'    => '?paged=%#%',
        'current'   => $current,
        'total'     => $total,
        'type'      => 'array',
        'prev_text' => '上一页',
        'next_text' => '下一页',
        'end_size'  => 1,
        'mid_size'  => 2,
    ) );

    if ( empty( $links ) ) {
        return '';
    }

    $html = '<nav class="pagination" aria-label="分页导航"><ul>';
    foreach ( $links as $link ) {
        // 给当前页加上 aria-current,方便读屏与样式
        if ( false !== strpos( $link, 'class="page-numbers current"' )
            || false !== strpos( $link, 'aria-current' ) ) {
            $html .= '<li class="is-current">' . $link . '</li>';
        } else {
            $html .= '<li>' . $link . '</li>';
        }
    }
    $html .= '</ul></nav>';
    return $html;
}
<?php
// 内容分页(一篇长文拆成多页)也要保证链接可抓取
add_filter( 'wp_link_pages_args', 'mimangfei_link_pages_args' );
function mimangfei_link_pages_args( $args ) {
    $args['before'] = '<nav class="page-links" aria-label="文章分页">';
    $args['after']  = '</nav>';
    $args['next_or_number'] = 'number';
    return $args;
}
<?php
// 让 canonical 指向分页自身(仅在确认插件未正确处理时使用)
add_filter( 'get_canonical_url', 'mimangfei_paged_canonical', 20 );
function mimangfei_paged_canonical( $canonical ) {
    $paged = (int) get_query_var( 'paged' );
    if ( $paged > 1 && is_home() ) {
        return get_pagenum_link( $paged );
    }
    return $canonical;
}

常见踩坑

  1. 给首页(非分页)也加了 rel=next:第一页就带 next 标签,逻辑不对,也会让第三方工具误判。只在 is_paged() 为真时输出。
  2. 分页 URL 用 ?paged=2 但站点开了伪静态:会产生两套 URL 指向同一内容。统一用 /page/2/ 形式,并把带参数的形式做 301。
  3. 案例:某站第 2 页之后长期零收录,检查发现 SEO 插件把全部分页的 canonical 统一指向了第 1 页,等于自己告诉 Google「这些页面都是首页的副本」。改成 self-referencing canonical 后,两周内第 2–5 页陆续被收录。教训:canonical 不是「去重万金油」,分页页应当自我引用。
  4. AJAX 无限滚动没有回退 URL:纯 JS 加载更多,关掉 JS 就只剩第一页。要么保留分页链接,要么用 History API 同步更新 URL。
  5. paginate_links() 的 base 写错:get_pagenum_link( PHP_INT_MAX ) 这个技巧能自动适配伪静态与查询串两种形式,硬编码 base 在关闭伪静态时会失效。
  6. 自定义 WP_Query 分页失效:自定义查询没传 paged 参数,第 2 页仍显示第 1 页内容。必须写 'paged' => get_query_var( 'paged' ) ?: 1。
  7. the_posts_pagination() 与自定义查询不匹配:它读的是全局 $wp_query,自定义循环里要用 paginate_links() 手动传 total。
  8. 分页页内容太薄:只放标题和一句话摘要,每页 90% 内容相同。露出首段或加分类说明文字,让每页有独特内容。归档页的整体取舍可参考 主题日期归档是否该保留。

总结

分页处理的判断标准是三条:链接可抓取(真实 URL)、canonical 自我引用、每页有差异化标题与内容。rel=next/prev 可以保留但不必投入。行动清单:确认分页是真实 URL → 检查 canonical 是否指向自身 → 给分页页加页码标题 → 保证每页内容有差异 → 用 paginate_links() 输出带无障碍标记的分页 → 在 Search Console 里看「已编入索引」的分页数量。做完这些,再决定首页的形态,可参考 主题首页静态页 vs 最新文章的选择,两者共同决定站点的收录结构。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。