Логотип «2Captcha»Перейти на главную страницу
Туториалы по обходу капчи

Эта статья была полезной?

Как обойти капчу Yidun на сайте id7.cloud.huawei.com

Грегори Фишер
Грегори Фишер

Технический специалист

id7.cloud.huawei.com — европейская площадка входа в аккаунт HUAWEI. Страница входа защищена капчей Yidun.

Капча появляется не при каждом входе: показать её или пропустить, решает сервер Huawei. Но параметры для задачи страница готовит заранее, ещё до того как появится окно с картинкой, и их можно прочитать.

По сравнению с обычным Yidun на этом сайте есть три сложности.

Ключа сайта нет в коде страницы. Его отдаёт отдельный запрос, а чтобы собрать этот запрос, сначала нужно получить два других значения от Huawei.

Установлена версия Enterprise. Кроме ключа сайта задаче нужны ещё три значения — challenge, hcg и hct, и все три одноразовые.

Решение не вписывается в форму. Страница упаковывает его в строку JSON вместе с другими значениями и отправляет отдельным параметром запроса.

Параметры задачи

Тип задачи — YidunTaskProxyless, если решать через прокси сервиса, или YidunTask, если подставлять свои.

Параметр Тип Обязательный Описание
type String Да YidunTaskProxyless или YidunTask
websiteURL String Да Адрес страницы входа: https://id7.cloud.huawei.com/CAS/portal/loginAuth.html
websiteKey String Да Ключ сайта, он же captchaId. У этого сайта — 0f743r3g1gm36431pg87n8rz3grz0ym5
userAgent String Нет User-Agent браузера, которым открыта страница
yidunGetLib String Нет Адрес файла, который загружает капчу. Для Enterprise рекомендуется передавать
yidunApiServerSubdomain String Нет Домен сервера капчи без https://. У Huawei он свой, не стандартный
challenge String Нет Одноразовое значение из ответа cscPreprocess
hcg String Нет Одноразовое значение из того же ответа
hct Number Нет Метка времени из того же ответа

Три последних параметра документация помечает как необязательные, но для этого сайта они нужны: без них решение относится к обычной версии Yidun, а Huawei ждёт Enterprise.

Для типа YidunTask добавляются данные прокси: proxyType, proxyAddress, proxyPort, proxyLogin и proxyPassword.

Как найти параметры

Постоянные значения у этого сайта такие:

Значения challenge, hcg и hct одноразовые, их нужно получать заново перед каждой задачей. Ниже показано, как их получает сама страница и как повторить это в скрипте.

Шаг первый: запрос cscPreprocess

Откройте страницу входа, нажмите F12 и перейдите на вкладку «Сеть» (Network). Начните вход, и среди запросов появится cscPreprocess с параметром reflushCode. Это запрос методом POST по адресу вида /CAS/IDM_W/ajaxHandler/cscPreprocess?reflushCode=ЧИСЛО.

В его теле страница отправляет captchaType, clientType, lang и sceneId, а также два своих служебных значения — pageToken и pageTokenKey. Оба лежат в объекте localInfo на странице.

Ответ выглядит так:

json Copy
{
  "appId": "huaweiup",
  "businessId": "huaweiup",
  "cdnDomain": "",
  "challenge": "f4df3943be517cca2b6060842c4cb96daf6b22e2f15f521ef2177031bab2069b",
  "hcg": "1cb7f8d1fa60134e7f5c92b15f96205046cbd91581eb0c16c9d3df63db9967e1",
  "hct": 1788597543413,
  "isSuccess": 1,
  "sceneId": "login",
  "serviceDomain": ["csc-adapter-dre.security.dbankcloud.com"],
  "type": 2
}

Отсюда берутся challenge, hcg и hct для задачи. Значения businessId, sceneId и serviceDomain понадобятся на следующем шаге, а type — при сборке ответа для сервера.

Про сам запрос есть две детали. Пара pageToken и pageTokenKey срабатывает только один раз: при повторном запросе с той же парой сервер отвечает ошибкой 10000004, и страницу нужно загрузить заново. Параметр captchaType в теле запроса принимает только значение 1; при любом другом приходит ошибка 10000001.

Значение type в ответе — это вид проверки у Yidun. Двойка означает пазл: в библиотеке капчи виды перечислены как JIGSAW 2, POINT 3, SMS 4, INTELLISENSE 5, ICON_POINT 7, INFERENCE 9, WORD_ORDER 10, SPACE 11, VOICE 12. Вид задан настройками Huawei, а не сценарием: запрос со sceneId register вернул то же значение.

Шаг второй: запрос captchaid

Ключа сайта в коде страницы нет. Обёртка Huawei запрашивает его у адреса из serviceDomain:

Copy
https://csc-adapter-dre.security.dbankcloud.com/captcha/v4/captchaid?businessId=huaweiup&sceneId=login&lang=ru-RU

Ответ на этот запрос и содержит всё, что осталось:

json Copy
{
  "resultCode": 0,
  "resultMessage": "Success",
  "captchaId": "0f743r3g1gm36431pg87n8rz3grz0ym5",
  "vendorServiceDomain": [
    "csc-captcha-dre.security.dbankcloud.com",
    "csc-captcha-dre.security.dbankcloud.cn"
  ],
  "vendorJsURL": [
    "contentcenter-dre.dbankcdn.com/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js"
  ]
}

Поле captchaId — это websiteKey. Первый адрес из vendorServiceDomain идёт в yidunApiServerSubdomain как есть, без https://. Первый адрес из vendorJsURL идёт в yidunGetLib, но к нему нужно дописать https:// — сервер отдаёт его без схемы.

Значения captchaId, vendorServiceDomain и vendorJsURL при проверке не менялись, поэтому их можно записать в код. А challenge, hcg и hct читайте заново каждый раз.

Примеры кода

Python + requests

Пример получает одноразовые значения, отправляет задачу и забирает решение. Значения pageToken и pageTokenKey возьмите со страницы входа: они разные в каждой сессии.

python Copy
import time

import requests

API_KEY = "ВАШ_API_КЛЮЧ"

PAGE_URL = "https://id7.cloud.huawei.com/CAS/portal/loginAuth.html"
WEBSITE_KEY = "0f743r3g1gm36431pg87n8rz3grz0ym5"
API_SUBDOMAIN = "csc-captcha-dre.security.dbankcloud.com"
GET_LIB = ("https://contentcenter-dre.dbankcdn.com"
           "/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js")

PAGE_TOKEN = "ЗНАЧЕНИЕ_СО_СТРАНИЦЫ"
PAGE_TOKEN_KEY = "ЗНАЧЕНИЕ_СО_СТРАНИЦЫ"

session = requests.Session()
session.headers["User-Agent"] = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
    "(KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
)

preprocess = session.post(
    "https://id7.cloud.huawei.com/CAS/IDM_W/ajaxHandler/cscPreprocess",
    params={"reflushCode": int(time.time() * 1000)},
    data={
        "pageToken": PAGE_TOKEN,
        "pageTokenKey": PAGE_TOKEN_KEY,
        "captchaType": "1",
        "clientType": "cas",
        "lang": "ru-ru",
        "sceneId": "login",
    },
    timeout=30,
).json()

if preprocess.get("isSuccess") != 1:
    raise RuntimeError(f"cscPreprocess не отдал параметры: {preprocess}")

task = {
    "type": "YidunTaskProxyless",
    "websiteURL": PAGE_URL,
    "websiteKey": WEBSITE_KEY,
    "userAgent": session.headers["User-Agent"],
    "yidunGetLib": GET_LIB,
    "yidunApiServerSubdomain": API_SUBDOMAIN,
    "challenge": preprocess["challenge"],
    "hcg": preprocess["hcg"],
    "hct": preprocess["hct"],
}

created = requests.post(
    "https://api.rucaptcha.com/createTask",
    json={"clientKey": API_KEY, "task": task},
    timeout=30,
).json()

if created.get("errorId") != 0:
    raise RuntimeError(f"Задача не создана: {created}")

task_id = created["taskId"]
print("Задача создана, id", task_id)

for _ in range(24):
    time.sleep(5)

    result = requests.post(
        "https://api.rucaptcha.com/getTaskResult",
        json={"clientKey": API_KEY, "taskId": task_id},
        timeout=30,
    ).json()

    if result.get("errorId") != 0:
        raise RuntimeError(f"Ошибка: {result}")

    if result.get("status") == "ready":
        validate = result["solution"]["token"]
        print("Решение получено:", validate[:30], "…")
        break
else:
    raise RuntimeError("Решение не пришло за отведённое время")

Python + Playwright

Пример открывает страницу входа, читает с неё служебные значения, повторяет оба запроса Huawei, отправляет задачу и собирает готовый authcode.

python Copy
import json
import os
import time

import requests
from playwright.sync_api import sync_playwright

API_KEY = os.getenv("APIKEY_RUCAPTCHA", "ВАШ_API_КЛЮЧ")
PAGE_URL = "https://id7.cloud.huawei.com/CAS/portal/loginAuth.html"
WEBSITE_KEY = "0f743r3g1gm36431pg87n8rz3grz0ym5"
API_SUBDOMAIN = "csc-captcha-dre.security.dbankcloud.com"
GET_LIB = ("https://contentcenter-dre.dbankcdn.com"
           "/pub_1/cscaptcha_captcha_900_9/b/v3/netease/static/load.min.js")


def solve(task):
    created = requests.post(
        "https://api.rucaptcha.com/createTask",
        json={"clientKey": API_KEY, "task": task},
        timeout=30,
    ).json()

    if created.get("errorId") != 0:
        raise RuntimeError(f"Задача не создана: {created}")

    task_id = created["taskId"]
    print("Задача создана, id", task_id)

    for _ in range(24):
        time.sleep(5)

        result = requests.post(
            "https://api.rucaptcha.com/getTaskResult",
            json={"clientKey": API_KEY, "taskId": task_id},
            timeout=30,
        ).json()

        if result.get("errorId") != 0:
            raise RuntimeError(f"Ошибка: {result}")

        if result.get("status") == "ready":
            return result["solution"]["token"]

    raise RuntimeError("Решение не пришло за отведённое время")


with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    try:
        page.goto(PAGE_URL)
        page.wait_for_function("window.localInfo !== undefined", timeout=30000)

        local_info = page.evaluate("""() => ({
            pageToken: window.localInfo.pageToken,
            pageTokenKey: window.localInfo.pageTokenKey,
            sceneId: window.localInfo.cscSceneId,
            captchaType: window.localInfo.displayCaptchaType,
            lang: window.localInfo.lang || 'ru-ru',
        })""")

        preprocess = page.evaluate("""async (info) => {
            const body = new URLSearchParams({
                pageToken: info.pageToken,
                pageTokenKey: info.pageTokenKey,
                captchaType: info.captchaType,
                clientType: 'cas',
                lang: info.lang,
                sceneId: info.sceneId,
            });
            const url = '/CAS/IDM_W/ajaxHandler/cscPreprocess?reflushCode=' + Date.now();
            const response = await fetch(url, {
                method: 'POST',
                credentials: 'include',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body,
            });
            return response.json();
        }""", local_info)

        if preprocess.get("isSuccess") != 1:
            raise RuntimeError(f"cscPreprocess не отдал параметры: {preprocess}")

        user_agent = page.evaluate("navigator.userAgent")

        validate = solve({
            "type": "YidunTaskProxyless",
            "websiteURL": PAGE_URL,
            "websiteKey": WEBSITE_KEY,
            "userAgent": user_agent,
            "yidunGetLib": GET_LIB,
            "yidunApiServerSubdomain": API_SUBDOMAIN,
            "challenge": preprocess["challenge"],
            "hcg": preprocess["hcg"],
            "hct": preprocess["hct"],
        })

        authcode = json.dumps({
            "type": preprocess["type"],
            "sceneId": preprocess["sceneId"],
            "lang": local_info["lang"],
            "challenge": preprocess["challenge"],
            "hcg": preprocess["hcg"],
            "hct": preprocess["hct"],
            "validate": validate,
        })

        print("Готовый authcode:", authcode[:80], "…")

    except Exception as e:
        print(f"Ошибка: {e}")
    finally:
        browser.close()

Как использовать полученный токен

Сервис возвращает решение в поле solution.token. У Yidun это значение называется validate. Обычно его кладут в скрытое поле формы. На странице входа Huawei такое поле есть — это input с идентификатором captchaInfo внутри блока hwid-captchaHtml, — но обработчик страницы его не читает.

Вместо этого страница собирает из решения строку JSON и отправляет её отдельным параметром запроса под именем authcode. В коде страницы это выглядит так:

javascript Copy
getRandomCode: function (result) {
    var t = { validate: result.validate };
    return JSON.stringify(be.extend(this.secondverifyParam, t));
}

Объект secondverifyParam страница собрала раньше, из ответа cscPreprocess. В итоге в authcode попадает семь значений:

json Copy
{
  "type": 2,
  "sceneId": "login",
  "lang": "ru-RU",
  "challenge": "f4df3943be517cca2b6060842c4cb96daf6b22e2f15f521ef2177031bab2069b",
  "hcg": "1cb7f8d1fa60134e7f5c92b15f96205046cbd91581eb0c16c9d3df63db9967e1",
  "hct": 1788597543413,
  "validate": "РЕШЕНИЕ_ОТ_СЕРВИСА"
}

Отсюда два правила. Значения challenge, hcg и hct нужны дважды: сначала в задаче, потом в authcode, и это должны быть одни и те же значения. И решение само по себе бесполезно: сервер ждёт его внутри строки, а не отдельно.

Частые ошибки и решения

Ошибка или проблема Причина Решение
Сервис решает капчу, но сервер Huawei отклоняет ответ В задаче не были переданы challenge, hcg и hct Передавайте все три: на этом сайте стоит версия Enterprise
Ошибка при создании задачи из-за ключа сайта Ключ искали в коде страницы, а его там нет Ключ отдаёт запрос captcha/v4/captchaid, он же указан в статье
Ответ приходит, но сервер отвечает ошибкой проверки В задаче и в authcode оказались разные challenge, hcg и hct Получите тройку один раз и используйте её в обоих местах
Запрос cscPreprocess отвечает ошибкой 10000004 Пара pageToken и pageTokenKey уже была использована Значения одноразовые. Загрузите страницу заново и возьмите новые
Запрос cscPreprocess отвечает ошибкой 10000001 В теле запроса передан captchaType, отличный от 1 Здесь допустимо только значение 1. С видом проверки у Yidun это поле не связано
Форма уходит без решения Решение записали в скрытое поле captchaInfo Поле на странице есть, но обработчик его не читает. Собирайте authcode
Капча не появляется совсем Сервер решил, что проверка не нужна Это нормально. Обрабатывайте оба случая: с капчей и без неё
Сервер отвечает, что параметры устарели Между получением тройки и отправкой прошло слишком много времени Собирайте параметры прямо перед созданием задачи

Полный список кодов ошибок находится на странице «Коды ошибок», ссылка на неё ниже.

Полезные ссылки