# -*- coding: utf-8 -*-
"""
=============================================================
  极验识别 Demo (Python版)

  功能说明：
  提交极验验证码识别任务（支持三代/四代）
  极验识别为异步流程：先提交任务获取resultid，再轮询查询结果

  使用方法：
  1. 安装依赖：pip install requests
  2. 将下方的配置参数替换为你自己的值
  3. 运行脚本：python recognize_geetest.py
=============================================================
"""

import requests
import json
import sys
import time

# ======================== 配置区域（请替换为你自己的参数）========================
# 用户密钥，登录平台后获取
APPKEY = "你的appkey"

# 极验gt值（三代为gt值，四代为captcha_id值）
GT = "你获取到的gt值"

# challenge值（三代必填，每次只能使用一次；四代无需传此参数，留空即可）
CHALLENGE = ""

# 项目类型（请参照项目价格表，不同类型对应不同的itemid）
ITEM_ID = 0

# 验证码所在的页面URL（可选，部分网站需要填写）
REFERER = ""

# 可选参数：代理IP（格式示例：http://IP:端口，若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888）
PROXY = ""

# 可选参数：开发者密钥（如果有的话填写）
DEVKEY = ""

# 可选参数：SDK版本（特殊版本为2，默认为1）
SDK = ""

# 可选参数：对接模式（按次计费:0，包月计费:1，默认为0。包月用户必填）
GIVEN = ""

# 可选参数：特殊网站极验域名（如api-na.geetest.com，不要带http://和/，只需域名）
HOST = ""

# 可选参数：User-Agent（适用于某些检验UA的网站，只支持传入安卓ua）
USER_AGENT = ""
# ===============================================================================

# API基础地址
API_BASE = "http://api.ttocr.com/api"

# 轮询配置
POLL_INTERVAL = 2    # 轮询间隔（秒），不得低于1秒
MAX_POLL_TIME = 60   # 最大等待时间（秒）


def submit_task():
    """
    步骤1：提交极验识别任务
    接口地址：POST http://api.ttocr.com/api/recognize
    返回resultid用于后续查询结果
    """
    print("=" * 50)
    print("[提交任务] 正在提交极验识别任务...")
    print("=" * 50)
    url = f"{API_BASE}/recognize"
    post_data = {
        "appkey": APPKEY,
        "gt": GT,
        "itemid": ITEM_ID,
    }
    # 三代需要传challenge，四代不需要
    if CHALLENGE:
        post_data["challenge"] = CHALLENGE
    # 验证码所在页面URL，部分网站需要填写
    if REFERER:
        post_data["referer"] = REFERER
    if PROXY:
        post_data["proxy"] = PROXY
    if DEVKEY:
        post_data["devkey"] = DEVKEY
    if SDK:
        post_data["sdk"] = SDK
    if GIVEN:
        post_data["given"] = GIVEN
    if HOST:
        post_data["host"] = HOST
    if USER_AGENT:
        post_data["userAgent"] = USER_AGENT

    print(f"[请求参数] gt={GT[:20]}..." if len(GT) > 20 else f"[请求参数] gt={GT}")
    print(f"[请求参数] itemid={ITEM_ID}")
    print(f"[请求参数] referer={REFERER}")

    try:
        response = requests.post(url, data=post_data, timeout=30)
        result = response.json()
        print(f"[提交响应] {json.dumps(result, ensure_ascii=False, indent=2)}")
        if result.get("status") == 1:
            resultid = result.get("resultid")
            print(f"[成功] 任务提交成功！resultid={resultid}")
            return resultid
        else:
            print(f"[失败] 任务提交失败，错误信息：{result.get('msg')}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"[异常] 网络请求出错：{e}")
        return None


def query_result(resultid):
    """
    步骤2：轮询查询识别结果
    接口地址：POST http://api.ttocr.com/api/results
    注意：查询间隔不低于1秒，否则会被拉黑IP 10分钟
    """
    print("\n" + "=" * 50)
    print("[查询结果] 正在轮询识别结果...")
    print(f"[查询结果] 轮询间隔：{POLL_INTERVAL}秒，最大等待：{MAX_POLL_TIME}秒")
    print("=" * 50)
    url = f"{API_BASE}/results"
    start_time = time.time()
    while True:
        elapsed = time.time() - start_time
        if elapsed > MAX_POLL_TIME:
            print(f"[超时] 已等待{MAX_POLL_TIME}秒，识别超时，请稍后重试")
            return None
        try:
            post_data = {"appkey": APPKEY, "resultid": resultid}
            response = requests.post(url, data=post_data, timeout=30)
            result = response.json()
            if result.get("status") == 1:
                print(f"\n[成功] 识别成功！耗时：{result.get('time')}ms")
                print(f"[识别结果] {json.dumps(result.get('data'), ensure_ascii=False, indent=2)}")
                print(f"\n[完整响应] {json.dumps(result, ensure_ascii=False, indent=2)}")
                return result
            else:
                msg = result.get("msg", "")
                print(f"[等待中] 第{int(elapsed)}秒 - {msg}")
        except requests.exceptions.RequestException as e:
            print(f"[异常] 查询请求出错：{e}")
        time.sleep(POLL_INTERVAL)


if __name__ == "__main__":
    print("*" * 60)
    print("  极验识别 Demo (Python版)")
    print("*" * 60)
    if APPKEY == "你的appkey":
        print("\n[错误] 请先在脚本顶部的配置区域填写你的 APPKEY")
        sys.exit(1)
    if GT == "你获取到的gt值":
        print("\n[错误] 请先在脚本顶部的配置区域填写 GT 值")
        sys.exit(1)
    if ITEM_ID == 0:
        print("\n[错误] 请先在脚本顶部的配置区域填写 ITEM_ID（项目类型）")
        sys.exit(1)

    # 步骤1：提交任务
    resultid = submit_task()
    if resultid:
        # 步骤2：轮询查询结果
        query_result(resultid)
    print("\n" + "=" * 50)
    print("[完成] 识别执行完毕")
    print("=" * 50)

