文档大纲

巧用WordPress给影刀做个应用使用计数器

在影刀中做了很多应用,有些分享出去了,想了解分享出去后的使用情况。影刀企业版有控制台,可以查看数据。对于免费版就没这方面功能了。

有影刀社区中,有刀友建议在应用中添加钉钉或飞书发信息的方式,获取统计数据。我是通过钉钉集中获取应用报错信息的,如果再添加统计数据发送,假如应用运行的次数多,那一定很烦,且这个方式并不适合做统计汇总。

碰巧我有一个使用Wordpress搭建的个人网站,就想到了这个办法,借用Wordpress的REST API和自定义数据库存储能力,结合影刀的Python 代码节点,来实现精准统计应用运行次数和时长的需求。

如果你碰巧也有Wordpress网站,那可以直接尝试我这个方法。

如果你没有Wordpress网站,也可以参考我的思路或逻辑,比如将数据发送写入到自己的MySQL数据库中,后续再进行查询。

先看一下测试的效果展示:

核心逻辑

影刀每次运行时,通过代码节点向 WordPress 发送运行数据;WordPress 接收数据后存入数据库,最后通过自定义页面 / 短代码展示统计结果。

操作步骤

  1. WordPress添加自定义插件

3.1 在电脑上新建一个文本文件,重命名为 rpa-stat.php。将以下代码完整复制进去:

<?php
/*
Plugin Name: RPA 运行监控中心 (Pro版)
Description: 接收影刀 RPA 上报的数据,支持记录应用名称、IP、状态及运行时长。
Version: 2.0
Author: RPA Monitor
*/

// 1. 初始化数据库表 (增加 app_name 和 user_ip 字段)
function rpa_stat_create_table_pro() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'rpa_run_stats';
    $charset_collate = $wpdb->get_charset_collate();

    // SQL 语句:自动创建或升级表结构
    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        app_key varchar(50) NOT NULL COMMENT '应用唯一标识',
        app_name varchar(100) NOT NULL COMMENT '应用显示名称',
        start_time datetime NOT NULL COMMENT '开始时间',
        end_time datetime NOT NULL COMMENT '结束时间',
        duration float NOT NULL COMMENT '运行时长(秒)',
        status varchar(20) DEFAULT 'success' COMMENT '运行状态',
        user_ip varchar(45) DEFAULT '' COMMENT '运行机器IP',
        create_time datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY app_key (app_key)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}
// 插件激活时运行建表逻辑
register_activation_hook(__FILE__, 'rpa_stat_create_table_pro');
// 为了确保新字段生效,我们挂载到 plugins_loaded 再次检查结构
add_action('plugins_loaded', 'rpa_stat_create_table_pro');

// 2. 注册 REST API 接口
add_action('rest_api_init', function () {
    register_rest_route('rpa-stat/v1', '/report', array(
        'methods' => 'POST',
        'callback' => 'rpa_stat_handle_request',
        'permission_callback' => '__return_true', // 使用自定义密钥验证
    ));
});

function rpa_stat_handle_request($request) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'rpa_run_stats';
    $params = $request->get_json_params();

    // --- 安全验证 ---
    $secret_key = 'your_secure_secret_123456'; // 【请修改】必须与影刀中一致
    if (!isset($params['secret_key']) || $params['secret_key'] !== $secret_key) {
        return new WP_Error('403', '非法访问:密钥错误', array('status' => 403));
    }

    // --- 获取真实 IP ---
    $user_ip = $_SERVER['REMOTE_ADDR'];
    // 如果使用了 CDN (如 Cloudflare),尝试获取真实 IP
    if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
        $user_ip = $_SERVER["HTTP_CF_CONNECTING_IP"];
    } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $user_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }

    // --- 写入数据库 ---
    $result = $wpdb->insert(
        $table_name,
        array(
            'app_key'    => sanitize_text_field($params['app_key']),
            'app_name'   => sanitize_text_field($params['app_name']), // 新增字段
            'start_time' => sanitize_text_field($params['start_time']),
            'end_time'   => sanitize_text_field($params['end_time']),
            'duration'   => floatval($params['duration']),
            'status'     => sanitize_text_field($params['status']),
            'user_ip'    => sanitize_text_field($user_ip)             // 新增字段
        ),
        array('%s', '%s', '%s', '%s', '%f', '%s', '%s')
    );

    if ($result) {
        return array('success' => true, 'id' => $wpdb->insert_id, 'ip_recorded' => $user_ip);
    } else {
        return new WP_Error('500', '数据库写入失败', array('status' => 500));
    }
}

// 3. 短代码展示 (前端仪表盘)
add_shortcode('rpa_stat', 'rpa_stat_render_dashboard');

function rpa_stat_render_dashboard($atts) {
    global $wpdb;
    $table_name = $wpdb->prefix . 'rpa_run_stats';
    
    // 筛选参数:[rpa_stat app_key="xxx"]
    $atts = shortcode_atts(array('app_key' => ''), $atts);
    $where = "";
    if ($atts['app_key']) {
        $where = $wpdb->prepare("WHERE app_key = %s", $atts['app_key']);
    }

    // 数据查询
    $total_runs = $wpdb->get_var("SELECT COUNT(*) FROM $table_name $where");
    $total_duration = $wpdb->get_var("SELECT SUM(duration) FROM $table_name $where");
    $fail_count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name $where AND status = 'failed'");
    $logs = $wpdb->get_results("SELECT * FROM $table_name $where ORDER BY start_time DESC LIMIT 20");

    // 计算展示数据
    $hours = $total_duration ? round($total_duration / 3600, 2) : 0;
    $success_rate = $total_runs > 0 ? round((($total_runs - $fail_count) / $total_runs) * 100, 1) : 0;

    // 内联样式与 HTML
    $html = '<style>
        .rpa-dashboard { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 100%; overflow-x: auto; }
        .rpa-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 15px; margin-bottom: 20px; }
        .rpa-card { background: #fff; padding: 15px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); text-align: center; border: 1px solid #eee; }
        .rpa-card h4 { margin: 0 0 5px; font-size: 12px; color: #666; font-weight: normal; }
        .rpa-card .num { font-size: 24px; font-weight: bold; color: #2271b1; }
        .rpa-table { width: 100%; border-collapse: collapse; font-size: 13px; background: #fff; }
        .rpa-table th { background: #f0f0f1; text-align: left; padding: 10px; border-bottom: 2px solid #ddd; }
        .rpa-table td { padding: 8px 10px; border-bottom: 1px solid #eee; color: #555; }
        .status-tag { padding: 2px 6px; border-radius: 4px; font-size: 11px; font-weight: bold; }
        .st-success { background: #d1e7dd; color: #0f5132; }
        .st-failed { background: #f8d7da; color: #842029; }
        .ip-addr { font-family: monospace; color: #888; }
    </style>';

    $html .= '<div class="rpa-dashboard">';
    $html .= '<div class="rpa-cards">
                <div class="rpa-card"><h4>总运行次数</h4><div class="num">'.$total_runs.'</div></div>
                <div class="rpa-card"><h4>总时长(小时)</h4><div class="num">'.$hours.'</div></div>
                <div class="rpa-card"><h4>成功率</h4><div class="num">'.$success_rate.'%</div></div>
              </div>';
    
    $html .= '<table class="rpa-table"><thead>
                <tr>
                    <th>状态</th>
                    <th>应用名称</th>
                    <th>开始时间</th>
                    <th>时长(秒)</th>
                    <th>运行IP</th>
                </tr>
              </thead><tbody>';

    foreach ($logs as $log) {
        $st_class = ($log->status == 'success') ? 'st-success' : 'st-failed';
        $st_text = ($log->status == 'success') ? '成功' : '失败';
        
        $html .= "<tr>
            <td><span class='status-tag {$st_class}'>{$st_text}</span></td>
            <td><strong>{$log->app_name}</strong><br><small style='color:#999'>{$log->app_key}</small></td>
            <td>{$log->start_time}</td>
            <td>{$log->duration}</td>
            <td class='ip-addr'>{$log->user_ip}</td>
        </tr>";
    }
    $html .= '</tbody></table></div>';

    return $html;
}

注意:替换53行代码中的秘钥'your_secure_secret_123456'为自己设置的复杂秘钥,注意和影刀中的保持一致。

3.2 将 `rpa-stat.php` 放入文件夹 `rpa-stat` 中。 3.3 将文件夹上传到 WordPress 的 `wp-content/plugins/` 目录。

3.4 进入 WordPress 后台 -> 插件 -> 启用 RPA 运行监控中心 (Pro版)。

3.5 在Wordpress新建一个页面,页面中插入短代码:

总运行次数

167

总时长(小时)

237.28

成功率

99.4%
状态 应用名称 开始时间 时长(秒) 运行IP
成功 全数据下载分析
alldata_analysis
2026-02-25 08:12:10 14826.6 180.157.4.196
成功 月报财报刷新
monthly_fresh
2026-02-24 16:06:06 4023.34 180.157.4.196
成功 全数据下载分析
alldata_analysis
2026-02-24 07:42:39 6359.73 180.157.4.196
成功 全数据下载分析
alldata_analysis
2026-02-23 08:01:57 13031.2 180.157.4.196
成功 全数据下载分析
alldata_analysis
2026-02-22 08:20:49 14877.2 180.157.4.196
成功 全数据下载分析
alldata_analysis
2026-02-21 07:41:28 13300.7 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-20 09:23:32 11902 42.3.51.43
成功 全数据下载分析
alldata_analysis
2026-02-19 09:53:45 14778.5 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-18 09:01:17 13914.6 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-16 08:47:02 25676.5 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-15 07:50:08 8183.34 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-14 08:16:16 15200.6 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-13 11:27:39 14849.3 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-13 08:48:37 2285.46 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-12 09:08:58 14720.7 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-12 07:37:24 1835.17 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-11 08:00:30 15273.5 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-09 11:15:04 15109.5 180.157.4.12
成功 全数据下载分析
alldata_analysis
2026-02-07 08:23:01 15311.8 180.157.4.12
成功 淘系数据下载分析
taodata_analyze
2026-02-06 14:56:30 207.49 115.205.79.202
,保存、发布。

  1. 影刀准备工作
  • 准备工作:安装 Requests 库 打开影刀 -> 环境管理 -> 自定义依赖 -> 添加 requests。
  1. 影刀流程内添加指令,记录运行开始时间:

在流程的最开始位置,添加影刀指令:日期时间转为时间戳,获取变量"start_ts"。

这个获取的时间戳,看起来是小数,但实际上是以文本格式传递,因此下面还要将这个变量转换为浮点数。

  1. 构建异常处理结构 (Try-Catch)

为了统计应用运行"失败"的情况,整个业务逻辑必须包裹在异常处理中。

  • 添加一个 【异常处理 (Try-Catch)】 组件。
  • 将你原有的所有业务流程节点,拖动到 Try 分支中。
  1. 结束节点:计算时长并上报到 WordPress

新建Python模块,输入以下代码:

import time
import requests
import datetime

def main(args):
    # 1. 从参数获取变量
    app_key = args.get("v_app_key", "unknown_app")
    app_name = args.get("v_app_name", "未命名应用")
    start_ts = args.get("v_start_time", 0)
    status = args.get("status", "success") # 默认为成功
    
    # 2. 计算时间和时长
    end_ts = time.time()
    
    if start_ts == 0:
        duration = 0 # 防止未运行起始节点
    else:
        duration = round(end_ts - start_ts, 2)
        
    # 转换为 SQL 格式 (YYYY-MM-DD HH:MM:SS)
    # 注意:Windows下 timestamp 可能是 float
    start_str = datetime.datetime.fromtimestamp(start_ts).strftime('%Y-%m-%d %H:%M:%S')
    end_str = datetime.datetime.fromtimestamp(end_ts).strftime('%Y-%m-%d %H:%M:%S')

    # 3. 配置接口信息 (请替换你的域名和密钥)
    API_URL = "https://你的域名/wp-json/rpa-stat/v1/report"
    SECRET_KEY = "your_secure_secret_123456" 

    # 4. 构造数据包 (注意:不包含IP,IP由服务器自动获取)
    payload = {
        "secret_key": SECRET_KEY,
        "app_key": app_key,
        "app_name": app_name,  # 新增:应用中文名
        "start_time": start_str,
        "end_time": end_str,
        "duration": duration,
        "status": status
    }

    # 5. 发送请求
    try:
        # verify=False 用于跳过 SSL 证书验证(防止自签证书报错),正式环境建议设为 True
        res = requests.post(API_URL, json=payload, timeout=5, verify=False)
        if res.status_code == 200:
            print(f"上报成功: [{app_name}] 耗时 {duration}秒")
        else:
            print(f"上报失败: {res.status_code} - {res.text}")
    except Exception as e:
        print(f"上报网络错误: {e}")

设置以下变量,作为这个Python模块的输入参数:

将这个Python模块插入主流程,设置输入参数值:

注意v_start_time就是前面指令定义的时间戳变量,

v_app_name为应用的名称,可以使用中文,以便在页面查看。

v_app_key为录入数据库的应用身份,使用英文。

status:这个模块如果是插入try__Catch___的Try语句中,就设置为文本"success",插入Catch语句,则设置为"failed",便于区分应用状态。

注意事项

  1. 接口安全:务必将SECRET_KEY替换为复杂的随机字符串(如 32 位字母 + 数字),防止他人恶意调用接口;
  2. 异常处理:影刀流程若中途报错终止,结束节点的代码可能无法执行。可在影刀中添加「异常捕获」节点,将上报代码放入异常处理逻辑,记录 "异常终止" 的时长(到报错时间为止);
  3. 网络权限:确保影刀所在环境能访问你的 WordPress 网站(若影刀在内网,需配置端口映射 / 公网访问);
  4. 数据备份:定期备份 WordPress 数据库(重点备份wp_rpa_run_stats表),避免数据丢失;
  5. 方法复用:如果有多个应用需要统计,可以把两段Python分别做成自定义指令,在需要统计的应用中直接调用。

最终效果

当你的影刀应用被他人运行时,每次运行都会自动向 WordPress 上报数据,你只需打开 WordPress 的统计页面(你的域名/rpa-report/),就能实时看到:

  • 应用被运行的总次数;
  • 累计运行的总时长(秒 / 小时);
  • 运行者的IP地址;
  • 运行的应用标识;
  • 每一次运行的详细时间和时长(便于排查问题)。

阅读量: 247