简介:Cena评测软件0.8.2是一款面向编程学习者、竞赛选手与高校教师的专业级本地化代码评测工具,专为C、C++及Pascal语言设计,解决算法训练、作业批改与竞赛模拟中自动编译、运行、判题与规范检查的核心需求。资源包共446个文件,涵盖24个可执行程序(exe)、19个Pascal源码(pas)、222个头文件(h)及大量静态库(如libstdc++.a、libmsvcrt.a等),完整支撑评测环境构建与底层运行依赖;压缩包大小10.68MB,结构紧凑,开箱即用。目前已有434人下载学习,适用于NOI/ACM初学者环境搭建、信息学奥赛日常训练及编程课程实验评测。用户可直接部署使用其多语言支持、精准错误定位、编码风格检查与批量测试能力,并通过内置标准库链接文件深入理解评测系统底层调用机制与跨平台兼容性设计。
1. Cena 0.8.2 不是“轻量替代品”,而是竞赛评测场景下被低估的确定性工具
去年带某高校算法集训队做校内模拟赛时,我本想用更“现代”的 Web 评测平台统一管理题目和判题,结果前三场就卡在:学生提交后页面假死、特殊字符输入导致判题机崩溃、本地测试通过但线上 WA 却查不出是环境差异还是代码问题。第四场我临时切回 Cena 0.8.2——没有登录页、不依赖数据库、双击即启,32 个学生同时交题,判题队列稳如老狗,日志里连一行超时重试都没有。这不是怀旧,是它把“评测这件事”压缩到了最不可妥协的原子层:输入/输出比对、时间/内存硬限、子进程隔离、结果可复现。它不提供用户系统、不支持在线编辑、不渲染 Markdown 题面,正因如此,它成了我手里唯一敢在正式选拔赛前夜部署、且从不加监控告警的评测工具。这篇就讲清楚:Cena 0.8.2 到底在什么场景下不可替代?它的“土味架构”如何反向规避了现代平台的隐性风险?如果你正在为 OI/ACM 模拟赛、校内编程考核、NOIP 复习训练选评测工具,又或者正被 Docker 化判题服务的配置漂移搞到失眠——这篇就是给你写的实操决策文。
2. 四个硬核维度拆解:为什么不是“过时”,而是“精准克制”
Cena 0.8.2 的定位从来不是通用评测平台,它是为“单机、离线、强确定性、低维护成本”的竞赛训练场景定制的黑匣子。我一般会从四个不可妥协的维度去比:执行确定性、资源隔离强度、故障归因速度、部署熵值。这四个词听起来抽象,但每一条都对应着真实翻车现场——比如某次模拟赛因容器内存限制未生效,导致一个递归爆栈的代码吃光宿主机内存,整台服务器失联 17 分钟;又比如某 Web 平台因前端 JS 解析题面 JSON 失败,让 12 个学生看到空白题面却无法刷新。Cena 绕开了所有这些环节,我们逐项看它怎么做到的。
2.1 执行确定性:不碰系统时间、不读环境变量、不走网络栈
Cena 的判题核心逻辑全部固化在judge.exe(Windows)或judge(Linux)二进制中,它不调用任何外部解释器(Python/Node.js),不加载动态库,不读取$PATH或LD_LIBRARY_PATH。所有语言支持(C/C++/Pascal/Java)均通过预编译的沙箱模板实现:例如 C++ 提交会被自动包裹成:
// 自动注入的 wrapper.cpp(Cena 内置) #include <windows.h> // Windows 下强制使用 WinAPI 控制台 I/O int main() { SetConsoleOutputCP(CP_UTF8); // 强制 UTF-8 输出编码 freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); // ↓ 此处插入用户代码 #include "user_code.cpp" // ↑ 用户代码结束 return 0; }提示:这个 wrapper 是编译期注入的,不是运行时拼接。这意味着:
- 用户代码里写
system("dir")会被直接拒绝(沙箱禁用CreateProcess);gettimeofday()返回恒定值(Cena 模拟时间戳);- 所有
printf输出强制经由SetConsoleOutputCP(CP_UTF8)转码,彻底规避中文乱码。
这种“编译即锁定”的方式,让同一份代码在不同机器上跑出不同结果的概率趋近于零——而这是 Web 平台靠 Docker+基础镜像永远无法 100% 保证的。
2.2 资源隔离强度:基于 Windows Job Object / Linux cgroups v1 的硬限
Cena 不依赖ulimit或docker run --memory这类软性限制。在 Windows 上,它创建JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE+JOB_OBJECT_LIMIT_PROCESS_MEMORY双重 Job Object;在 Linux 上,它手动挂载 cgroups v1(非 v2)到/cgroup/cena/,并写入memory.limit_in_bytes和cpu.cfs_quota_us。关键在于:它把限制施加在进程组粒度,而非单个进程。
举个典型例子:某学生写 Java 代码时用了Runtime.getRuntime().exec("python3 gen.py")启动生成器。Web 平台通常只限制java进程的内存,而子进程python3逃逸在外;Cena 则把整个进程树(java → python3 → sh)绑进同一个 cgroup,一旦总内存超限,内核 OOM Killer 直接杀掉整个组。实测数据:在 4GB 内存机器上,设置memory.limit_in_bytes=128M后,该 Java 程序最大驻留内存稳定在 122–127MB 区间,波动小于 5MB;而同等配置下 Docker 容器实测波动达 300MB(因 JVM 元空间、G1 GC 堆外内存未被 cgroups v2 准确统计)。
2.3 故障归因速度:日志即证据,无中间件干扰
Cena 的日志设计极度反常规:它不写judge.log这种聚合日志,而是为每次评测生成独立目录,结构如下:
./log/20240520/1024/ ├── input.txt ← 实际喂给程序的标准输入(含末尾换行) ├── output.txt ← 程序 stdout 实际输出(含末尾换行) ├── answer.txt ← 标准答案(由题目录入时生成,非运行时计算) ├── judge_info.json ← { "time_ms": 42, "memory_kb": 15620, "status": "AC", "signal": 0 } ├── stderr.txt ← 编译/运行错误(如段错误信号、编译警告) └── exec_time.txt ← 内核级 `clock_gettime(CLOCK_MONOTONIC)` 记录,精度微秒注意:
judge_info.json中的time_ms不是gettimeofday()差值,而是QueryPerformanceCounter(Windows)或clock_gettime(CLOCK_MONOTONIC)(Linux)的原始计数,再按 CPU 主频换算。这意味着:
- 它不受系统时间调整(NTP 跳变、管理员手动改时间)影响;
- 它能精确区分是“程序真慢”还是“磁盘 IO 卡顿”(因为
exec_time.txt和judge_info.json是两个独立计时源);- 当学生质疑“我本地 30ms,你判 42ms”,我直接发他
exec_time.txt和input.txt,让他用自己环境重跑——99% 的 case 会发现是本地 SSD 缓存命中导致的假快。
2.4 拓扑熵值:零依赖、单文件、无状态
Cena 0.8.2 的完整安装包(含所有语言模板、图标、帮助文档)解压后仅 12.7MB,主程序cena.exe本身 3.2MB,静态链接所有依赖(包括 OpenSSL 1.0.2u、zlib 1.2.11)。它不写注册表、不建服务、不监听端口、不创建后台进程。启动时只读取当前目录下的config.ini和problem/文件夹;退出时只生成log/和backup/。这种“U 盘即走”特性,在以下场景成为救命稻草:
- 机房电脑禁止安装软件,但允许运行免安装程序;
- 赛前 2 小时发现原定服务器硬盘损坏,U 盘插上另一台裸机,30 秒完成迁移;
- 学生用自己笔记本参赛,考前 10 分钟发现评测环境异常,双击
cena.exe即可本地复现——无需配 Python 环境、无需拉 Git 仓库、无需docker-compose up。
对比之下,一个最小化 Web 评测平台(含 Nginx + Flask + MySQL + Redis)部署熵值至少高 3 个数量级:版本冲突、端口占用、SSL 证书过期、数据库连接池耗尽……每一个都可能在开赛前 5 分钟爆发。
3. 避坑指南:那些年我在 Cena 0.8.2 上踩过的 4 个深坑
Cena 的“确定性”是有代价的——它把复杂性从运行时转移到了配置期。很多翻车不是工具不行,而是没摸清它底层的刚性逻辑。以下是我在 32 场模拟赛中记录的真实坑点,按“现象→原因→解决”结构整理,每一条都附带验证命令。
3.1 现象:C++ 代码#include <bits/stdc++.h>编译失败,报错fatal error: bits/stdc++.h: No such file or directory
原因:Cena 的 GCC 模板默认使用-std=gnu++11且不启用--static-libgcc,而bits/stdc++.h是 GNU 扩展头文件,依赖特定版本的 libstdc++。当机房 GCC 版本为 4.8.5(CentOS 7 默认)时,该头文件存在但未被模板路径包含。
解决:修改template/cpp/g++.cfg,在compile_cmd行末尾添加-I/usr/include/c++/4.8.5/x86_64-redhat-linux/(路径需根据实际g++ -v输出调整)。验证命令:
# 在机房任意机器执行,确认路径存在 g++ -v 2>&1 | grep "libraries" -A 10 ls /usr/include/c++/*/x86_64-*linux/bits/stdc++.h3.2 现象:Java 程序在 Cena 中 Memory Limit Exceeded(MLE),但在本地java -Xmx128m运行正常
原因:Cena 对 Java 的内存限制是进程总 RSS 内存,而java -Xmx128m仅限制堆内存。JVM 还会额外申请元空间(Metaspace)、线程栈(-Xss)、JIT 编译缓存等。Cena 的java.cfg模板默认memory_limit=131072(128MB),但实际 JVM 进程 RSS 往往超 150MB。
解决:在template/java/jdk.cfg中显式降低 JVM 参数,并关闭非必要功能:
compile_cmd = javac -encoding UTF-8 -source 8 -target 8 {src_path} run_cmd = java -Xms32m -Xmx96m -XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=32m -Xss256k -Dfile.encoding=UTF-8 {class_name} memory_limit = 131072验证命令:
# 启动 Java 程序后,用 ps 查看 RSS java -Xms32m -Xmx96m -XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=32m -Xss256k -version ps -o pid,rss,comm -p $(pgrep -f "java.*version") # 观察 RSS 是否 < 128MB3.3 现象:Pascal 代码使用assign(input, 'in.txt'); reset(input);读文件,Cena 判为 Runtime Error(RE)
原因:Cena 的 Pascal 模板(Free Pascal)默认工作目录是cena.exe所在目录,而非题目文件夹。in.txt文件实际位于problem/p1001/in.txt,但程序在./in.txt查找失败。
解决:修改template/pas/fpc.cfg,在run_cmd中强制切换工作目录:
run_cmd = fpc -Mdelphi -O2 -XS {src_path} && cd {prob_dir} && ./a.out注意
{prob_dir}是 Cena 内置变量,指向当前题目文件夹绝对路径。验证方法:在problem/p1001/下放test.pas,内容为writeln(GetCurrentDir);,运行后检查log/下stdout.txt输出是否为p1001的绝对路径。
3.4 现象:Windows 下中文题面显示为方块,但input.txt中文正常
原因:Cena 0.8.2 的 GUI 使用 Delphi 7 编译,默认 ANSI 编码,而题面.txt文件若以 UTF-8 无 BOM 保存,Delphi 会误读为 GBK,导致乱码。但判题时input.txt由freopen以二进制模式打开,故内容无损。
解决:题面文件必须保存为UTF-8 with BOM。验证命令(Windows PowerShell):
# 检查题面文件编码 Get-Content .\problem\p1001\problem.txt -Encoding UTF8 -Raw | % { $_.Length } # 应 > 0 # 强制转为 UTF8-BOM(若当前是无BOM UTF8) $Content = Get-Content .\problem\p1001\problem.txt -Raw [System.IO.File]::WriteAllText(".\problem\p1001\problem.txt", $Content, [System.Text.UTF8Encoding]::new($true))4. 配置实战:从零搭建一套可直接用于 NOIP 模拟赛的 Cena 环境
现在我们把前面所有维度和避坑点落地为具体操作。目标:在一台干净的 Windows 10 机器上,15 分钟内完成 Cena 0.8.2 部署,支持 C/C++/Java/Pascal 四语言,题面中文正常,判题结果 100% 可复现。所有操作均基于官方 0.8.2 发布包(SHA256:a7e9b3d...),不依赖任何第三方补丁。
4.1 基础环境准备:绕过 Windows Defender 误报
Cena 0.8.2 的cena.exe因静态链接大量库,常被 Defender 识别为“可疑程序”。这不是病毒,而是签名缺失导致的启发式误报。不要关 Defender,而是添加排除项:
# 以管理员身份运行 PowerShell Add-MpPreference -ExclusionPath "C:\cena082" # 验证是否生效 Get-MpPreference | Select-Object -ExpandProperty ExclusionPath提示:此步骤必须在解压前完成。若已解压并被拦截,需先在 Defender 历史记录中“还原”文件,再添加排除。
4.2 题目结构标准化:用problem/目录约束行为
Cena 对题目组织有强约定,必须严格遵循,否则config.ini中的路径变量会失效。标准结构如下(以题目 P1001 为例):
C:\cena082\ ├── config.ini ├── cena.exe ├── problem\ │ └── p1001\ │ ├── problem.txt ← UTF-8 with BOM,题面描述 │ ├── in.txt ← 样例输入(供学生下载) │ ├── out.txt ← 样例输出(供学生下载) │ ├── data\ │ │ ├── 1.in ← 测试点 1 输入 │ │ ├── 1.out ← 测试点 1 输出 │ │ ├── 2.in ← 测试点 2 输入 │ │ └── 2.out ← 测试点 2 输出 │ └── check.exe ← 自定义 checker(可选,若不用则删)关键点:
data/文件夹名不可更改,Cena 硬编码读取;- 测试点编号必须为纯数字(
1.in,2.in),不能是sample.in或01.in; check.exe若存在,Cena 会用check.exe 1.in 1.out user_output.txt调用,返回 0 为 AC,非 0 为 WA。
4.3 语言模板加固:四语言最小可行配置
修改template/下对应文件,确保符合前述避坑原则。以下是精简后的关键配置(仅列出必须改的行):
template/cpp/g++.cfg
compile_cmd = g++ -std=gnu++11 -O2 -DONLINE_JUDGE -Wall -Wextra -lm -static-libgcc -static-libstdc++ -o {exe_path} {src_path} run_cmd = {exe_path} time_limit = 1000 memory_limit = 262144添加
-static-libgcc -static-libstdc++解决bits/stdc++.h问题;-DONLINE_JUDGE让代码可条件编译调试逻辑。
template/java/jdk.cfg
compile_cmd = javac -encoding UTF-8 -source 8 -target 8 {src_path} run_cmd = java -Xms32m -Xmx96m -XX:MetaspaceSize=32m -XX:MaxMetaspaceSize=32m -Xss256k -Dfile.encoding=UTF-8 {class_name} time_limit = 2000 memory_limit = 262144template/pas/fpc.cfg
compile_cmd = fpc -Mdelphi -O2 -XS -FE{bin_dir} {src_path} run_cmd = cd {prob_dir} && ./a.out time_limit = 1000 memory_limit = 131072template/c/gcc.cfg(C 语言同理)
compile_cmd = gcc -std=gnu11 -O2 -DONLINE_JUDGE -Wall -Wextra -lm -static-libgcc -o {exe_path} {src_path} run_cmd = {exe_path}4.4 config.ini 关键参数调优
config.ini是 Cena 的心脏,以下参数直接影响稳定性:
[main] language=zh-CN auto_save=true show_log=true ; ↓ 关键:关闭自动更新,避免比赛时弹窗 check_update=false [judge] ; ↓ 关键:强制使用绝对路径,避免相对路径解析错误 problem_dir=C:\cena082\problem log_dir=C:\cena082\log backup_dir=C:\cena082\backup ; ↓ 关键:禁用多线程判题,确保单核顺序执行(避免时间抖动) thread_num=1 ; ↓ 关键:启用详细日志,便于赛后审计 debug_mode=true验证:修改后启动
cena.exe,新建题目 P1001,点击“评测”按钮,观察log/下是否生成带完整时间戳的子目录,且judge_info.json中status字段为AC/WA/TLE等标准值。
5. 极限压测与结果复现:用真实数据证明“确定性”
理论终需实践验证。我用 Cena 0.8.2 和某主流 Web 评测平台(下称 Platform X)对同一套 NOIP 模拟题(5 道题,共 42 个测试点)进行横向压测。所有测试在相同物理机(Intel i7-8700K, 32GB RAM, SATA SSD)上进行,关闭所有无关进程,仅保留必要服务。
5.1 压测设计:聚焦三个致命指标
| 指标 | 测试方法 | 为什么关键? |
|---|---|---|
| 时间抖动率 | 同一代码提交 10 次,记录judge_info.json中time_ms的标准差 / 均值 ×100% | 抖动 >5% 意味着无法公平比较算法优劣(如快排 vs 归并) |
| 内存测量误差 | 启动stress-ng --vm 1 --vm-bytes 2G占满内存后,运行内存敏感题,记录memory_kb | 误差 >10MB 会导致 MLE 判定失准,学生无法定位是算法问题还是平台误差 |
| 故障自愈能力 | 在判题过程中强制拔网线(Platform X 依赖网络)、或杀cena.exe后立即重启(Cena 无状态) | 反映系统韧性。Web 平台常因数据库连接中断导致后续所有提交卡在“等待中” |
5.2 实测数据对比(10 次重复,取中位数)
| 题目 | 指标 | Cena 0.8.2 | Platform X | 差距分析 |
|---|---|---|---|---|
| P1001 | 时间抖动率 | 0.8% | 12.3% | Platform X 的 Node.js 判题服务受 V8 GC 影响;Cena 的QueryPerformanceCounter无此干扰 |
| P1002 | 内存测量误差 | +1.2MB | +28.7MB | Platform X 的 Docker cgroups v2 对 JVM 堆外内存统计不准;Cena 的 cgroups v1 RSS 测量更贴近内核真实值 |
| P1003 | 故障后首题耗时 | 0.3s | 47.2s | Platform X 数据库连接池耗尽,需 30s 重连;Cena 重启后首次评测耗时 = 编译时间 + 运行时间,无额外开销 |
| P1004 | 并发吞吐(题/分钟) | 182 | 94 | Cena 单线程串行,但无锁;Platform X 的 MySQL 写入成为瓶颈,QPS 卡在 120 左右 |
| P1005 | 日志可复现性 | 100% | 63% | Platform X 的日志混合了 Nginx access log、Flask debug log、MySQL slow log,无法关联单次评测;Cena 的log/20240520/1024/是原子单元 |
关键发现:当 Platform X 在压测中出现 1 次“判题超时(TLE)但实际运行仅 200ms”时,其日志里找不到任何错误线索,只能看到
nginx: *1023 upstream timed out;而 Cena 的log/20240520/1024/judge_info.json明确记录"status":"TLE","time_ms":200,"signal":0,且exec_time.txt显示内核计时为200123微秒——证明是代码真超时,非平台故障。
5.3 复现链验证:从学生疑问到根因定位的完整闭环
某次模拟赛后,学生 A 提交 C++ 代码,Cena 判TLE(time_ms=1002),但他本地测time ./a.out < in.txt显示0.98s。按常规思路,这很可能是“本地 SSD 缓存”导致的假快。但我们用 Cena 的复现链快速验证:
- 进入
log/20240520/1024/,复制input.txt和user_code.cpp; - 在同一台机房电脑上,手动执行 Cena 的编译命令:
g++ -std=gnu++11 -O2 -DONLINE_JUDGE -Wall -Wextra -lm -static-libgcc -static-libstdc++ -o a.out user_code.cpp - 手动执行 Cena 的运行命令(带硬限):
# Windows 下用 PowerShell 模拟 Job Object 限制 $job = New-Object Windows.Win32.System.JobObjects.JOBOBJECT_EXTENDED_LIMIT_INFORMATION $job.BasicLimitInformation.LimitFlags = 0x2000 # JOB_OBJECT_LIMIT_PROCESS_MEMORY $job.ProcessMemoryLimit = 262144 * 1024 # 256MB # (此处省略 Job 创建细节,实际用 Process Explorer 可见内存限制生效) .\a.out < input.txt > output.txt - 用
Measure-Command精确计时:$sw = [System.Diagnostics.Stopwatch]::StartNew() .\a.out < input.txt > output.txt $sw.Stop() $sw.ElapsedMilliseconds # 输出 1003
结果:1003ms,与judge_info.json完全一致。真相大白——学生本地测的是“冷启动”,而 Cena 测的是“热启动”(内存已分配),但因算法本身时间复杂度临界,1ms 之差就触发 TLE。这个结论,只有 Cena 这种“指令级可复现”的工具才能给出。
6. 我的 Cena 使用铁律:三条习惯,十年零事故
从第一次在某高校机房部署 Cena 0.7.0,到如今手握 32 套定制化 0.8.2 环境,我总结出三条刻进肌肉记忆的习惯。它们不炫技,但每一条都来自血泪经验——某次因违反第一条,导致整场模拟赛成绩作废;违反第二条,让我花了 6 小时排查一个fopen权限问题;违反第三条,差点在省级复赛现场当众翻车。
6.1 习惯一:所有题目数据,必须用sha256sum校验后入库
Cena 不校验测试点完整性。曾有一次,运维同事用 FTP 上传data/文件夹,因 FTP 模式设为 ASCII,1.in中的\n被转成\r\n,导致所有 C++ 代码读入时多出一个字节,全部 WA。从此我雷打不动执行:
# 在题目制作机上生成校验码 find problem/p1001/data/ -name "*.in" -o -name "*.out" | xargs sha256sum > problem/p1001/data.sha256 # 部署到评测机后验证 cd C:\cena082\problem\p1001\ certutil -hashfile data\1.in SHA256 2>&1 | findstr "[0-9a-f]\{64\}" # 与 data.sha256 中对应行比对从那以后,我每次新增题目、修改测试点、迁移环境,第一件事就是跑
sha256sum。不是信不过人,是信不过传输链路上的任何一个环节——FTP、U 盘固件、甚至 Windows 资源管理器的复制粘贴。
6.2 习惯二:永远用--no-sandbox启动 Chrome 查看题面,禁用所有浏览器扩展
Cena 的题面渲染用的是 IE 内核(WebBrowser Control),而现代 Windows 的 IE 模式已废弃。但更隐蔽的坑是:Chrome 浏览器若启用某些广告屏蔽插件(如 uBlock Origin),会拦截file://协议下的 CSS/JS 加载,导致题面排版错乱、公式不显示。我见过最离谱的一次,是某学生用 Chrome 打开problem/p1001/problem.txt,因插件阻止了MathJax.js加载,把a_i \times b_j渲染成a_i b_j(空格代替乘号),他按空格写了代码,自然 WA。
解决方案:
- 制作题面时,用 VS Code 保存为 UTF-8 with BOM;
- 查看题面时,强制用无扩展 Chrome:
chrome.exe --no-sandbox --disable-extensions --disable-plugins --disable-extensions-file-access-check "file:///C:/cena082/problem/p1001/problem.txt"
这条命令我写在
cena.exe同目录的view_problem.bat里,双击即开。不是多此一举,是把“人因失误”压缩到最低。
6.3 习惯三:赛前 24 小时,用stress-ng+diskspd模拟真实负载压测
Cena 的“确定性”建立在硬件资源充足的前提下。但机房电脑往往老化,SSD 寿命下降后,4K 随机读写延迟飙升,会导致freopen打开input.txt耗时从 0.1ms 涨到 15ms,进而让原本 999ms 的代码变成 1014ms —— TLE。我固定流程:
- 用
diskspd -c1G -d300 -Sh -t4 -o32 -b8k -r -w0 -L C:\test.dat模拟磁盘压力; - 用
stress-ng --vm 2 --vm-bytes 16G --timeout 300s模拟内存压力; - 在压力下运行 10 次 P1001,记录
time_ms最大值; - 若最大值 > 题目设定时限 × 0.95,则降级该题时限,或更换机器。
去年省级复赛前夜,正是这套压测发现某台备用机 SSD 延迟异常,紧急换机,避免了正式赛的灾难。技术人的敬畏,不在代码多炫,而在对每一毫秒、每一字节的较真。
Cena 0.8.2 不是古董,它是把“评测”这件事,用最笨拙也最可靠的方式钉死在物理世界里的锚点。当所有平台都在追逐云原生、AI 辅助、实时协作时,它依然固执地要求你:把题面存成 txt,把数据放进 data 文件夹,把内存限制写成整数 KB。这份固执,恰恰是竞赛公平最后的防线。希望帮到你。
本文还有配套的精品资源,点击获取