本文约 4,216 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:写了三十篇书评,却发现没法”按评分看前十”
个人读书、观影、数码好物这三类内容的共同点是:每篇文章的字段非常固定——被评对象的信息、多维评分、总结论、购买参考。但很多站长直接用普通文章(post)去写,评分写在标题里,作者信息写在正文首段。结果是:想做一个”2024 年度十分以上”的榜单,只能手动翻全部文章;想按某导演聚合,压根做不到。信息被埋进了不可解析的正文里。把这类内容升级为「结构化实体」,是内容站从”日记”变成”数据库”的关键一步。
原理分析:把「作品」单独抽成一个实体
推荐的做法是:review 自定义文章类型承载文章本身,而把「被评测对象」(书/影/好物)用自定义字段或另一个 post type 保存。这样每一项评分、每一部元数据都是可查询的字段,WP_Query 的 meta_query 与 tax_query 都能用上。
常用三组外部数据源(均需自行申请或按其公共条款使用):电影元数据来自 TMDB API(themoviedb.org,GET /3/movie/{movie_id}),图书元数据可用 Open Library API(https://openlibrary.org/api/books?bibkeys=ISBN:{isbn}&format=json&jscmd=data),数码参数通常靠人工整理或品牌规格页抓取。调用时用 HTTP API 并把结果缓存起来,避免每次请求都打远端。
| 内容形态 | 建议维度 | 结论字段 |
|---|---|---|
| 书评 | 文字、结构、信息密度、可读性 | 一句话推荐 + 适合人群 |
| 影评 | 剧本、表演、视听、节奏 | 打分 + 观看场景 |
| 好物 | 做工、性能、性价比、售后 | 预算区间建议 |
保姆级实操
步骤 1:注册 review 与自定义分类。 rewrite 用中文 slug 无害,但为了兼容性与可读性建议用英文:
add_action( 'init', function () {
register_post_type( 'review', [
'labels' => [ 'name' => '评测', 'singular_name' => '评测' ],
'public' => true,
'has_archive' => true,
'rewrite' => [ 'slug' => 'review' ],
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ],
'show_in_rest' => true,
'menu_icon' => 'dashicons-star-filled',
] );
register_taxonomy( 'review_type', 'review', [
'labels' => [ 'name' => '评测类型' ],
'public' => true,
'rewrite' => [ 'slug' => 'review-type' ],
'show_in_rest' => true,
] );
} );
步骤 2:用 Advanced Custom Fields(ACF)建分组字段。 建立「评测信息」字段组:subject_title(对象名)、rating_total(总分)、rating_detail(多维评分,可用 repeater)、pros / cons( repeater)、isbn_or_id(外部 ID)。之后用 get_field() 取值。
步骤 3:外部元数据拉取与缓存。 用 wp_remote_get + transient 组合,避免每次渲染都打 TMDB:
function mf_fetch_movie( $tmdb_id ) {
$key = 'mf_tmdb_' . absint( $tmdb_id );
$cache = get_transient( $key );
if ( false !== $cache ) {
return $cache;
}
$res = wp_remote_get( sprintf(
'https://api.themoviedb.org/3/movie/%d?language=zh-CN',
$tmdb_id
), [
'timeout' => 10,
'headers' => [ 'Authorization' => 'Bearer ' . get_option( 'mf_tmdb_token' ) ],
] );
if ( is_wp_error( $res ) ) {
return [];
}
$data = json_decode( wp_remote_retrieve_body( $res ), true );
set_transient( $key, $data, DAY_IN_SECONDS * 7 );
return $data;
}
步骤 4:统一的模板输出。 在子主题里建 single-review.php,把评分条做成固定组件。评分条用 CSS 变量控制宽度:
.mf-rating { display: flex; align-items: center; gap: 8px; }
.mf-rating__bar { height: 8px; border-radius: 4px; background: #e5e7eb; overflow: hidden; flex: 1; }
.mf-rating__fill { height: 100%; background: linear-gradient(90deg,#f59e0b,#f97316); }
$rating = (float) get_field( 'rating_total' );
printf(
'<div class="mf-rating"><span>%.1f</span><div class="mf-rating__bar"><div class="mf-rating__fill" style="width:%d%%"></div></div></div>',
$rating,
(int) ( $rating * 10 )
);
步骤 5:做可排序的榜单页。 用 meta_query 按总分排序,配合分类过滤出”高分榜””近期更新”:
$q = new WP_Query( [
'post_type' => 'review',
'posts_per_page' => 10,
'tax_query' => [ [ 'taxonomy' => 'review_type', 'field' => 'slug', 'terms' => 'movie' ] ],
'meta_query' => [
'has_rating' => [ 'key' => 'rating_total', 'compare' => 'EXISTS', 'type' => 'DECIMAL(3,1)' ],
[ 'key' => 'rating_total', 'value' => 8, 'compare' => '>=', 'type' => 'DECIMAL(3,1)' ],
],
'orderby' => [ 'has_rating' => 'DESC', 'date' => 'DESC' ],
] );
步骤 6:固定三段式结论。 「谁适合 / 谁不适合」「同类替换方案」「购买注意点」三段必须有,它们是这类内容的差异化来源。WordPress 结构化数据评分标注
常见踩坑
- 评分存在
post_content里,meta_query排不了序,榜单页只能人工维护。 - 案例: 某影评站每次页面加载都直接调用 TMDB,某天对方 API 限流返回 429,整站首页出现 PHP Warning 且打开超时 8 秒以上,两天内搜索流量掉了一半。
meta_query忘记写type => 'DECIMAL',字符串比较导致 9.0 排在 10 分之前。- 新建了 post type 却直接写内容,没保存一次固定链接,前台 archive 404。
- 用了 EDITOR 不支持的自定义区块,古腾堡编辑时反复报 “此区块遇到问题”。
- 外部图片(TMDB 海报)直接热链,对方换 CDN 后整站海报全裂,应落地到媒体库。
- 好物类内容没有标清”自购/厂商提供”,读者会质疑中立性。WordPress 自定义文章类型实战
总结
评测类内容站的判断标准是:元信息是否结构化、能否在不改 PHP 的情况下出新榜单、结论是否落实到具体人群。行动清单:抽离 review post type → ACF 定义字段组 → 外部数据走缓存 → 输出统一组件模板 → 建 2-3 个榜单页。用同一套模板扎扎实实写三十篇,胜过洋洋洒洒写一百篇随笔。
