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. Разрешает использовать действительные локальные файлы и права при временной недоступности сервиса. Неверная подпись, повреждение, отзыв или истечение прав всё равно вызывают ошибку. |
| channel | None — стандартный канал DuckoLab. Объект ReleaseChannel нужен только для самостоятельной настройки адресов доставки и доверенных ключей. |
| bundle | None — стандартный комплект файлов библиотеки. Иной локальный путь нужен при собственной схеме размещения компонентов; это не путь к браузерному профилю. |
| ca_bundle | Путь к файлу доверенных CA для HTTPS-запросов. None оставляет стандартную настройку. Проверку сертификатов этот параметр не отключает. |
| proxy | None или ProxyRoute. Строки/словарь proxies здесь не поддерживаются. |
| cookie_policy | None или CookiePolicyOptions. None выбирает стандартную политику cookies браузера. Это не словарь cookies. |
HTTP-протокол
application выбирает вариант профиля. Для большинства запросов оставьте значение h2. Выбирайте другой вариант, если приложению нужен определённый режим соединения:
| Значение | Назначение |
|---|---|
h1 | Профиль для запросов HTTP/1.1. У Client это выбор профиля, а не принудительное ограничение протокола отдельного запроса: профиль может допускать HTTP/2. Для обязательного HTTP/1.1 используйте HttpClient(protocol='h1'). |
h2 | HTTP/2 с возможностью согласовать HTTP/1.1 с сервером. Значение по умолчанию. |
h3 | HTTP/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. |
| body | b'' | Готовое тело: bytes либо строка, кодируемая в UTF-8. JSON и форму сериализуйте сами или используйте HttpClient. |
| timeout_ms | 30000 | Таймаут передачи, миллисекунды. Не timeout в секундах. |
| body_limit | 1048576 | Лимит удерживаемого буферизованного тела, байты. Превышение — ошибка, не молчаливое обрезание. |
| header_limit | 65536 | Максимальный размер сохраняемых заголовков ответа, в байтах. |
| body_mode | 1 | Для 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 сохраняют прежнюю семантику.