WordPress免插件快速生成sitemap网站地图教程

很多朋友用WordPress创建自己的博客网站后,不知道如何在WordPress中创建一个支持百度收录的XML站点地图,接下来给大家提供一个通过编写PHP脚本,避免使用WordPress插件。只需要将下面提供的代码保存为sitemap.php并上传至网站根目录,然后在宝塔面板中设置shell脚本来定期更新网站地图。

将下面代码复制并保存到文件sitemap.php,然后上传到WordPress网站根目录。

<?php
/**
 * WordPress XML Sitemap Generator
 * 生成符合sitemaps.org规范的站点地图
 * 优化点:添加缓存机制、完善错误处理、提升性能
 */

// 确保从WordPress环境运行
if (!defined('ABSPATH')) {
    // 更安全的路径处理
    $wpRootDir = dirname(__FILE__);
    while (!file_exists($wpRootDir . '/wp-blog-header.php') && strlen($wpRootDir) > 1) {
        $wpRootDir = dirname($wpRootDir);
    }
    require($wpRootDir . '/wp-blog-header.php');
}

// 缓存功能 - 减少服务器负载
$cacheFile = WP_CONTENT_DIR . '/sitemap-cache.xml';
$cacheDuration = 3600; // 缓存有效期(秒) - 1小时

// 检查缓存是否有效
if (file_exists($cacheFile) && time() - filemtime($cacheFile) < $cacheDuration) {
    header("Content-type: text/xml; charset=UTF-8");
    header('HTTP/1.1 200 OK');
    readfile($cacheFile);
    exit;
}

// 配置选项 - 增加更多可配置项
$config = [
    'posts_to_show' => 9999,
    'include_tags'  => true,
    'include_archives' => false, // 新增:是否包含日期归档
    'priorities'    => [
        'home'      => 1.0,
        'posts'     => 0.6,
        'pages'     => 0.6,
        'categories'=> 0.8,
        'tags'      => 0.4,
        'archives'  => 0.3
    ],
    'changefreq'    => [
        'home'      => 'daily',
        'posts'     => 'monthly',
        'pages'     => 'weekly',
        'categories'=> 'weekly',
        'tags'      => 'monthly',
        'archives'  => 'monthly'
    ],
    'exclude' => [ // 新增:排除特定ID的内容
        'posts' => [],
        'pages' => [],
        'categories' => [],
        'tags' => []
    ]
];

// 开始捕获输出内容用于缓存
ob_start();

// 设置响应头
header("Content-type: text/xml; charset=UTF-8");
header('HTTP/1.1 200 OK');

// 生成XML内容
echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:mobile="http://www.baidu.com/schemas/sitemap-mobile/1/">';
echo '<!-- 生成时间: ' . current_time('mysql') . ' -->';
echo '<!-- 总条目数统计将在底部显示 -->';

$totalUrls = 0; // 统计总URL数量

/**
 * 生成URL条目
 * @param string $loc URL地址
 * @param string $lastmod 最后修改时间
 * @param string $changefreq 更改频率
 * @param float $priority 优先级
 * @return bool 成功返回true,失败返回false
 */
function render_sitemap_url($loc, $lastmod = '', $changefreq = '', $priority = '', &$totalUrls) {
    // 确保URL有效
    if (empty($loc) || !filter_var($loc, FILTER_VALIDATE_URL)) {
        error_log("Invalid URL in sitemap: " . $loc);
        return false;
    }
    
    // 验证时间格式
    if (!empty($lastmod) && !preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2}$/', $lastmod)) {
        error_log("Invalid lastmod format in sitemap: " . $lastmod);
        $lastmod = ''; // 忽略无效的时间格式
    }
    
    // 验证更新频率
    $validChangefreq = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'];
    if (!empty($changefreq) && !in_array($changefreq, $validChangefreq)) {
        error_log("Invalid changefreq in sitemap: " . $changefreq);
        $changefreq = '';
    }
    
    // 验证优先级
    if (!empty($priority) && (!is_numeric($priority) || $priority < 0 || $priority > 1)) {
        error_log("Invalid priority in sitemap: " . $priority);
        $priority = '';
    }
    
    echo '<url>';
    echo '<loc>' . esc_url($loc) . '</loc>';
    
    if (!empty($lastmod)) {
        echo '<lastmod>' . esc_html($lastmod) . '</lastmod>';
    }
    
    if (!empty($changefreq)) {
        echo '<changefreq>' . esc_html($changefreq) . '</changefreq>';
    }
    
    if (!empty($priority)) {
        echo '<priority>' . esc_html($priority) . '</priority>';
    }
    
    echo '</url>';
    $totalUrls++;
    return true;
}

// 首页
$home_lastmod = get_lastpostmodified('GMT');
$home_lastmod = $home_lastmod ? gmdate('Y-m-d\TH:i:s+00:00', strtotime($home_lastmod)) : '';
render_sitemap_url(
    get_home_url(),
    $home_lastmod,
    $config['changefreq']['home'],
    $config['priorities']['home'],
    $totalUrls
);

// 普通文章
$posts_args = [
    'posts_per_page' => $config['posts_to_show'],
    'post_status'    => 'publish',
    'post_type'      => 'post',
    'post__not_in'   => $config['exclude']['posts'], // 排除指定文章
    'no_found_rows'  => true, // 不计算总条数,提升性能
    'update_post_term_cache' => false, // 不缓存分类数据,提升性能
    'update_post_meta_cache' => false // 不缓存元数据,提升性能
];

$myposts = get_posts($posts_args);
foreach ($myposts as $post) {
    setup_postdata($post);
    render_sitemap_url(
        get_permalink(),
        get_the_time('c'),
        $config['changefreq']['posts'],
        $config['priorities']['posts'],
        $totalUrls
    );
}
wp_reset_postdata();

// 页面
$mypages = get_pages([
    'post_status' => 'publish',
    'exclude' => $config['exclude']['pages'] // 排除指定页面
]);
if (!empty($mypages)) {
    foreach ($mypages as $page) {
        $page_modified = get_page($page->ID)->post_modified;
        $page_modified = $page_modified ? str_replace(" ", "T", $page_modified) . '+00:00' : '';
        
        render_sitemap_url(
            get_page_link($page->ID),
            $page_modified,
            $config['changefreq']['pages'],
            $config['priorities']['pages'],
            $totalUrls
        );
    }
}

// 文章分类
$terms = get_terms([
    'taxonomy' => 'category',
    'orderby'  => 'name',
    'hide_empty' => true,
    'exclude'  => $config['exclude']['categories'], // 排除指定分类
    'fields'   => 'all'
]);

if (!is_wp_error($terms) && !empty($terms)) {
    foreach ($terms as $term) {
        $term_link = get_term_link($term);
        if (!is_wp_error($term_link)) {
            render_sitemap_url(
                $term_link,
                '',
                $config['changefreq']['categories'],
                $config['priorities']['categories'],
                $totalUrls
            );
        }
    }
}

// 文章标签(可选)
if ($config['include_tags']) {
    $tags = get_terms([
        'taxonomy' => 'post_tag',
        'hide_empty' => true,
        'exclude'  => $config['exclude']['tags'], // 排除指定标签
        'fields'   => 'all'
    ]);
    
    if (!is_wp_error($tags) && !empty($tags)) {
        foreach ($tags as $tag) {
            $tag_link = get_term_link($tag);
            if (!is_wp_error($tag_link)) {
                render_sitemap_url(
                    $tag_link,
                    '',
                    $config['changefreq']['tags'],
                    $config['priorities']['tags'],
                    $totalUrls
                );
            }
        }
    }
}

// 日期归档(可选)
if ($config['include_archives']) {
    $archive_years = get_years();
    foreach ($archive_years as $year) {
        $archive_link = get_year_link($year);
        render_sitemap_url(
            $archive_link,
            '',
            $config['changefreq']['archives'],
            $config['priorities']['archives'],
            $totalUrls
        );
    }
}

echo '<!-- 总URL条目数: ' . $totalUrls . ' -->';
echo '</urlset>';

// 保存输出内容到缓存文件
$output = ob_get_clean();
file_put_contents($cacheFile, $output);

// 输出内容
echo $output;
?>

宝塔面板找到计划任务,选择shell脚本,若需要每天凌晨 2 点执行站点地图生成脚本,配置如下:

  • 任务类型:Shell 脚本
/www/server/php/你的PHP版本/bin/bin/php /www/wwwroot/你的域名/sitemap.php

(PHP 路径可在宝塔「PHP 管理」中查看,例如/www/server/php/82/bin/php

  • 执行周期:每天 02:00
  • 任务名称:每日更新站点地图
添加后,宝塔会在指定时间自动运行脚本,无需手动操作。你也可以在任务列表中点击「执行」按钮手动触发任务,验证是否能正常运行。

验证任务是否生效

  1. 配置完成后,点击任务列表中的「执行」按钮,手动触发一次
  2. 检查是否生成 / 更新了缓存文件(默认路径:/wp-content/sitemap-cache.xml
  3. 查看任务日志,确认无报错信息

注意事项

  • 权限问题:确保sitemap.php和缓存目录有写入权限(可在宝塔文件管理中右键设置「755 权限」)
  • 频率设置:内容更新频繁的网站建议每天更新,静态网站可每周更新一次
  • 多站点配置:若服务器有多个网站,需为每个站点单独创建定时任务,使用对应的路径
通过定时任务,站点地图会自动更新,无需手动操作,确保搜索引擎始终获取最新的网站结构。
  1. 主要输出文件(缓存文件)

    默认路径为:

    你的网站根目录/wp-content/sitemap-cache.xml

    例如:

    /www/wwwroot/你的域名/wp-content/sitemap-cache.xml

    这是实际生成的 XML 站点地图文件,包含所有 URL 信息,也是搜索引擎应该读取的文件。
  1. 为什么不是sitemap.xml

    代码中使用了缓存机制,生成的文件名为sitemap-cache.xml(而非直接生成sitemap.xml),原因是:

    • 避免直接覆盖可能已存在的手动创建的sitemap.xml
    • 缓存文件由脚本自动管理,定时任务会定期更新该文件
  2. 如何访问?

    可以通过网站域名直接访问:

    https://你的域名/wp-content/sitemap-cache.xml

如果需要自定义路径

若想修改生成的文件名或路径,可在代码中找到以下行进行调整:

$cacheFile = WP_CONTENT_DIR . '/sitemap-cache.xml';

例如,改为直接生成根目录下的sitemap.xml

$cacheFile = ABSPATH . '/sitemap.xml';

修改后,记得确保目标目录有写入权限,否则会导致生成失败。

打赏
免费GM传奇手游公益服安卓+IOS巨魔安装双端
上一篇
DOF端游详细图文架设教程-致敬阿拉德800万勇士
下一篇
博主索奈
Sonay
28 文章
0 评论
0 收藏
生成中...
二维码标题