跳转到主要内容
获取令牌时遇到问题吗
联系支持

portugal_text_find_icon

注意!

此任务不需要使用代理服务器。


请求必须包含一张 base64 格式的图片,该图片由 5 张横向拼接的图像组成(不包含文本),并按照其显示顺序排列。下方展示了拼接过程的详细示例。此外,TaskArgument 参数用于指定任务文本——即需要查找的目标图标。

请求参数


重要提示:在创建任务之前请直接获取 base64 图片,以避免在解题过程中出现错误(参见章节 自动识别与解决示例)。


type<string>required

ComplexImageTask


class<string>required

recognition


imagesBase64<array>required

base64 编码格式的图片。


Task(在 metadata 中)<string>required

任务名称:"portugal_text_find_icon"


TaskArgument(在 metadata 中)<string>required

用于指定需要查找哪个图标的任务文本。例如:"Clique no(a) quadrado."

重要说明:任务文本中的某些字符必须正确转义,以避免处理或识别错误。 例如,对于文本 "Por favor, clique no(a) avião.",必须传递 "Por favor, clique no(a) avi\\u00E3o."详见章节 自动识别与解决示例)。

创建任务方法

POST
https://api.capmonster.cloud/createTask

请求

{
"clientKey": "API_KEY",
"task": {
"type": "ComplexImageTask",
"class": "recognition",
"imagesBase64": [
"iVBORw0KGgoAAAA...SuQmCC"
],
"metadata": {
"Task": "portugal_text_find_icon",
"TaskArgument": "Encontre o(a) avi\\u00E3o."
}
}
}

响应

{
"errorId":0,
"taskId":143998457
}

示例任务:

示例展示了 5 个图标以及任务文本:“Encontre o(a) avião.”(找到飞机)。

你需要发送一个 base64 图片,该图片由 5 张水平拼接的图标组成:

获取任务结果方法

POST
https://api.capmonster.cloud/getTaskResult

请求

{
"clientKey":"API_KEY",
"taskId": 143998457
}

响应: 返回的索引表示需要点击的图标编号。图标编号从 1 到 5:

{
"solution": {
"answer": [4],
"metadata": {
"AnswerType": "NumericArray"
}
},
"status": "ready",
"errorId": 0,
"errorCode": null,
"errorDescription": null
}

自动识别与解决示例

以下为使用 requestsPlaywright 的 Python 示例,展示完整的验证码处理流程:从获取任务并提取图片,到处理、准备并发送至 CapMonster Cloud 进行识别,以及获取最终结果。

重要

这些示例仅用于演示,展示与你网站交互的一般逻辑。在实际项目中,代码可能需要根据具体网站、请求结构和 headers 进行适配。

敏感数据(API key、代理设置等)应存储在 .env 文件或环境变量中。

显示代码
import os
import io
import time
import base64
import csv
import json
import re
import requests
from PIL import Image

# ===================== 配置 =====================
# 建议将敏感数据存储在 .env 文件中

# 内部验证码 API 基础地址
BASE = "https://www.example.com"

# CapMonster Cloud API
API_KEY = "YOUR_API_KEY"
CREATE_TASK_URL = "https://api.capmonster.cloud/createTask"
GET_RESULT_URL = "https://api.capmonster.cloud/getTaskResult"

# 用于模拟真实浏览器请求的 headers
HEADERS = {
"User-Agent": "userAgentPlaceholder",
"Referer": BASE + "/",
"Accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8",
"Connection": "keep-alive"
}

# 数据保存目录(图片、日志、CSV)
SAVE_DIR = "captcha_results"
os.makedirs(SAVE_DIR, exist_ok=True)

session = requests.Session()
session.headers.update(HEADERS)

# ===================== 工具函数 =====================

def serialize_json(text):
"""
将字符串转换为 JSON 安全格式。
"""
json_str = json.dumps(text, ensure_ascii=True)[1:-1]
return re.sub(r'\\u([0-9a-f]{4})', lambda m: '\\u' + m.group(1).upper(), json_str)


def post_json(url, payload):
"""
发送 JSON POST 请求并返回服务器响应。
"""
return requests.post(url, json=payload).json()

# ===================== 验证码获取 =====================

def get_captcha():
"""
从网站内部 API 请求新的验证码。
"""
url = f"{BASE}/api.php?action=new"
res = session.get(url)
data = res.json()
print("[CAPTCHA]:", data)
return data


def build_image_urls(data):
"""
根据 session 和答案构建验证码图片 URL 列表。
"""
return [
f"{BASE}/api.php?action=img&s={data['session']}&c={ans}"
for ans in data["answers"]
]

# ===================== 图片处理 =====================

def download_images(urls):
"""
从 URL 列表下载验证码图片。
"""
images = []
for url in urls:
r = session.get(url)

if "image" not in r.headers.get("Content-Type", ""):
continue

if len(r.content) < 100:
continue

try:
img = Image.open(io.BytesIO(r.content)).convert("RGBA")
images.append(img)
except:
pass

return images


def merge_images(pil_images):
"""
将多张图片水平拼接为一张图片。
"""
widths, heights = zip(*(img.size for img in pil_images))

result = Image.new("RGBA", (sum(widths), max(heights)))

x = 0
for img in pil_images:
result.paste(img, (x, 0))
x += img.size[0]

return result


def to_base64(img):
"""
将图片转换为 base64 字符串。
"""
buf = io.BytesIO()
img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode()


def save_csv(prompt, urls):
"""
将验证码日志(提示词 + 图片 URL)保存到 CSV 文件。
"""
with open(os.path.join(SAVE_DIR, "captcha.csv"), "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["prompt", "image_url"])
for url in urls:
writer.writerow([prompt, url])

# ===================== CapMonster Cloud API =====================

def create_task(base64_image, prompt):
"""
创建 CapMonster Cloud 图片识别任务。
"""
payload = {
"clientKey": API_KEY,
"task": {
"type": "ComplexImageTask",
"class": "recognition",
"imagesBase64": [base64_image],
"metadata": {
"Task": "portugal_text_find_icon",
"TaskArgument": serialize_json(prompt)
}
}
}

res = post_json(CREATE_TASK_URL, payload)
print("[createTask]:", res)
return res.get("taskId")


def get_result(task_id):
"""
等待任务完成并返回结果。
"""
while True:
time.sleep(2)

res = post_json(GET_RESULT_URL, {
"clientKey": API_KEY,
"taskId": task_id
})

if res.get("status") == "ready":
return res

print("[...] 等待结果中...")

# ===================== 主流程 =====================

def main():

# 获取验证码
data = get_captcha()
prompt = data["question_i"]
print("[PROMPT]:", prompt)

# 构建图片 URL
urls = build_image_urls(data)
save_csv(prompt, urls)

# 下载图片
images = download_images(urls)
if not images:
print("未找到图片")
return

# 将图片拼接
merged = merge_images(images)

filepath = os.path.join(SAVE_DIR, f"captcha_{int(time.time())}.png")
merged.save(filepath)
print("[+] 图片已保存:", filepath)

# 转换为 base64
base64_img = to_base64(merged)

# 在 CapMonster Cloud 创建任务
task_id = create_task(base64_img, prompt)
if not task_id:
print("createTask 错误")
return

print("[+] taskId:", task_id)

# 获取结果
result = get_result(task_id)

print("\n=== 完整结果 ===")
print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
main()