توفر Azure Functions حل اختبار CAPTCHA بدون خادم مع تكامل محكم في نظام Azure البيئي - Key Vault للأسرار وتخزين قائمة الانتظار لتوزيع المهام ورؤى التطبيقات للمراقبة.
وظيفة تشغيل HTTP
# function_app.py
import json
import time
import os
import logging
import urllib.request
import urllib.parse
import azure.functions as func
app = func.FunctionApp()
@app.route(route="solve", methods=["POST"])
def solve_captcha(req: func.HttpRequest) -> func.HttpResponse:
"""HTTP trigger for CAPTCHA solving."""
try:
body = req.get_json()
except ValueError:
return func.HttpResponse(
json.dumps({"error": "JSON body required"}),
status_code=400,
mimetype="application/json",
)
method = body.get("method", "userrecaptcha")
params = body.get("params", {})
api_key = os.environ["CAPTCHAAI_KEY"]
try:
token = solve(api_key, method, params)
return func.HttpResponse(
json.dumps({"token": token}),
mimetype="application/json",
)
except Exception as e:
logging.error(f"Solve failed: {e}")
return func.HttpResponse(
json.dumps({"error": str(e)}),
status_code=500,
mimetype="application/json",
)
def solve(api_key, method, params, timeout=90):
"""Solve CAPTCHA via CaptchaAI API."""
submit_data = urllib.parse.urlencode({
"key": api_key,
"method": method,
"json": 1,
**params,
}).encode()
req = urllib.request.Request(
"https://ocr.captchaai.com/in.php",
data=submit_data,
)
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.loads(resp.read())
if result.get("status") != 1:
raise RuntimeError(f"Submit error: {result.get('request')}")
task_id = result["request"]
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
poll_url = (
f"https://ocr.captchaai.com/res.php"
f"?key={api_key}&action=get&id={task_id}&json=1"
)
with urllib.request.urlopen(poll_url, timeout=15) as resp:
data = json.loads(resp.read())
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(f"Solve error: {data['request']}")
raise TimeoutError("Solve timeout")
التكامل مفتاح المدفن
قم بتخزين مفتاح API في Azure Key Vault:
# Create Key Vault
az keyvault create \
--name captchaai-vault \
--resource-group myResourceGroup
# Store secret
az keyvault secret set \
--vault-name captchaai-vault \
--name CaptchaAIKey \
--value "YOUR_API_KEY"
# Grant function access
az webapp identity assign \
--name my-captcha-function \
--resource-group myResourceGroup
az keyvault set-policy \
--name captchaai-vault \
--object-id <principal-id> \
--secret-permissions get
المرجع في إعدادات التطبيق:
CAPTCHAAI_KEY=@Microsoft.KeyVault(SecretUri=https://captchaai-vault.vault.azure.net/secrets/CaptchaAIKey/)
معالجة الدُفعات التي يتم تشغيلها في قائمة الانتظار
معالجة مهام اختبار CAPTCHA من وحدة تخزين قائمة انتظار Azure:
@app.queue_trigger(
arg_name="msg",
queue_name="captcha-tasks",
connection="AzureWebJobsStorage",
)
def process_queue_task(msg: func.QueueMessage):
"""Process CAPTCHA task from queue."""
task = json.loads(msg.get_body().decode())
api_key = os.environ["CAPTCHAAI_KEY"]
try:
token = solve(api_key, task["method"], task["params"])
logging.info(f"Task {task['id']} solved")
# Store result in Table Storage or return queue
_store_result(task["id"], "success", token)
except Exception as e:
logging.error(f"Task {task['id']} failed: {e}")
_store_result(task["id"], "error", str(e))
def _store_result(task_id, status, value):
"""Store result (simplified — use Table Storage in production)."""
logging.info(f"Result: {task_id} = {status}")
هيكل المشروع
captcha-function/
├── function_app.py
├── requirements.txt
├── host.json
└── local.settings.json
المتطلبات.txt:
azure-functions
host.json:
{
"version": "2.0",
"functionTimeout": "00:02:00",
"logging": {
"logLevel": {
"default": "Information"
}
}
}
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "python",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"CAPTCHAAI_KEY": "YOUR_API_KEY_FOR_LOCAL_DEV"
}
}
نشر
# Create function app
az functionapp create \
--resource-group myResourceGroup \
--consumption-plan-location westus2 \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--name my-captcha-solver \
--storage-account mystorageaccount
# Deploy
func azure functionapp publish my-captcha-solver
# Test
curl -X POST https://my-captcha-solver.azurewebsites.net/api/solve \
-H "Content-Type: application/json" \
-d '{
"method": "userrecaptcha",
"params": {
"googlekey": "SITE_KEY",
"pageurl": "https://example.com"
}
}'
إرسال المهام إلى قائمة الانتظار
from azure.storage.queue import QueueClient
import json
queue = QueueClient.from_connection_string(
conn_str="YOUR_STORAGE_CONNECTION_STRING",
queue_name="captcha-tasks",
)
# Submit batch
for i in range(10):
task = {
"id": f"task-{i}",
"method": "userrecaptcha",
"params": {
"googlekey": "SITE_KEY",
"pageurl": f"https://example.com/page{i}",
},
}
queue.send_message(json.dumps(task))
print(f"Queued task-{i}")
استكشاف الأخطاء وإصلاحها
| المشكلة | السبب | الإجراء |
|---|---|---|
| تنتهي مهلة الوظيفة في 5 دقائق | المهلة الافتراضية | قم بتعيين functionTimeout في host.json |
| يُرجع مرجع Key Vault فارغًا | الهوية مفقودة/policy | قم بتعيين الهوية المُدارة وسياسة Key Vault |
| إعادة محاولة رسائل قائمة الانتظار إلى ما لا نهاية | الدالة تطرح استثناءً | التعامل مع الأخطاء المعروفة، وتسجيل الدخول والعودة |
| بداية باردة> 10 ثواني | وقت تشغيل بايثون init | استخدم الخطة المميزة أو قم بتعيين FUNCTIONS_WORKER_PROCESS_COUNT |
الأسئلة الشائعة
الاستهلاك مقابل الخطة المميزة؟
استخدم الاستهلاك للحجم المنخفض (<100/day). استخدم Premium لأحمال العمل المتسقة - فهو يحافظ على دفء المثيلات، ويزيل عمليات التشغيل الباردة، ويدعم تكامل VNET.
كيف يمكن مقارنة تسعير Azure Functions بـ AWS Lambda؟
مشابه جدًا لأحمال عمل CAPTCHA. يتقاضى كلاهما حوالي 0.0001 دولار أمريكي لكل استدعاء بقيمة 256 ميجابايت/60s. يتضمن Azure مليون استدعاء مجاني/month.
هل يمكنني استخدام الوظائف الدائمة لعمليات سير العمل المعقدة؟
نعم. تدعم الوظائف المتينة أنماط /fan-in المروحية - أرسل 10 اختبارات CAPTCHA بالتوازي، ثم اجمع كل النتائج. رائعة لمعالجة الدفعات.
أدلة ذات صلة
جاهز للنشر على Azure؟ احصل على مفتاح CaptchaAI الخاص بك اليوم.
النقاشات (0)
شارك في النقاش
سجّل الدخول لمشاركة رأيك.
تسجيل الدخوللا توجد تعليقات بعد.