搜索全站
建站 12 分钟阅读

WordPress 社区站内容审核与反垃圾:审核流程、敏感词与举报机制

社区站被垃圾内容淹没,通常不是因为没装反垃圾插件,而是审核流程缺一环。本文从三层过滤讲起,附敏感词与举报功能的可运行代码。

U
UFO_PF 2022-07-26 · 阅读 12 分钟
Wo 建站
阅读提示
本文约 4,665 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:反垃圾不是装个插件就完事

每个社区站长都会经历那个早上:打开后台,300 条待审评论,全是英文博彩链接。装了 Akismet 之后好一些,但很快又出现新的问题——机器绕过 Akismet 发中文软广、老用户之间吵架需要人工介入、有人举报内容但你没有一个受理入口。反垃圾真正的结构应该是三层:机器过滤(挡掉 95%)、规则过滤(挡掉剩下大部分)、人工兜底(处理争议)。只有第一层的社区,要么被淹,要么误杀正常用户。

原理分析:三层过滤的分工

层级 手段 拦截率 误杀风险
机器层 Akismet、reCAPTCHA、蜜罐字段 高 低
规则层 黑名单关键词、链接数限制、频率限制 中 中
人工层 待审队列、举报入口、版主处理 低 无

WordPress 内置了两套关键词机制,存放在 options 表里:moderation_keys(命中后进入待审)与 blacklist_keys(命中后直接判垃圾)。这两套由 wp_check_comment_data() 触发,是规则层的基础。核心钩子是 pre_comment_approved——它决定一条内容的初始状态,返回 0(待审)、1(通过)、spam(垃圾)。规则层的自定义逻辑全部挂在这里。

保姆级实操

步骤 1:配置内置的审核规则。 进入”设置 → 讨论”,勾选”评论必须经人工批准”(对新站点强烈建议开启),并填写”评论审核关键词”与”评论黑名单”。

步骤 2:接入 Akismet。 装插件后在设置页填入 API Key。Akismet 会把判定结果写进评论的 akismet_result meta,后续可以据此统计拦截量。

步骤 3:加蜜罐字段。 机器表单会填满所有字段,人类看不见隐藏字段,所以隐藏字段被填即判定为机器。这是成本最低、误杀最少的一招。

// 在评论表单里插入一个人类看不见的字段
add_filter( 'comment_form_defaults', 'mimangfei_add_honeypot' );
function mimangfei_add_honeypot( $defaults ) {
    $defaults['fields']['hp'] = '<p style="display:none"><input type="text" name="mmf_hp" value="" autocomplete="off" tabindex="-1"></p>';
    return $defaults;
}

// 隐藏字段被填写即为机器
add_filter( 'pre_comment_approved', 'mimangfei_check_honeypot' );
function mimangfei_check_honeypot( $approved ) {
    if ( ! empty( $_POST['mmf_hp'] ) ) {
        return 'spam';
    }
    return $approved;
}

步骤 4:写敏感词与链接数规则。 敏感词命中进待审,链接超过 2 条也进待审,正常用户几乎不受影响。

add_filter( 'pre_comment_approved', 'mimangfei_content_rules', 10, 2 );
function mimangfei_content_rules( $approved, $commentdata ) {
    if ( 'spam' === $approved ) {
        return $approved;
    }
    $content = isset( $commentdata['comment_content'] ) ? $commentdata['comment_content'] : '';

    // 规则一:链接数量限制
    $links = preg_match_all( '/https?:\/\//i', $content, $m );
    if ( $links > 2 ) {
        return 0; // 进入待审
    }

    // 规则二:敏感词命中
    $words = (array) get_option( 'mmf_moderation_words', array() );
    foreach ( $words as $word ) {
        if ( $word && false !== mb_strpos( $content, $word ) ) {
            return 0;
        }
    }

    // 规则三:新用户前 3 条内容一律待审
    $user = wp_get_current_user();
    if ( $user->exists() ) {
        $count = get_comments( array(
            'user_id' => $user->ID,
            'status'  => 'approve',
            'count'   => true,
        ) );
        if ( $count < 3 ) {
            return 0;
        }
    }
    return $approved;
}

步骤 5:做频率限制。 同一 IP 在 60 秒内提交超过 3 次即拦截。用 transient 存储,不额外建表。

add_filter( 'pre_comment_approved', 'mimangfei_rate_limit' );
function mimangfei_rate_limit( $approved ) {
    $ip  = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
    $key = 'mmf_rate_' . md5( $ip );
    $hit = (int) get_transient( $key );
    if ( $hit >= 3 ) {
        return 'spam';
    }
    set_transient( $key, $hit + 1, MINUTE_IN_SECONDS );
    return $approved;
}

步骤 6:加举报入口。 给每条内容一个”举报”按钮,写入独立表或用 comment meta 记录,后台统一处理。

add_action( 'wp_ajax_mmf_report', 'mimangfei_handle_report' );
add_action( 'wp_ajax_nopriv_mmf_report', 'mimangfei_handle_report' );
function mimangfei_handle_report() {
    check_ajax_referer( 'mmf_report', 'nonce' );

    $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
    $reason  = isset( $_POST['reason'] ) ? sanitize_text_field( wp_unslash( $_POST['reason'] ) ) : '';
    if ( ! $post_id ) {
        wp_send_json_error( '参数错误' );
    }

    $reports = (array) get_post_meta( $post_id, '_mmf_reports', true );
    $reports[] = array(
        'user'  => get_current_user_id(),
        'ip'    => $_SERVER['REMOTE_ADDR'],
        'time'  => current_time( 'mysql' ),
        'reason'=> $reason,
    );
    update_post_meta( $post_id, '_mmf_reports', $reports );

    // 举报达 3 次自动转为待审
    if ( count( $reports ) >= 3 ) {
        wp_update_post( array( 'ID' => $post_id, 'post_status' => 'pending' ) );
        wp_mail( get_option( 'admin_email' ), '内容被多次举报', '请处理:' . get_permalink( $post_id ) );
    }
    wp_send_json_success( '已收到举报' );
}

步骤 7:给版主配好工具。 在后台装”批量处理”类视图,并配置待审通知邮件,避免待审队列积压超过 24 小时。

常见踩坑

  1. 只装 Akismet 不加规则。 Akismet 对中文软广识别率偏低,需要本土规则补位。
  2. 误杀正常用户。 敏感词里包含了常见词的 substring,应做全词匹配或维护白名单。
  3. 待审队列积压。 没有通知机制,管理员三天没登录,评论区等于关闭。
  4. 案例: 某社区把”评论黑名单”配置得过宽,包含了单字”票”,结果正常讨论”机票”的用户评论被直接判垃圾且不通知,两周后才被发现,期间流失了大量老用户。教训:敏感词优先用”进待审”而不是”直接判垃圾”。
  5. 蜜罐字段被浏览器自动填充。 要加 autocomplete="off" 与负 tabindex。
  6. 举报接口没做 nonce 校验。 可被脚本刷举报,导致正常内容被自动下架。
  7. 频率限制用了 IP 但站点在 CDN 后。 必须取 HTTP_X_FORWARDED_FOR 或使用 CDN 提供的真实 IP 头。

总结

三层过滤的配置顺序是:先开 Akismet 与蜜罐(机器层),再加链接数、敏感词、新用户审核(规则层),最后补举报入口与版主通知(人工层)。判断标准:待审队列不超过 24 小时、正常用户几乎不被拦截、垃圾内容不在前台出现超过 10 分钟。社区互动载体怎么选见WordPress 论坛插件对比;会员内容的权限保护见会员权限与内容保护。

U
UFO_PF作者

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

留下你的想法

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