DuckoNetДокументация 0.11.5Документация DuckoLab
Разделы

Client и AsyncClient

Client и AsyncClient отправляют запросы с браузерным контекстом и возвращают Response, в котором тело и заголовки представлены байтами. Контекст задаёт происхождение запроса и правила cookies. Если его не передать, клиент использует контекст открытия указанной страницы.

Выбирайте этот интерфейс, если хотите управлять контекстом и обработкой байтов непосредственно. Для параметров URL, JSON, форм, файлов, автоматических перенаправлений и чтения .text/.json() используйте HttpClient. Оба интерфейса входят в DuckoNet 0.11.5.

Основной импорт: from duckonet import Client, AsyncClient, StartupInfo, StartupError.

Client(*, api_key, browser='chrome', version=None, application='h2',
       state_dir=None, check_interval=300, allow_offline=True,
       channel=None, bundle=None, profile_id=None, ca_bundle=None,
       proxy=None, cookie_policy=None)

AsyncClient наследует тот же конструктор. Все аргументы именованные.

АргументСмысл и ограничения
api_keyОбязательная строка с API-ключом DuckoLab. Используется для доступа к библиотеке, а не для авторизации на целевом сайте.
browserСемейство браузерного профиля. Поддерживается chrome.
versionПолная строка версии Chrome или None. При None, если не указан profile_id, выбирается максимальная доступная версия для вашего ключа.
applicationВариант сетевого профиля. По умолчанию h2. Значения и выбор режима объяснены ниже, в разделе «HTTP-протокол».
profile_idТочный идентификатор профиля в каталоге. Он должен соответствовать остальным условиям выбора: браузеру, платформе, application, версии и правам API-ключа.
state_dirПуть постоянной установки; None означает Path.home()/'.duckonet'/'default'.
check_intervalИнтервал проверки обновлений при открытии клиента, в секундах: целое число от 0 до 3600, по умолчанию 300. При 0 проверка выполняется при каждом открытии нового клиента.
allow_offlineПо умолчанию True. Разрешает использовать действительные локальные файлы и права при временной недоступности сервиса. Неверная подпись, повреждение, отзыв или истечение прав всё равно вызывают ошибку.
channelNone — стандартный канал DuckoLab. Объект ReleaseChannel нужен только для самостоятельной настройки адресов доставки и доверенных ключей.
bundleNone — стандартный комплект файлов библиотеки. Иной локальный путь нужен при собственной схеме размещения компонентов; это не путь к браузерному профилю.
ca_bundleПуть к файлу доверенных CA для HTTPS-запросов. None оставляет стандартную настройку. Проверку сертификатов этот параметр не отключает.
proxyNone или ProxyRoute. Строки/словарь proxies здесь не поддерживаются.
cookie_policyNone или CookiePolicyOptions. None выбирает стандартную политику cookies браузера. Это не словарь cookies.

HTTP-протокол

application выбирает вариант профиля. Для большинства запросов оставьте значение h2. Выбирайте другой вариант, если приложению нужен определённый режим соединения:

ЗначениеНазначение
h1Профиль для запросов HTTP/1.1. У Client это выбор профиля, а не принудительное ограничение протокола отдельного запроса: профиль может допускать HTTP/2. Для обязательного HTTP/1.1 используйте HttpClient(protocol='h1').
h2HTTP/2 с возможностью согласовать HTTP/1.1 с сервером. Значение по умолчанию.
h3HTTP/2 с возможностью перехода на HTTP/3, когда сервер объявляет подходящий адрес через Alt-Svc.
h2_onlyТолько HTTP/2, без перехода на HTTP/1.1. Требует соответствующего профиля и поддержки сервера.
h3_onlyТолько HTTP/3. Требует соответствующего профиля, поддержки сервера и доступного UDP-маршрута.

Профиль выбранного варианта должен присутствовать в каталоге для вашей версии Chrome, платформы и API-ключа. Если подходящего профиля нет, открытие клиента завершается ошибкой выбора; библиотека не подменяет его другим вариантом. auto не является значением application у Client: это значение параметра protocol у HttpClient.

После запроса читайте response.protocol: 1 означает HTTP/1.1, 2 — HTTP/2, 3 — HTTP/3.

Методы и свойства

request(method, url, **kwargs) возвращает Response; get(url, **kwargs) и post(url, **kwargs) передают GET/POST в request. Другие методы задаются через request, например client.request('DELETE', url). Отдельных .put()/.patch()/.delete() нет. close() освобождает ресурсы клиента. У AsyncClient методы request/get/post/close надо await; используется async with, не with. startup_info первоначально None, после входа — StartupInfo. distribution — расширенный Distribution этой установки. Публичных .session, .stream, .cookies, .headers у этого клиента нет; для управления сессией используйте Distribution.

Если аргумент context отсутствует, клиент создаёт контекст открытия страницы для выбранного профиля Chrome или Edge. Метод Distribution.navigation_context(url, selection=...) позволяет явно получить такой контекст в расширенном API. Для другого происхождения запроса передайте соответствующий BrowserContext или BrowserHopContext. Явный context=None не создаёт контекст автоматически и может быть отклонён выбранным профилем.

Аргументы HTTP-запроса

request(), get() и post() принимают следующие именованные аргументы:

ИмяПо умолчаниюЗначение
headers()Последовательность пар (name,value), сохраняющая порядок/повторы. Не обычный dict; можно mapping.items(). Строковое имя — ASCII, значение — Latin-1.
bodyb''Готовое тело: bytes либо строка, кодируемая в UTF-8. JSON и форму сериализуйте сами или используйте HttpClient.
timeout_ms30000Таймаут передачи, миллисекунды. Не timeout в секундах.
body_limit1048576Лимит удерживаемого буферизованного тела, байты. Превышение — ошибка, не молчаливое обрезание.
header_limit65536Максимальный размер сохраняемых заголовков ответа, в байтах.
body_mode1Для request() значение должно быть 1: сохранить тело в памяти. Для чтения по частям используйте Session.stream() или HttpClient.stream().
contextсм. вышеКонтекст запроса: BrowserContext, BrowserHopContext или CookieContext. Допустимый тип зависит от профиля. Для поставляемого Chrome-профиля используйте браузерный контекст.

method — HTTP-метод в виде ASCII-строки, url — полный URL. Для клиентского вызова передавайте URL строкой; поддержка bytes у низкоуровневого компилятора не означает, что автоматическое создание браузерного контекста примет байты. Схема адреса, размеры и заголовки проверяются по правилам профиля. Заголовки Host, длину и способ передачи тела, а также защищённые браузерные поля формирует библиотека.

Аргументы json, data, params, timeout, verify, proxies, cookies, auth и allow_redirects в этом интерфейсе не поддерживаются: их передача вызывает ошибку. У HttpClient доступны json, data, params, cookies и allow_redirects. Таймаут задаётся через timeout_seconds, прокси — через proxy, доверенные сертификаты — через ca_bundle конструктора. Аргумент auth не поддерживается; заголовок авторизации целевого сайта задавайте через headers.

Client.request() не выполняет полный браузерный Fetch с CORS, preflight и перенаправлениями; для этого существует отдельная функция duckonet.browser_request(session, request) с объектом BrowserRequest и синхронной сессией. Это не метод клиента.

Response

Response и ResponseBlock — неизменяемые dataclass-значения. response.status_code — HTTP-код; protocol — номер протокола (1 — HTTP/1.1, 2 — HTTP/2, 3 — HTTP/3); body — bytes или None; url — bytes. Поля request_id/owner_id/epoch сопоставляют операцию, outcome — числовой результат выполнения запроса, body_complete, body_bytes_received, tls_verified — отдельные признаки результата.

response.blocks — все сохранённые блоки ResponseBlock(status_code,section,protocol,headers). response.headers — свойство, выбирающее заголовки последнего блока section=2. Каждая пара содержит bytes, не str; dict теряет дубликаты. Информационные блоки и trailers рассматривайте через blocks. response.headers вызывается без скобок.

У Response нет .text, .content, .json() и .raise_for_status(). Для текста выберите кодировку сами; для JSON используйте стандартный json. Ответ HTTP400/500 сам по себе не NativeError: проверяйте status_code. NativeError может сопровождаться частичным Response, у которого надо отдельно проверить body_complete.

import json

def decode_json_response(response):
    if not 200 <= response.status_code < 300:
        raise RuntimeError(f'HTTP {response.status_code}')
    if not response.body_complete or response.body is None:
        raise RuntimeError('Полное тело не сохранено')
    return json.loads(response.body)

def values_for(response, name):
    key = name.lower().encode('ascii')
    return [value for field, value in response.headers if field.lower() == key]

Клиент открывается один раз. После выхода из контекста, вызова close() или ошибки при открытии создайте новый экземпляр с тем же state_dir.

StartupInfo и обновления

StartupInfo содержит логические поля checked, updated, offline, enrolled. checked=True и updated=False означают, что проверка выполнена, но файлы не изменились. После первой регистрации возможно сочетание checked=True, enrolled=True, updated=False. При создании следующего клиента с тем же state_dir до истечения check_interval новая проверка обновлений не выполняется (checked=False). Сами HTTP-запросы проверку обновлений не запускают.

Подготовка одной установки выполняется последовательно под блокировкой. Ожидание ограничено 30 секундами, затем возникает STARTUP_BUSY. Продление разрешения на работу выполняется отдельно от загрузки профилей.

Активная сессия сохраняет своё поколение. После смены файлов установки открытая до обновления сессия может отклонять новые запросы: закройте её и создайте новый Client. Если в процесс уже загружено несовместимое ядро, перезапустите процесс. Загруженную библиотеку не перезаписывают во время работы.

Работа без доступа к сервису разрешена только при распознанной сетевой недоступности, ещё действительных локальных файлах и правах и отсутствии незавершённой операции записи. Ошибки подписи, повреждение, отзыв и истечение прав не переводятся в успешный автономный режим. При allow_offline=False требуется сетевая проверка, когда наступает срок check_interval.

Синхронный пример

import os
from duckonet import Client

with Client(api_key=os.environ['DUCKONET_API_KEY'], browser='chrome') as client:
    response = client.get('https://example.com/', timeout_ms=15_000)
    print(response.status_code)
    print((response.body or b'').decode('utf-8', errors='replace'))

Асинхронный пример

import asyncio
import os
from duckonet import AsyncClient

async def main():
    async with AsyncClient(api_key=os.environ['DUCKONET_API_KEY'], browser='chrome') as client:
        response = await client.get('https://example.com/')
        print(response.status_code, response.body_bytes_received)

asyncio.run(main())

Дополнительные сетевые возможности

В DuckoNet 0.11.5 доступны WebSocket через HttpClient/AsyncHttpClient и HTTP/3 через MASQUE. WebSocket открывается через HTTP/1.1 Upgrade; H3 требует явного MasqueProxy и совместимого HTTPS/H2 CONNECT-UDP сервера. Обычные proxy URLs сохраняют прежнюю семантику.

Текст страницы