文章目录
-
- 在信息爆炸的互联网时代,用户浏览网页的时间越来越碎片化。根据研究,普通用户在决定是否继续阅读一篇文章前,平均只会花费15秒浏览页面内容。一个精心设计的摘要不仅能帮助用户快速了解文章核心内容,还能显著提高页面停留时间和内容转化率。 传统的WordPress摘要功能通常只是简单截取文章开头部分文字,这种方法往往无法准确反映文章的核心观点。而智能摘要生成器通过算法分析文章内容,提取关键信息,生成简洁、准确的摘要,为用户提供更好的阅读体验。 本文将带你从零开始,通过WordPress代码二次开发,为你的网站添加一个智能化的内容自动摘要生成器。无论你是WordPress开发者还是有一定技术基础的网站管理员,都能通过本教程实现这一功能。
-
- 在开始开发之前,我们需要了解WordPress默认的摘要系统是如何工作的: WordPress使用the_excerpt()函数显示摘要 默认情况下,如果没有手动设置摘要,WordPress会自动截取文章前55个单词 可以通过excerpt_length过滤器修改摘要长度 可以通过excerpt_more过滤器修改摘要末尾的"阅读更多"文本
- 为了安全地进行代码开发,我们建议采取以下步骤: 备份你的网站:在进行任何代码修改前,请务必备份整个网站和数据库 创建子主题:如果你正在使用主题,建议创建子主题进行修改 启用调试模式:在wp-config.php中添加以下代码以便查看错误信息: define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); 安装代码编辑器:推荐使用VS Code、Sublime Text或PHPStorm
- 我们的智能摘要生成器将包含以下组件: 文本处理模块:清理和预处理文章内容 关键词提取模块:识别文章中的关键术语和概念 摘要生成算法:基于文本分析生成连贯摘要 缓存机制:提高性能,避免重复处理相同内容 管理界面:允许用户配置摘要生成参数
-
- 首先,我们创建一个独立的WordPress插件来实现这个功能: 在wp-content/plugins/目录下创建新文件夹smart-excerpt-generator 在该文件夹中创建以下文件: smart-excerpt-generator.php (主插件文件) includes/ (目录) class-text-processor.php class-keyword-extractor.php class-summary-generator.php assets/ (目录) css/admin-style.css js/admin-script.js templates/ (目录) admin-settings.php
- 打开smart-excerpt-generator.php,添加以下代码: <?php /** * Plugin Name: 智能摘要生成器 * Plugin URI: https://yourwebsite.com/ * Description: 为WordPress文章自动生成智能摘要 * Version: 1.0.0 * Author: 你的名字 * License: GPL v2 or later * Text Domain: smart-excerpt */ // 防止直接访问 if (!defined('ABSPATH')) { exit; } // 定义插件常量 define('SEG_VERSION', '1.0.0'); define('SEG_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('SEG_PLUGIN_URL', plugin_dir_url(__FILE__)); // 自动加载类文件 spl_autoload_register(function ($class) { $prefix = 'SmartExcerpt\'; $base_dir = SEG_PLUGIN_DIR . 'includes/'; $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { return; } $relative_class = substr($class, $len); $file = $base_dir . str_replace('\', '/', $relative_class) . '.php'; if (file_exists($file)) { require $file; } }); // 初始化插件 function seg_init_plugin() { // 检查PHP版本 if (version_compare(PHP_VERSION, '7.0.0', '<')) { add_action('admin_notices', function() { echo '<div class="notice notice-error"><p>'; echo '智能摘要生成器需要PHP 7.0或更高版本。当前版本:' . PHP_VERSION; echo '</p></div>'; }); return; } // 实例化主控制器 $plugin = new SmartExcerptMainController(); $plugin->run(); } add_action('plugins_loaded', 'seg_init_plugin');
- 在includes/目录下创建class-text-processor.php: <?php namespace SmartExcerpt; class TextProcessor { /** * 清理HTML内容,提取纯文本 */ public function extract_plain_text($content) { // 移除HTML标签 $text = strip_tags($content); // 解码HTML实体 $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8'); // 移除多余空白字符 $text = preg_replace('/s+/', ' ', $text); // 移除短代码 $text = strip_shortcodes($text); return trim($text); } /** * 将文本分割成句子 */ public function split_into_sentences($text) { // 使用正则表达式分割句子 $sentences = preg_split('/(?<=[.?!。?!])s+/', $text, -1, PREG_SPLIT_NO_EMPTY); // 过滤空句子和过短句子 $sentences = array_filter($sentences, function($sentence) { return strlen(trim($sentence)) > 10; }); return array_values($sentences); } /** * 计算句子权重 */ public function calculate_sentence_score($sentence, $keywords) { $score = 0; // 基于关键词出现频率评分 foreach ($keywords as $keyword => $weight) { $count = substr_count(strtolower($sentence), strtolower($keyword)); $score += $count * $weight; } // 基于句子位置评分(开头和结尾的句子通常更重要) // 这个因素将在调用此方法时通过参数传递 // 基于句子长度评分(中等长度的句子通常包含更多信息) $length = strlen($sentence); if ($length > 50 && $length < 200) { $score += 2; } return $score; } }
- 在includes/目录下创建class-keyword-extractor.php: <?php namespace SmartExcerpt; class KeywordExtractor { private $stop_words; public function __construct() { // 中文停用词列表(部分示例) $this->stop_words = [ '的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这', 'the', 'and', 'a', 'an', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'being' ]; } /** * 从文本中提取关键词 */ public function extract($text, $max_keywords = 10) { // 分词处理(简化版,实际应用中可能需要使用分词库) $words = $this->tokenize($text); // 移除停用词 $words = $this->remove_stop_words($words); // 计算词频 $word_freq = array_count_values($words); // 按频率排序 arsort($word_freq); // 取前N个关键词 $keywords = array_slice($word_freq, 0, $max_keywords, true); // 计算权重(归一化处理) $total = array_sum($keywords); $weighted_keywords = []; foreach ($keywords as $word => $count) { $weighted_keywords[$word] = $count / $total * 100; } return $weighted_keywords; } /** * 简单分词函数(针对中文和英文) */ private function tokenize($text) { // 将文本转换为小写 $text = mb_strtolower($text, 'UTF-8'); // 使用正则表达式分割单词 // 匹配中文词语和英文单词 preg_match_all('/[x{4e00}-x{9fa5}]|[a-zA-Z]+/', $text, $matches); return $matches[0]; } /** * 移除停用词 */ private function remove_stop_words($words) { return array_filter($words, function($word) { return !in_array($word, $this->stop_words) && strlen($word) > 1; }); } }
-
- 在includes/目录下创建class-summary-generator.php: <?php namespace SmartExcerpt; class SummaryGenerator { private $text_processor; private $keyword_extractor; public function __construct() { $this->text_processor = new TextProcessor(); $this->keyword_extractor = new KeywordExtractor(); } /** * 生成文章摘要 */ public function generate($content, $max_length = 150) { // 检查是否有缓存 $cache_key = 'seg_summary_' . md5($content . $max_length); $cached_summary = get_transient($cache_key); if ($cached_summary !== false) { return $cached_summary; } // 提取纯文本 $plain_text = $this->text_processor->extract_plain_text($content); // 如果文本太短,直接返回 if (strlen($plain_text) < $max_length) { return $plain_text; } // 提取关键词 $keywords = $this->keyword_extractor->extract($plain_text); // 分割成句子 $sentences = $this->text_processor->split_into_sentences($plain_text); // 计算每个句子的得分 $scored_sentences = []; $total_sentences = count($sentences); foreach ($sentences as $index => $sentence) { $score = $this->text_processor->calculate_sentence_score($sentence, $keywords); // 基于句子位置调整分数 $position_score = $this->calculate_position_score($index, $total_sentences); $score += $position_score; $scored_sentences[] = [ 'text' => $sentence, 'score' => $score, 'index' => $index ]; } // 按分数排序 usort($scored_sentences, function($a, $b) { return $b['score'] <=> $a['score']; }); // 选择最佳句子生成摘要 $selected_sentences = []; $current_length = 0; foreach ($scored_sentences as $sentence) { $sentence_length = strlen($sentence['text']); if ($current_length + $sentence_length <= $max_length) { $selected_sentences[] = $sentence; $current_length += $sentence_length; } if ($current_length >= $max_length * 0.8) { break; } } // 按原始顺序排序选中的句子 usort($selected_sentences, function($a, $b) { return $a['index'] <=> $b['index']; }); // 构建摘要 $summary = ''; foreach ($selected_sentences as $sentence) { $summary .= $sentence['text'] . ' '; } $summary = trim($summary); // 如果摘要太短,使用传统方法生成 if (strlen($summary) < $max_length * 0.5) { $summary = $this->generate_fallback_summary($plain_text, $max_length); } // 缓存结果(24小时) set_transient($cache_key, $summary, DAY_IN_SECONDS); return $summary; } /** * 计算句子位置分数 */ private function calculate_position_score($index, $total) { // 开头和结尾的句子通常更重要 $position = $index / max(1, $total - 1); if ($position < 0.1) { // 前10% return 3; } elseif ($position > 0.9) { // 后10% return 2; } elseif ($position < 0.2) { // 前10%-20% return 1; } return 0; } /** * 备用摘要生成方法 */ private function generate_fallback_summary($text, $max_length) { // 简单截取前N个字符,确保在完整单词处结束 if (strlen($text) <= $max_length) { return $text; } $truncated = substr($text, 0, $max_length); $last_space = strrpos($truncated, ' '); if ($last_space !== false) { $truncated = substr($truncated, 0, $last_space); } return $truncated . '...'; } }
- 在includes/目录下创建class-main-controller.php: <?php namespace SmartExcerpt; class MainController { private $summary_generator; public function __construct() { $this->summary_generator = new SummaryGenerator(); } public function run() { // 初始化钩子 $this->init_hooks(); } private function init_hooks() { // 替换默认的摘要生成函数 add_filter('get_the_excerpt', [$this, 'filter_the_excerpt'], 10, 2); // 添加快捷码支持 add_shortcode('smart_excerpt', [$this, 'shortcode_smart_excerpt']); // 添加RSS摘要支持 add_filter('the_excerpt_rss', [$this, 'filter_rss_excerpt']); // 添加管理菜单 add_action('admin_menu', [$this, 'add_admin_menu']); // 添加设置链接 add_filter('plugin_action_links_' . plugin_basename(SEG_PLUGIN_DIR . 'smart-excerpt-generator.php'), [$this, 'add_settings_link']); } /** * 过滤文章摘要 */ public function filter_the_excerpt($excerpt, $post) { // 如果已经有手动设置的摘要,直接返回 if (!empty($excerpt)) { return $excerpt; } // 获取文章内容 $content = $post->post_content; // 获取摘要长度设置 $length = get_option('seg_excerpt_length', 150); // 生成智能摘要 $smart_excerpt = $this->summary_generator->generate($content, $length); // 添加"阅读更多"链接 $more_text = get_option('seg_excerpt_more', '... 阅读更多'); $smart_excerpt .= ' <a href="' . get_permalink($post->ID) . '" class="read-more">' . $more_text . '</a>'; return $smart_excerpt; } /** * 快捷码函数 */ public function shortcode_smart_excerpt($atts) { $atts = shortcode_atts([ 'length' => 150, 'post_id' => null, 'more_text' => '...' ], $atts); $post_id = $atts['post_id'] ?: get_the_ID(); $post = get_post($post_id); if (!$post) { return ''; } $excerpt = $this->summary_generator->generate($post->post_content, $atts['length']); if (!empty($atts['more_text'])) { $excerpt .= ' <a href="' . get_permalink($post_id) . '">' . $atts['more_text'] . '</a>'; } return '<div class="smart-excerpt">' . $excerpt . '</div>'; } /** * 过滤RSS摘要 */ public function filter_rss_excerpt($excerpt) { global $post; if (get_option('seg_enable_for_rss', false)) { $length = get_option('seg_rss_excerpt_length', 100); return $this->summary_generator->generate($post->post_content, $length); } return $excerpt; } /** * 添加管理菜单 */ public function add_admin_menu() { add_options_page(
-
- /** * 添加管理菜单 */ public function add_admin_menu() { add_options_page( '智能摘要设置', '智能摘要', 'manage_options', 'smart-excerpt-settings', [$this, 'render_settings_page'] ); } /** * 添加设置链接到插件列表 */ public function add_settings_link($links) { $settings_link = '<a href="' . admin_url('options-general.php?page=smart-excerpt-settings') . '">设置</a>'; array_unshift($links, $settings_link); return $links; } /** * 渲染设置页面 */ public function render_settings_page() { // 检查用户权限 if (!current_user_can('manage_options')) { wp_die('您没有权限访问此页面'); } // 保存设置 if (isset($_POST['submit_settings']) && check_admin_referer('seg_settings_nonce')) { $this->save_settings(); echo '<div class="notice notice-success"><p>设置已保存!</p></div>'; } // 加载设置页面模板 include SEG_PLUGIN_DIR . 'templates/admin-settings.php'; } /** * 保存设置 */ private function save_settings() { // 摘要长度 if (isset($_POST['excerpt_length'])) { $length = intval($_POST['excerpt_length']); if ($length > 0) { update_option('seg_excerpt_length', $length); } } // "阅读更多"文本 if (isset($_POST['excerpt_more'])) { update_option('seg_excerpt_more', sanitize_text_field($_POST['excerpt_more'])); } // 是否启用RSS摘要 $enable_rss = isset($_POST['enable_rss']) ? 1 : 0; update_option('seg_enable_for_rss', $enable_rss); // RSS摘要长度 if (isset($_POST['rss_excerpt_length'])) { $rss_length = intval($_POST['rss_excerpt_length']); if ($rss_length > 0) { update_option('seg_rss_excerpt_length', $rss_length); } } // 是否启用缓存 $enable_cache = isset($_POST['enable_cache']) ? 1 : 0; update_option('seg_enable_cache', $enable_cache); // 缓存过期时间 if (isset($_POST['cache_expiration'])) { $expiration = intval($_POST['cache_expiration']); if ($expiration > 0) { update_option('seg_cache_expiration', $expiration); } } // 是否在文章编辑页面显示摘要预览 $show_preview = isset($_POST['show_preview']) ? 1 : 0; update_option('seg_show_preview', $show_preview); } }
- 在templates/目录下创建admin-settings.php: <div class="wrap"> <h1>智能摘要生成器设置</h1> <form method="post" action=""> <?php wp_nonce_field('seg_settings_nonce'); ?> <table class="form-table"> <tr> <th scope="row"> <label for="excerpt_length">摘要长度(字符数)</label> </th> <td> <input type="number" id="excerpt_length" name="excerpt_length" value="<?php echo esc_attr(get_option('seg_excerpt_length', 150)); ?>" min="50" max="500" step="10"> <p class="description">摘要的最大字符长度,建议值:150-200</p> </td> </tr> <tr> <th scope="row"> <label for="excerpt_more">"阅读更多"文本</label> </th> <td> <input type="text" id="excerpt_more" name="excerpt_more" value="<?php echo esc_attr(get_option('seg_excerpt_more', '... 阅读更多')); ?>" class="regular-text"> <p class="description">摘要末尾显示的"阅读更多"链接文本</p> </td> </tr> <tr> <th scope="row">RSS摘要设置</th> <td> <label> <input type="checkbox" id="enable_rss" name="enable_rss" value="1" <?php checked(get_option('seg_enable_for_rss', false)); ?>> 为RSS订阅启用智能摘要 </label> <div style="margin-top: 10px;"> <label for="rss_excerpt_length">RSS摘要长度:</label> <input type="number" id="rss_excerpt_length" name="rss_excerpt_length" value="<?php echo esc_attr(get_option('seg_rss_excerpt_length', 100)); ?>" min="50" max="300" step="10"> </div> </td> </tr> <tr> <th scope="row">缓存设置</th> <td> <label> <input type="checkbox" id="enable_cache" name="enable_cache" value="1" <?php checked(get_option('seg_enable_cache', true)); ?>> 启用摘要缓存 </label> <div style="margin-top: 10px;"> <label for="cache_expiration">缓存过期时间(小时):</label> <input type="number" id="cache_expiration" name="cache_expiration" value="<?php echo esc_attr(get_option('seg_cache_expiration', 24)); ?>" min="1" max="720" step="1"> <p class="description">缓存摘要结果以提高性能</p> </div> </td> </tr> <tr> <th scope="row">文章编辑页面</th> <td> <label> <input type="checkbox" id="show_preview" name="show_preview" value="1" <?php checked(get_option('seg_show_preview', true)); ?>> 显示摘要预览 </label> <p class="description">在文章编辑页面显示自动生成的摘要预览</p> </td> </tr> <tr> <th scope="row">摘要生成测试</th> <td> <button type="button" id="test_summary" class="button">测试摘要生成</button> <div id="test_result" style="margin-top: 10px; padding: 10px; background: #f5f5f5; display: none;"></div> </td> </tr> </table> <p class="submit"> <input type="submit" name="submit_settings" class="button-primary" value="保存设置"> <button type="button" id="clear_cache" class="button">清除缓存</button> </p> </form> <div class="card"> <h2>使用说明</h2> <p>1. 智能摘要会自动替换WordPress默认的摘要生成功能</p> <p>2. 如果文章已有手动设置的摘要,将优先使用手动摘要</p> <p>3. 在文章中使用短码:[smart_excerpt length="200" more_text="查看更多"]</p> <p>4. 可以通过过滤器自定义摘要生成行为,详见插件文档</p> </div> </div> <script> jQuery(document).ready(function($) { // 测试摘要生成 $('#test_summary').on('click', function() { var testText = "人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器。该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大。可以设想,未来人工智能带来的科技产品,将会是人类智慧的容器。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考,也可能超过人的智能。"; $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'seg_test_summary', text: testText, length: $('#excerpt_length').val() }, success: function(response) { $('#test_result').html('<strong>测试结果:</strong><br>' + response).show(); } }); }); // 清除缓存 $('#clear_cache').on('click', function(e) { e.preventDefault(); if (confirm('确定要清除所有摘要缓存吗?')) { $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'seg_clear_cache' }, success: function(response) { alert(response.message); } }); } }); }); </script>
- 在主控制器类中添加AJAX处理方法: // 在MainController类的init_hooks方法中添加: add_action('wp_ajax_seg_test_summary', [$this, 'ajax_test_summary']); add_action('wp_ajax_seg_clear_cache', [$this, 'ajax_clear_cache']); // 添加文章编辑页面摘要预览 add_action('add_meta_boxes', [$this, 'add_excerpt_preview_metabox']); // 在MainController类中添加新方法: /** * AJAX测试摘要生成 */ public function ajax_test_summary() { if (!current_user_can('manage_options')) { wp_die('权限不足'); } $text = isset($_POST['text']) ? $_POST['text'] : ''; $length = isset($_POST['length']) ? intval($_POST['length']) : 150; if (empty($text)) { wp_die('请输入测试文本'); } $summary = $this->summary_generator->generate($text, $length); echo wp_kses_post($summary); wp_die(); } /** * AJAX清除缓存 */ public function ajax_clear_cache() { if (!current_user_can('manage_options')) { wp_send_json_error(['message' => '权限不足']); } global $wpdb; // 删除所有智能摘要缓存 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '_transient_seg_summary_%' ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '_transient_timeout_seg_summary_%' ) ); wp_send_json_success(['message' => '缓存已清除']); } /** * 添加摘要预览元框 */ public function add_excerpt_preview_metabox() { if (get_option('seg_show_preview', true)) { add_meta_box( 'seg_excerpt_preview', '智能摘要预览', [$this, 'render_excerpt_preview_metabox'], 'post', 'side', 'high' ); } } /** * 渲染摘要预览元框 */ public function render_excerpt_preview_metabox($post) { $content = $post->post_content; $length = get_option('seg_excerpt_length', 150); echo '<div id="seg_preview_container">'; echo '<p>自动生成的摘要预览:</p>'; echo '<div id="seg_preview_content" style="background: #f5f5f5; padding: 10px; border-radius: 3px; min-height: 100px;">'; if (!empty($content)) { $preview = $this->summary_generator->generate($content, $length); echo wp_kses_post($preview); } else { echo '<em>请输入文章内容以查看摘要预览</em>'; } echo '</div>'; echo '<button type="button" id="seg_refresh_preview" class="button button-small" style="margin-top: 10px;">刷新预览</button>'; echo '</div>'; // 添加JavaScript ?> <script> jQuery(document).ready(function($) { // 刷新预览 $('#seg_refresh_preview').on('click', function() { var content = $('#content').val(); var length = <?php echo $length; ?>; $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'seg_update_preview', content: content, length: length, post_id: <?php echo $post->ID; ?>, nonce: '<?php echo wp_create_nonce('seg_preview_nonce'); ?>' }, success: function(response) { if (response.success) { $('#seg_preview_content').html(response.data); } } }); }); // 自动刷新预览(每30秒) setInterval(function() { if ($('#content').is(':focus')) { $('#seg_refresh_preview').click(); } }, 30000); }); </script> <?php } // 添加预览更新AJAX处理 add_action('wp_ajax_seg_update_preview', [$this, 'ajax_update_preview']); /** * AJAX更新预览 */ public function ajax_update_preview() { check_ajax_referer('seg_preview_nonce', 'nonce'); if (!current_user_can('edit_posts')) { wp_send_json_error('权限不足'); } $content = isset($_POST['content']) ? $_POST['content'] : ''; $length = isset($_POST['length']) ? intval($_POST['length']) : 150; if (empty($content)) { wp_send_json_success('<em>请输入文章内容以查看摘要预览</em>'); } $summary = $this->summary_generator->generate($content, $length); wp_send_json_success(wp_kses_post($summary)); }
-
- 为了让其他开发者可以自定义摘要生成行为,我们添加一些过滤器: // 在SummaryGenerator类的generate方法开始处添加: $content = apply_filters('seg_before_generate', $content, $max_length); // 在生成摘要后添加: $summary = apply_filters('seg_after_generate', $summary, $content, $max_length); // 在MainController类的filter_the_excerpt方法中添加: $smart_excerpt = apply_filters('seg_custom_excerpt', $smart_excerpt, $post, $length); // 创建新的过滤器类 // 在includes/目录下创建class-custom-filters.php: <?php namespace SmartExcerpt; class CustomFilters { /** * 示例过滤器:为特定分类的文章添加前缀 */ public static function add_category_prefix($excerpt, $post, $length) { $categories = get_the_category($post->ID); if (!empty($categories)) { $category_names = array_map(function($cat) { return $cat->name; }, $categories); $prefix = '【' . implode('、', $category_names) . '】'; $excerpt = $prefix . ' ' . $excerpt; } return $excerpt; } /** * 示例过滤器:移除摘要中的短链接 */ public static function remove_short_urls($summary, $content, $max_length) { // 移除类似bit.ly、t.cn等短链接 $summary = preg_replace('/b(https?://)?(bit.ly|t.cn|goo.gl|tinyurl.com)/S+/i', '', $summary); return trim($summary); } /** * 示例过滤器:为长摘要添加分页 */ public static function add_pagination($excerpt, $post) { $full_content = $post->post_content; $excerpt_length = strlen($excerpt); $full_length = strlen(strip_tags($full_content)); if ($full_length > $excerpt_length * 2) { $excerpt .= ' <span class="summary-pagination">[1/2]</span>'; } return $excerpt; } } // 在MainController类的init_hooks方法中添加过滤器示例: add_filter('seg_custom_excerpt', ['SmartExcerptCustomFilters', 'add_category_prefix'], 10, 3); add_filter('seg_after_generate', ['SmartExcerptCustomFilters', 'remove_short_urls'], 10, 3);
- // 在includes/目录下创建class-performance-optimizer.php: <?php namespace SmartExcerpt; class PerformanceOptimizer { /** * 批量生成摘要缓存 */ public static function batch_generate_cache($post_ids = []) { if (empty($post_ids)) { // 获取最近100篇文章 $args = [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 100, 'fields' => 'ids' ]; $query = new WP_Query($args); $post_ids = $query->posts; } $summary_generator = new SummaryGenerator(); $results = [ 'total' => count($post_ids),
在信息爆炸的互联网时代,用户浏览网页的时间越来越碎片化。根据研究,普通用户在决定是否继续阅读一篇文章前,平均只会花费15秒浏览页面内容。一个精心设计的摘要不仅能帮助用户快速了解文章核心内容,还能显著提高页面停留时间和内容转化率。
传统的WordPress摘要功能通常只是简单截取文章开头部分文字,这种方法往往无法准确反映文章的核心观点。而智能摘要生成器通过算法分析文章内容,提取关键信息,生成简洁、准确的摘要,为用户提供更好的阅读体验。
本文将带你从零开始,通过WordPress代码二次开发,为你的网站添加一个智能化的内容自动摘要生成器。无论你是WordPress开发者还是有一定技术基础的网站管理员,都能通过本教程实现这一功能。
在开始开发之前,我们需要了解WordPress默认的摘要系统是如何工作的:
- WordPress使用
the_excerpt()函数显示摘要 - 默认情况下,如果没有手动设置摘要,WordPress会自动截取文章前55个单词
- 可以通过
excerpt_length过滤器修改摘要长度 - 可以通过
excerpt_more过滤器修改摘要末尾的"阅读更多"文本
为了安全地进行代码开发,我们建议采取以下步骤:
- 备份你的网站:在进行任何代码修改前,请务必备份整个网站和数据库
- 创建子主题:如果你正在使用主题,建议创建子主题进行修改
-
启用调试模式:在wp-config.php中添加以下代码以便查看错误信息:
define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false); - 安装代码编辑器:推荐使用VS Code、Sublime Text或PHPStorm
我们的智能摘要生成器将包含以下组件:
- 文本处理模块:清理和预处理文章内容
- 关键词提取模块:识别文章中的关键术语和概念
- 摘要生成算法:基于文本分析生成连贯摘要
- 缓存机制:提高性能,避免重复处理相同内容
- 管理界面:允许用户配置摘要生成参数
首先,我们创建一个独立的WordPress插件来实现这个功能:
- 在wp-content/plugins/目录下创建新文件夹
smart-excerpt-generator -
在该文件夹中创建以下文件:
- smart-excerpt-generator.php (主插件文件)
-
includes/ (目录)
- class-text-processor.php
- class-keyword-extractor.php
- class-summary-generator.php
-
assets/ (目录)
- css/admin-style.css
- js/admin-script.js
-
templates/ (目录)
- admin-settings.php
打开smart-excerpt-generator.php,添加以下代码:
<?php
/**
* Plugin Name: 智能摘要生成器
* Plugin URI: https://yourwebsite.com/
* Description: 为WordPress文章自动生成智能摘要
* Version: 1.0.0
* Author: 你的名字
* License: GPL v2 or later
* Text Domain: smart-excerpt
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('SEG_VERSION', '1.0.0');
define('SEG_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('SEG_PLUGIN_URL', plugin_dir_url(__FILE__));
// 自动加载类文件
spl_autoload_register(function ($class) {
$prefix = 'SmartExcerpt\';
$base_dir = SEG_PLUGIN_DIR . 'includes/';
$len = strlen($prefix);
if (strncmp($prefix, $class, $len) !== 0) {
return;
}
$relative_class = substr($class, $len);
$file = $base_dir . str_replace('\', '/', $relative_class) . '.php';
if (file_exists($file)) {
require $file;
}
});
// 初始化插件
function seg_init_plugin() {
// 检查PHP版本
if (version_compare(PHP_VERSION, '7.0.0', '<')) {
add_action('admin_notices', function() {
echo '<div class="notice notice-error"><p>';
echo '智能摘要生成器需要PHP 7.0或更高版本。当前版本:' . PHP_VERSION;
echo '</p></div>';
});
return;
}
// 实例化主控制器
$plugin = new SmartExcerptMainController();
$plugin->run();
}
add_action('plugins_loaded', 'seg_init_plugin');
在includes/目录下创建class-text-processor.php:
<?php
namespace SmartExcerpt;
class TextProcessor {
/**
* 清理HTML内容,提取纯文本
*/
public function extract_plain_text($content) {
// 移除HTML标签
$text = strip_tags($content);
// 解码HTML实体
$text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// 移除多余空白字符
$text = preg_replace('/s+/', ' ', $text);
// 移除短代码
$text = strip_shortcodes($text);
return trim($text);
}
/**
* 将文本分割成句子
*/
public function split_into_sentences($text) {
// 使用正则表达式分割句子
$sentences = preg_split('/(?<=[.?!。?!])s+/', $text, -1, PREG_SPLIT_NO_EMPTY);
// 过滤空句子和过短句子
$sentences = array_filter($sentences, function($sentence) {
return strlen(trim($sentence)) > 10;
});
return array_values($sentences);
}
/**
* 计算句子权重
*/
public function calculate_sentence_score($sentence, $keywords) {
$score = 0;
// 基于关键词出现频率评分
foreach ($keywords as $keyword => $weight) {
$count = substr_count(strtolower($sentence), strtolower($keyword));
$score += $count * $weight;
}
// 基于句子位置评分(开头和结尾的句子通常更重要)
// 这个因素将在调用此方法时通过参数传递
// 基于句子长度评分(中等长度的句子通常包含更多信息)
$length = strlen($sentence);
if ($length > 50 && $length < 200) {
$score += 2;
}
return $score;
}
}
在includes/目录下创建class-keyword-extractor.php:
<?php
namespace SmartExcerpt;
class KeywordExtractor {
private $stop_words;
public function __construct() {
// 中文停用词列表(部分示例)
$this->stop_words = [
'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这',
'the', 'and', 'a', 'an', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'being'
];
}
/**
* 从文本中提取关键词
*/
public function extract($text, $max_keywords = 10) {
// 分词处理(简化版,实际应用中可能需要使用分词库)
$words = $this->tokenize($text);
// 移除停用词
$words = $this->remove_stop_words($words);
// 计算词频
$word_freq = array_count_values($words);
// 按频率排序
arsort($word_freq);
// 取前N个关键词
$keywords = array_slice($word_freq, 0, $max_keywords, true);
// 计算权重(归一化处理)
$total = array_sum($keywords);
$weighted_keywords = [];
foreach ($keywords as $word => $count) {
$weighted_keywords[$word] = $count / $total * 100;
}
return $weighted_keywords;
}
/**
* 简单分词函数(针对中文和英文)
*/
private function tokenize($text) {
// 将文本转换为小写
$text = mb_strtolower($text, 'UTF-8');
// 使用正则表达式分割单词
// 匹配中文词语和英文单词
preg_match_all('/[x{4e00}-x{9fa5}]|[a-zA-Z]+/', $text, $matches);
return $matches[0];
}
/**
* 移除停用词
*/
private function remove_stop_words($words) {
return array_filter($words, function($word) {
return !in_array($word, $this->stop_words) && strlen($word) > 1;
});
}
}
在includes/目录下创建class-summary-generator.php:
<?php
namespace SmartExcerpt;
class SummaryGenerator {
private $text_processor;
private $keyword_extractor;
public function __construct() {
$this->text_processor = new TextProcessor();
$this->keyword_extractor = new KeywordExtractor();
}
/**
* 生成文章摘要
*/
public function generate($content, $max_length = 150) {
// 检查是否有缓存
$cache_key = 'seg_summary_' . md5($content . $max_length);
$cached_summary = get_transient($cache_key);
if ($cached_summary !== false) {
return $cached_summary;
}
// 提取纯文本
$plain_text = $this->text_processor->extract_plain_text($content);
// 如果文本太短,直接返回
if (strlen($plain_text) < $max_length) {
return $plain_text;
}
// 提取关键词
$keywords = $this->keyword_extractor->extract($plain_text);
// 分割成句子
$sentences = $this->text_processor->split_into_sentences($plain_text);
// 计算每个句子的得分
$scored_sentences = [];
$total_sentences = count($sentences);
foreach ($sentences as $index => $sentence) {
$score = $this->text_processor->calculate_sentence_score($sentence, $keywords);
// 基于句子位置调整分数
$position_score = $this->calculate_position_score($index, $total_sentences);
$score += $position_score;
$scored_sentences[] = [
'text' => $sentence,
'score' => $score,
'index' => $index
];
}
// 按分数排序
usort($scored_sentences, function($a, $b) {
return $b['score'] <=> $a['score'];
});
// 选择最佳句子生成摘要
$selected_sentences = [];
$current_length = 0;
foreach ($scored_sentences as $sentence) {
$sentence_length = strlen($sentence['text']);
if ($current_length + $sentence_length <= $max_length) {
$selected_sentences[] = $sentence;
$current_length += $sentence_length;
}
if ($current_length >= $max_length * 0.8) {
break;
}
}
// 按原始顺序排序选中的句子
usort($selected_sentences, function($a, $b) {
return $a['index'] <=> $b['index'];
});
// 构建摘要
$summary = '';
foreach ($selected_sentences as $sentence) {
$summary .= $sentence['text'] . ' ';
}
$summary = trim($summary);
// 如果摘要太短,使用传统方法生成
if (strlen($summary) < $max_length * 0.5) {
$summary = $this->generate_fallback_summary($plain_text, $max_length);
}
// 缓存结果(24小时)
set_transient($cache_key, $summary, DAY_IN_SECONDS);
return $summary;
}
/**
* 计算句子位置分数
*/
private function calculate_position_score($index, $total) {
// 开头和结尾的句子通常更重要
$position = $index / max(1, $total - 1);
if ($position < 0.1) { // 前10%
return 3;
} elseif ($position > 0.9) { // 后10%
return 2;
} elseif ($position < 0.2) { // 前10%-20%
return 1;
}
return 0;
}
/**
* 备用摘要生成方法
*/
private function generate_fallback_summary($text, $max_length) {
// 简单截取前N个字符,确保在完整单词处结束
if (strlen($text) <= $max_length) {
return $text;
}
$truncated = substr($text, 0, $max_length);
$last_space = strrpos($truncated, ' ');
if ($last_space !== false) {
$truncated = substr($truncated, 0, $last_space);
}
return $truncated . '...';
}
}
在includes/目录下创建class-main-controller.php:
<?php
namespace SmartExcerpt;
class MainController {
private $summary_generator;
public function __construct() {
$this->summary_generator = new SummaryGenerator();
}
public function run() {
// 初始化钩子
$this->init_hooks();
}
private function init_hooks() {
// 替换默认的摘要生成函数
add_filter('get_the_excerpt', [$this, 'filter_the_excerpt'], 10, 2);
// 添加快捷码支持
add_shortcode('smart_excerpt', [$this, 'shortcode_smart_excerpt']);
// 添加RSS摘要支持
add_filter('the_excerpt_rss', [$this, 'filter_rss_excerpt']);
// 添加管理菜单
add_action('admin_menu', [$this, 'add_admin_menu']);
// 添加设置链接
add_filter('plugin_action_links_' . plugin_basename(SEG_PLUGIN_DIR . 'smart-excerpt-generator.php'),
[$this, 'add_settings_link']);
}
/**
* 过滤文章摘要
*/
public function filter_the_excerpt($excerpt, $post) {
// 如果已经有手动设置的摘要,直接返回
if (!empty($excerpt)) {
return $excerpt;
}
// 获取文章内容
$content = $post->post_content;
// 获取摘要长度设置
$length = get_option('seg_excerpt_length', 150);
// 生成智能摘要
$smart_excerpt = $this->summary_generator->generate($content, $length);
// 添加"阅读更多"链接
$more_text = get_option('seg_excerpt_more', '... 阅读更多');
$smart_excerpt .= ' <a href="' . get_permalink($post->ID) . '" class="read-more">' . $more_text . '</a>';
return $smart_excerpt;
}
/**
* 快捷码函数
*/
public function shortcode_smart_excerpt($atts) {
$atts = shortcode_atts([
'length' => 150,
'post_id' => null,
'more_text' => '...'
], $atts);
$post_id = $atts['post_id'] ?: get_the_ID();
$post = get_post($post_id);
if (!$post) {
return '';
}
$excerpt = $this->summary_generator->generate($post->post_content, $atts['length']);
if (!empty($atts['more_text'])) {
$excerpt .= ' <a href="' . get_permalink($post_id) . '">' . $atts['more_text'] . '</a>';
}
return '<div class="smart-excerpt">' . $excerpt . '</div>';
}
/**
* 过滤RSS摘要
*/
public function filter_rss_excerpt($excerpt) {
global $post;
if (get_option('seg_enable_for_rss', false)) {
$length = get_option('seg_rss_excerpt_length', 100);
return $this->summary_generator->generate($post->post_content, $length);
}
return $excerpt;
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
'智能摘要设置',
'智能摘要',
'manage_options',
'smart-excerpt-settings',
[$this, 'render_settings_page']
);
}
/**
* 添加设置链接到插件列表
*/
public function add_settings_link($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=smart-excerpt-settings') . '">设置</a>';
array_unshift($links, $settings_link);
return $links;
}
/**
* 渲染设置页面
*/
public function render_settings_page() {
// 检查用户权限
if (!current_user_can('manage_options')) {
wp_die('您没有权限访问此页面');
}
// 保存设置
if (isset($_POST['submit_settings']) && check_admin_referer('seg_settings_nonce')) {
$this->save_settings();
echo '<div class="notice notice-success"><p>设置已保存!</p></div>';
}
// 加载设置页面模板
include SEG_PLUGIN_DIR . 'templates/admin-settings.php';
}
/**
* 保存设置
*/
private function save_settings() {
// 摘要长度
if (isset($_POST['excerpt_length'])) {
$length = intval($_POST['excerpt_length']);
if ($length > 0) {
update_option('seg_excerpt_length', $length);
}
}
// "阅读更多"文本
if (isset($_POST['excerpt_more'])) {
update_option('seg_excerpt_more', sanitize_text_field($_POST['excerpt_more']));
}
// 是否启用RSS摘要
$enable_rss = isset($_POST['enable_rss']) ? 1 : 0;
update_option('seg_enable_for_rss', $enable_rss);
// RSS摘要长度
if (isset($_POST['rss_excerpt_length'])) {
$rss_length = intval($_POST['rss_excerpt_length']);
if ($rss_length > 0) {
update_option('seg_rss_excerpt_length', $rss_length);
}
}
// 是否启用缓存
$enable_cache = isset($_POST['enable_cache']) ? 1 : 0;
update_option('seg_enable_cache', $enable_cache);
// 缓存过期时间
if (isset($_POST['cache_expiration'])) {
$expiration = intval($_POST['cache_expiration']);
if ($expiration > 0) {
update_option('seg_cache_expiration', $expiration);
}
}
// 是否在文章编辑页面显示摘要预览
$show_preview = isset($_POST['show_preview']) ? 1 : 0;
update_option('seg_show_preview', $show_preview);
}
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
'智能摘要设置',
'智能摘要',
'manage_options',
'smart-excerpt-settings',
[$this, 'render_settings_page']
);
}
/**
* 添加设置链接到插件列表
*/
public function add_settings_link($links) {
$settings_link = '<a href="' . admin_url('options-general.php?page=smart-excerpt-settings') . '">设置</a>';
array_unshift($links, $settings_link);
return $links;
}
/**
* 渲染设置页面
*/
public function render_settings_page() {
// 检查用户权限
if (!current_user_can('manage_options')) {
wp_die('您没有权限访问此页面');
}
// 保存设置
if (isset($_POST['submit_settings']) && check_admin_referer('seg_settings_nonce')) {
$this->save_settings();
echo '<div class="notice notice-success"><p>设置已保存!</p></div>';
}
// 加载设置页面模板
include SEG_PLUGIN_DIR . 'templates/admin-settings.php';
}
/**
* 保存设置
*/
private function save_settings() {
// 摘要长度
if (isset($_POST['excerpt_length'])) {
$length = intval($_POST['excerpt_length']);
if ($length > 0) {
update_option('seg_excerpt_length', $length);
}
}
// "阅读更多"文本
if (isset($_POST['excerpt_more'])) {
update_option('seg_excerpt_more', sanitize_text_field($_POST['excerpt_more']));
}
// 是否启用RSS摘要
$enable_rss = isset($_POST['enable_rss']) ? 1 : 0;
update_option('seg_enable_for_rss', $enable_rss);
// RSS摘要长度
if (isset($_POST['rss_excerpt_length'])) {
$rss_length = intval($_POST['rss_excerpt_length']);
if ($rss_length > 0) {
update_option('seg_rss_excerpt_length', $rss_length);
}
}
// 是否启用缓存
$enable_cache = isset($_POST['enable_cache']) ? 1 : 0;
update_option('seg_enable_cache', $enable_cache);
// 缓存过期时间
if (isset($_POST['cache_expiration'])) {
$expiration = intval($_POST['cache_expiration']);
if ($expiration > 0) {
update_option('seg_cache_expiration', $expiration);
}
}
// 是否在文章编辑页面显示摘要预览
$show_preview = isset($_POST['show_preview']) ? 1 : 0;
update_option('seg_show_preview', $show_preview);
}
}
在templates/目录下创建admin-settings.php:
<div class="wrap">
<h1>智能摘要生成器设置</h1>
<form method="post" action="">
<?php wp_nonce_field('seg_settings_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row">
<label for="excerpt_length">摘要长度(字符数)</label>
</th>
<td>
<input type="number"
id="excerpt_length"
name="excerpt_length"
value="<?php echo esc_attr(get_option('seg_excerpt_length', 150)); ?>"
min="50"
max="500"
step="10">
<p class="description">摘要的最大字符长度,建议值:150-200</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="excerpt_more">"阅读更多"文本</label>
</th>
<td>
<input type="text"
id="excerpt_more"
name="excerpt_more"
value="<?php echo esc_attr(get_option('seg_excerpt_more', '... 阅读更多')); ?>"
class="regular-text">
<p class="description">摘要末尾显示的"阅读更多"链接文本</p>
</td>
</tr>
<tr>
<th scope="row">RSS摘要设置</th>
<td>
<label>
<input type="checkbox"
id="enable_rss"
name="enable_rss"
value="1"
<?php checked(get_option('seg_enable_for_rss', false)); ?>>
为RSS订阅启用智能摘要
</label>
<div style="margin-top: 10px;">
<label for="rss_excerpt_length">RSS摘要长度:</label>
<input type="number"
id="rss_excerpt_length"
name="rss_excerpt_length"
value="<?php echo esc_attr(get_option('seg_rss_excerpt_length', 100)); ?>"
min="50"
max="300"
step="10">
</div>
</td>
</tr>
<tr>
<th scope="row">缓存设置</th>
<td>
<label>
<input type="checkbox"
id="enable_cache"
name="enable_cache"
value="1"
<?php checked(get_option('seg_enable_cache', true)); ?>>
启用摘要缓存
</label>
<div style="margin-top: 10px;">
<label for="cache_expiration">缓存过期时间(小时):</label>
<input type="number"
id="cache_expiration"
name="cache_expiration"
value="<?php echo esc_attr(get_option('seg_cache_expiration', 24)); ?>"
min="1"
max="720"
step="1">
<p class="description">缓存摘要结果以提高性能</p>
</div>
</td>
</tr>
<tr>
<th scope="row">文章编辑页面</th>
<td>
<label>
<input type="checkbox"
id="show_preview"
name="show_preview"
value="1"
<?php checked(get_option('seg_show_preview', true)); ?>>
显示摘要预览
</label>
<p class="description">在文章编辑页面显示自动生成的摘要预览</p>
</td>
</tr>
<tr>
<th scope="row">摘要生成测试</th>
<td>
<button type="button" id="test_summary" class="button">测试摘要生成</button>
<div id="test_result" style="margin-top: 10px; padding: 10px; background: #f5f5f5; display: none;"></div>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit_settings" class="button-primary" value="保存设置">
<button type="button" id="clear_cache" class="button">清除缓存</button>
</p>
</form>
<div class="card">
<h2>使用说明</h2>
<p>1. 智能摘要会自动替换WordPress默认的摘要生成功能</p>
<p>2. 如果文章已有手动设置的摘要,将优先使用手动摘要</p>
<p>3. 在文章中使用短码:[smart_excerpt length="200" more_text="查看更多"]</p>
<p>4. 可以通过过滤器自定义摘要生成行为,详见插件文档</p>
</div>
</div>
<script>
jQuery(document).ready(function($) {
// 测试摘要生成
$('#test_summary').on('click', function() {
var testText = "人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器。该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大。可以设想,未来人工智能带来的科技产品,将会是人类智慧的容器。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考,也可能超过人的智能。";
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'seg_test_summary',
text: testText,
length: $('#excerpt_length').val()
},
success: function(response) {
$('#test_result').html('<strong>测试结果:</strong><br>' + response).show();
}
});
});
// 清除缓存
$('#clear_cache').on('click', function(e) {
e.preventDefault();
if (confirm('确定要清除所有摘要缓存吗?')) {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'seg_clear_cache'
},
success: function(response) {
alert(response.message);
}
});
}
});
});
</script>
在主控制器类中添加AJAX处理方法:
// 在MainController类的init_hooks方法中添加:
add_action('wp_ajax_seg_test_summary', [$this, 'ajax_test_summary']);
add_action('wp_ajax_seg_clear_cache', [$this, 'ajax_clear_cache']);
// 添加文章编辑页面摘要预览
add_action('add_meta_boxes', [$this, 'add_excerpt_preview_metabox']);
// 在MainController类中添加新方法:
/**
* AJAX测试摘要生成
*/
public function ajax_test_summary() {
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$text = isset($_POST['text']) ? $_POST['text'] : '';
$length = isset($_POST['length']) ? intval($_POST['length']) : 150;
if (empty($text)) {
wp_die('请输入测试文本');
}
$summary = $this->summary_generator->generate($text, $length);
echo wp_kses_post($summary);
wp_die();
}
/**
* AJAX清除缓存
*/
public function ajax_clear_cache() {
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => '权限不足']);
}
global $wpdb;
// 删除所有智能摘要缓存
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
'_transient_seg_summary_%'
)
);
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
'_transient_timeout_seg_summary_%'
)
);
wp_send_json_success(['message' => '缓存已清除']);
}
/**
* 添加摘要预览元框
*/
public function add_excerpt_preview_metabox() {
if (get_option('seg_show_preview', true)) {
add_meta_box(
'seg_excerpt_preview',
'智能摘要预览',
[$this, 'render_excerpt_preview_metabox'],
'post',
'side',
'high'
);
}
}
/**
* 渲染摘要预览元框
*/
public function render_excerpt_preview_metabox($post) {
$content = $post->post_content;
$length = get_option('seg_excerpt_length', 150);
echo '<div id="seg_preview_container">';
echo '<p>自动生成的摘要预览:</p>';
echo '<div id="seg_preview_content" style="background: #f5f5f5; padding: 10px; border-radius: 3px; min-height: 100px;">';
if (!empty($content)) {
$preview = $this->summary_generator->generate($content, $length);
echo wp_kses_post($preview);
} else {
echo '<em>请输入文章内容以查看摘要预览</em>';
}
echo '</div>';
echo '<button type="button" id="seg_refresh_preview" class="button button-small" style="margin-top: 10px;">刷新预览</button>';
echo '</div>';
// 添加JavaScript
?>
<script>
jQuery(document).ready(function($) {
// 刷新预览
$('#seg_refresh_preview').on('click', function() {
var content = $('#content').val();
var length = <?php echo $length; ?>;
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'seg_update_preview',
content: content,
length: length,
post_id: <?php echo $post->ID; ?>,
nonce: '<?php echo wp_create_nonce('seg_preview_nonce'); ?>'
},
success: function(response) {
if (response.success) {
$('#seg_preview_content').html(response.data);
}
}
});
});
// 自动刷新预览(每30秒)
setInterval(function() {
if ($('#content').is(':focus')) {
$('#seg_refresh_preview').click();
}
}, 30000);
});
</script>
<?php
}
// 添加预览更新AJAX处理
add_action('wp_ajax_seg_update_preview', [$this, 'ajax_update_preview']);
/**
* AJAX更新预览
*/
public function ajax_update_preview() {
check_ajax_referer('seg_preview_nonce', 'nonce');
if (!current_user_can('edit_posts')) {
wp_send_json_error('权限不足');
}
$content = isset($_POST['content']) ? $_POST['content'] : '';
$length = isset($_POST['length']) ? intval($_POST['length']) : 150;
if (empty($content)) {
wp_send_json_success('<em>请输入文章内容以查看摘要预览</em>');
}
$summary = $this->summary_generator->generate($content, $length);
wp_send_json_success(wp_kses_post($summary));
}
为了让其他开发者可以自定义摘要生成行为,我们添加一些过滤器:
// 在SummaryGenerator类的generate方法开始处添加:
$content = apply_filters('seg_before_generate', $content, $max_length);
// 在生成摘要后添加:
$summary = apply_filters('seg_after_generate', $summary, $content, $max_length);
// 在MainController类的filter_the_excerpt方法中添加:
$smart_excerpt = apply_filters('seg_custom_excerpt', $smart_excerpt, $post, $length);
// 创建新的过滤器类
// 在includes/目录下创建class-custom-filters.php:
<?php
namespace SmartExcerpt;
class CustomFilters {
/**
* 示例过滤器:为特定分类的文章添加前缀
*/
public static function add_category_prefix($excerpt, $post, $length) {
$categories = get_the_category($post->ID);
if (!empty($categories)) {
$category_names = array_map(function($cat) {
return $cat->name;
}, $categories);
$prefix = '【' . implode('、', $category_names) . '】';
$excerpt = $prefix . ' ' . $excerpt;
}
return $excerpt;
}
/**
* 示例过滤器:移除摘要中的短链接
*/
public static function remove_short_urls($summary, $content, $max_length) {
// 移除类似bit.ly、t.cn等短链接
$summary = preg_replace('/b(https?://)?(bit.ly|t.cn|goo.gl|tinyurl.com)/S+/i', '', $summary);
return trim($summary);
}
/**
* 示例过滤器:为长摘要添加分页
*/
public static function add_pagination($excerpt, $post) {
$full_content = $post->post_content;
$excerpt_length = strlen($excerpt);
$full_length = strlen(strip_tags($full_content));
if ($full_length > $excerpt_length * 2) {
$excerpt .= ' <span class="summary-pagination">[1/2]</span>';
}
return $excerpt;
}
}
// 在MainController类的init_hooks方法中添加过滤器示例:
add_filter('seg_custom_excerpt', ['SmartExcerptCustomFilters', 'add_category_prefix'], 10, 3);
add_filter('seg_after_generate', ['SmartExcerptCustomFilters', 'remove_short_urls'], 10, 3);
// 在includes/目录下创建class-performance-optimizer.php:
<?php
namespace SmartExcerpt;
class PerformanceOptimizer {
/**
* 批量生成摘要缓存
*/
public static function batch_generate_cache($post_ids = []) {
if (empty($post_ids)) {
// 获取最近100篇文章
$args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 100,
'fields' => 'ids'
];
$query = new WP_Query($args);
$post_ids = $query->posts;
}
$summary_generator = new SummaryGenerator();
$results = [
'total' => count($post_ids),
// 在includes/目录下创建class-performance-optimizer.php:
<?php
namespace SmartExcerpt;
class PerformanceOptimizer {
/**
* 批量生成摘要缓存
*/
public static function batch_generate_cache($post_ids = []) {
if (empty($post_ids)) {
// 获取最近100篇文章
$args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 100,
'fields' => 'ids'
];
$query = new WP_Query($args);
$post_ids = $query->posts;
}
$summary_generator = new SummaryGenerator();
$results = [
'total' => count($post_ids),


