在本文中,我们尽量回答了所有关键问题。要开始解决问题,第一步是确定当前使用的是哪种防护系统。为此,您可以查看常见验证码与反机器人防护系统列表,其中提供了可视化示例和关键特征,帮助您快速判断自己正在使用哪一种方案。
如果您发现自己的网站使用的是 ComplexImage,下一步就是更深入地了解它的特性和具体工作方式。在本文中,您还可以查看 ComplexImage 的接入说明,以便彻底弄清它在您的网站上是如何运行的。这样一来,您不仅能更好地理解当前的防护机制,还可以更合理地规划后续的维护和支持。
通过 CapMonster Cloud API 工作的一般流程:
type - ComplexImageTask
class - recognition
imagesBase64 - base64 格式的图像数组。例如:[“/9j/4AAQSkZJRgABAQEAAAAAAAD…”];
Task(在 metadata 中) - 任务名称(例如 dli)。
https://api.capmonster.cloud/createTask{
"clientKey": "API_KEY",
"task": {
"type": "ComplexImageTask",
"class": "recognition",
"imagesBase64": [
"base64"
],
"metadata": {
"Task": "dli" // 替换为所需任务,可在 https://docs.capmonster.cloud/zh/docs/captchas/ComplexImageTask-Recognition/ 找到可用模块列表
}
}
}
{
"errorId":0,
"taskId":407533072
}https://api.capmonster.cloud/getTaskResult{
"clientKey":"API_KEY",
"taskId": 407533072
}
{
"solution":
{
"answer": "1",
"metadata": {
"AnswerType": "Text"
}
},
"cost": 0.0003,
"status": "ready",
"errorId": 0,
"errorCode": null,
"errorDescription": null
}
// npm install playwright @zennolab_com/capmonstercloud-client
// npx playwright install chromium
import { chromium } from 'playwright';
import { CapMonsterCloudClientFactory, ClientOptions, ComplexImageTaskRecognitionRequest } from '@zennolab_com/capmonstercloud-client';
const API_KEY = "YOUR_API_KEY";
const TARGET_URL = "https://example.com/captcha-page";
async function solveComplexImageTaskPlaywright() {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(TARGET_URL);
// 找到 CAPTCHA 图像
const captchaHandle = await page.$('#captcha'); // 替换为真实选择器
const captchaBase64 = await captchaHandle.evaluate(img => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return canvas.toDataURL('image/png').split(',')[1];
});
console.log("Captcha base64:", captchaBase64.substring(0, 50) + "...");
const cmcClient = CapMonsterCloudClientFactory.Create(
new ClientOptions({ clientKey: API_KEY })
);
// 提交 CAPTCHA 进行识别
const citRecognitionRequest = new ComplexImageTaskRecognitionRequest({
imagesBase64: [captchaBase64],
metaData: { Task: 'oocl_rotate' } // 替换为您的 CAPTCHA 类型
});
const result = await cmcClient.Solve(citRecognitionRequest);
console.log("Solution received:", result);
// 处理结果
const solution = result.solution;
if (!solution) {
console.error("No solution received");
return;
}
if (solution.metadata?.AnswerType === "Coordinate") {
// 带坐标的 CAPTCHA
const box = await captchaHandle.boundingBox();
for (const point of solution.answer) {
const clickX = box.x + point.X;
const clickY = box.y + point.Y;
console.log(`Clicking at: (${clickX}, ${clickY})`);
await page.mouse.click(clickX, clickY);
}
} else if (solution.metadata?.AnswerType === "Grid") {
// 网格 CAPTCHA(true/false 数组)
const box = await captchaHandle.boundingBox();
const gridItems = await page.$$('#captcha_grid div'); // 替换为网格元素选择器
const answers = solution.answer;
for (let i = 0; i < answers.length; i++) {
if (answers[i] && gridItems[i]) {
const itemBox = await gridItems[i].boundingBox();
const clickX = itemBox.x + itemBox.width / 2;
const clickY = itemBox.y + itemBox.height / 2;
console.log(`Clicking grid item ${i} at: (${clickX}, ${clickY})`);
await page.mouse.click(clickX, clickY);
}
}
} else {
console.warn("Unknown captcha solution type:", solution.metadata?.AnswerType);
}
// 点击确认按钮(如有)
await page.click('#submit_button'); // 替换为真实按钮选择器
console.log("Captcha solved.");
}
solveComplexImageTaskPlaywright().catch(console.error);
1. 在服务器端生成 CAPTCHA。
2. 将 CAPTCHA 传给客户端
<!--图像网格 CAPTCHA-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Grid CAPTCHA Demo</title>
<style>
#captchaGrid {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-gap: 10px;
margin-bottom: 10px;
}
.grid-item {
width: 100px;
height: 100px;
background-color: #eee;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 2px solid transparent;
}
.grid-item.selected {
border-color: blue;
}
</style>
</head>
<body>
<h1>Grid CAPTCHA Demo</h1>
<div id="captchaGrid"></div>
<button id="submitBtn">Submit</button>
<button id="refreshBtn">Refresh CAPTCHA</button>
<p id="result"></p>
<script>
let captchaId;
let answers = []; // 点击结果为 true/false 数组
async function loadCaptcha() {
const res = await fetch('/captcha'); // 服务器应返回 JSON,包含 captchaId 和 base64 图像数组
const data = await res.json();
captchaId = data.captchaId;
answers = new Array(data.images.length).fill(false);
const grid = document.getElementById('captchaGrid');
grid.innerHTML = '';
data.images.forEach((imgBase64, i) => {
const div = document.createElement('div');
div.className = 'grid-item';
div.style.backgroundImage = `url('data:image/png;base64,${imgBase64}')`;
div.style.backgroundSize = 'cover';
div.addEventListener('click', () => {
answers[i] = !answers[i];
div.classList.toggle('selected', answers[i]);
});
grid.appendChild(div);
});
document.getElementById('result').textContent = '';
}
document.getElementById('refreshBtn').addEventListener('click', loadCaptcha);
document.getElementById('submitBtn').addEventListener('click', async () => {
const res = await fetch('/captcha/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ captchaId, answer: answers })
});
const data = await res.json();
document.getElementById('result').textContent = data.success ? 'Captcha passed!' : 'Captcha failed, try again.';
if (!data.success) loadCaptcha();
});
// 启动时加载 CAPTCHA
loadCaptcha();
</script>
</body>
</html>
3. 用户输入答案
4. 将答案发送到服务器:
5. 服务器端验证
<?php
session_start();
// CAPTCHA TTL(秒)
define('CAPTCHA_TTL', 300); // 5 分钟
// 生成随机图像
function generateCaptchaImage($text = null) {
$width = 100;
$height = 100;
if (!$text) {
$text = substr(str_shuffle('ABCDEFGHJKLMNPQRSTUVWXYZ23456789'), 0, 2);
}
$image = imagecreatetruecolor($width, $height);
// 背景
$bgColor = imagecolorallocate($image, rand(180, 255), rand(180, 255), rand(180, 255));
imagefilledrectangle($image, 0, 0, $width, $height, $bgColor);
// 文本
$textColor = imagecolorallocate($image, 0, 0, 0);
$fontSize = 15;
$fontFile = __DIR__ . '/Arial.ttf'; // TTF 字体路径
if (file_exists($fontFile)) {
imagettftext($image, $fontSize, rand(-20,20), 10, 50, $textColor, $fontFile, $text);
} else {
imagestring($image, 5, 10, 40, $text, $textColor);
}
ob_start();
imagepng($image);
$imgData = ob_get_clean();
imagedestroy($image);
return base64_encode($imgData);
}
// 创建网格 CAPTCHA
function generateGridCaptcha() {
$numImages = 9; // 3x3
$images = [];
$solution = [];
for ($i = 0; $i < $numImages; $i++) {
// 随机解决,正确或错误(示例)
$isCorrect = rand(0,1) === 1;
$solution[] = $isCorrect;
// 生成图像(可添加不同对象以生成真实 CAPTCHA)
$text = $isCorrect ? 'OK' : 'NO';
$images[] = generateCaptchaImage($text);
}
return ['images' => $images, 'solution' => $solution];
}
// 生成 CAPTCHA 接口
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/captcha') {
$captchaId = uniqid('captcha_', true);
$gridCaptcha = generateGridCaptcha();
$_SESSION['captchas'][$captchaId] = [
'solution' => $gridCaptcha['solution'],
'timestamp' => time()
];
header('Content-Type: application/json');
echo json_encode([
'captchaId' => $captchaId,
'images' => $gridCaptcha['images']
]);
exit;
}
// 验证 CAPTCHA 接口
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/captcha/verify') {
$data = json_decode(file_get_contents('php://input'), true);
$captchaId = $data['captchaId'] ?? '';
$answer = $data['answer'] ?? [];
if (!isset($_SESSION['captchas'][$captchaId])) {
echo json_encode(['success' => false, 'message' => 'Captcha expired or not found']);
exit;
}
$captcha = $_SESSION['captchas'][$captchaId];
// TTL 验证
if (time() - $captcha['timestamp'] > CAPTCHA_TTL) {
unset($_SESSION['captchas'][$captchaId]);
echo json_encode(['success' => false, 'message' => 'Captcha expired']);
exit;
}
// true/false 数组验证
$success = $captcha['solution'] === $answer;
// 验证后删除 CAPTCHA
unset($_SESSION['captchas'][$captchaId]);
echo json_encode(['success' => $success]);
exit;
}
// 404
http_response_code(404);
echo 'Not found';
6. 后续操作
附加
进行负载测试(例如 k6 或 JMeter)——大量请求时:
如果你遇到已经安装 CAPTCHA 或其他保护系统的网站,且无法访问代码,不必担心!确定技术类型相对容易。可在隔离测试环境中使用 CapMonster Cloud 检查正确性,确保 token 处理和验证逻辑正常。
对于 图像 CAPTCHA —— 只需识别系统、研究其行为并确保保护功能正常。本文展示了如何识别图像 CAPTCHA (ComplexImage) 以及如何集成或重新配置,以便有效管理和控制保护。