如何定制WordPress的Sitemap输出

对于SEO来说,sitemap是必备的,WordPress从5.5版本开始内置了sitemap的输出

默认情况下,WordPress会将站内所有文章类型(public)的列表(包括自定义文章),所有分类列表(taxonomy)以及有发布文章的作者列表都分别输出成xml格式的sitemap,然后用wp-sitemap.xml做一个索引。一般情况下,这样的输出就足够了。

但有时候需求会有点不一样,比如不想输出page类型,或者有些作者不想加入到作者列表中,等等。另一方面,因为是动态文件,所以如果流量比较大的网站,或者服务器不是太好的站点,在拉取sitemap的时候可能就比较吃资源,所以还会有优化的需求。

照例WordPress提供了一些勾子来解决这些定制需求。在官方sitemap说明文档中介绍了常用的几种情况:

  • 如何在sitemap中移除某种列表的输出
  • 如何在sitemap中移除某些不想要出现的文章类型列表
  • 如何在sitemap中移除某些不想要出现的分类类型列表
  • 如何定制在sitemap中出一的链接数据,如lastmod,changefreq和priority
  • 如何控制在sitemap中输出的具体列表内容
  • 如何关闭sitemap

以上问题都可以在WordPress官方sitemap说明文档中的Configuring Sitemaps Behavior一节中找到解决方案,这里不再赘述。

本文分享几个个人使用中的小技巧,直接上代码。

输出所有用户主页(或用户文章列表页)

1
2
3
4
5
6
7
add_filter(
'wp_sitemaps_users_query_args',
function( $args) {
$args['has_published_posts']=false;
return $args;
}
);

更改用户主页(或用户文章列表页)地址

1
2
3
4
add_filter('wp_sitemaps_users_entry',function( $entry,$user) {
$entry['loc']=home_url('/user/'.$user->ID);//需要更改的用户页地址
return $entry;
},10,2);

缓存所有文章类型列表的sitemap

使用wordpress的get_transientset_transient函数来缓存sitemap数据,则在以后拉取的时候不用再做sql查询。如果配合redis等缓存,则效果更佳。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
add_filter('wp_sitemaps_posts_pre_url_list',function($list,$post_type,$page_num){
$num=wp_sitemaps_get_max_urls('post');
$args=[
'orderby' => 'ID',
'order' => 'ASC',
'post_type' => $post_type,
'posts_per_page' => $num,
'post_status' => array( 'publish' ),
'no_found_rows' => true,
'fields' => 'ids',
];
$args['paged'] = $page_num;
$key='wp_sitemaps_posts_pre_url_list:'.$post_type.':'.$num.':'.$page_num;
if (false === ($data = get_transient($key))) {
$url_list=[];
$query = new WP_Query( $args );
foreach ( $query->posts as $post ) {
$url_list[] = [
'loc' => get_permalink( $post ),
];
}
if(count($url_list)>=$num) {//判断如果当前页输出还没到最大值,则不缓存该页数据,可以达到及时更新的目的。
set_transient($key,$url_list,0);
}
$data=$url_list;
}
if(!empty($data)) return $data;
return $list;

},10,3);

缓存所有作者列表的sitemap

默认的作者页输出时使用login及用户名首字母排序,我们将其改成ID排序,则除了最后一页之后,所有列表几乎不再更改,就可以使用缓存了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
add_filter('wp_sitemaps_users_pre_url_list',function($list,$page_num){
$num=wp_sitemaps_get_max_urls('user');
$args['has_published_posts'] = false;
$args['paged'] = $page_num;
$args['number']= $num;
$args['fields'] = ['ID'];
$args['orderby'] = ['ID'];
$key='wp_sitemaps_users_pre_url_list:'.$num.':'.$page_num;
if (false === ($data = get_transient($key))) {
$url_list=[];
$query = new WP_User_Query( $args );
$users = $query->get_results();
foreach ( $users as $user ) {
$url_list[] = [
'loc' => home_url( '/user/'.$user->ID ),
];
}
if(count($url_list)>=$num) {
set_transient($key,$url_list,0);
}
$data=$url_list;
}
if(!empty($data)) return $data;
return $list;
},10,2);

BTW

需要提交百度sitemap的童鞋一定要注意,百度已不支持索引型sitemap,所以必须要将wp-sitemap.xml中所列的地址一个一个提交到百度站长工具中。(并不明白为何百度要这样折磨站长们)