Клики, прокрутка и XHR на Python
Браузер нужен, когда сайт создаёт карточки JavaScript-кодом или требует действия. HTTP и браузер используют общие правила разрешённых адресов, но открытая страница имеет собственную сессию. На агенте должна быть включена поддержка браузера.
def run(ctx):
page = ctx.browser().open(ctx.param('catalog_url'), ['*/api/products*'])
try:
page.click('button.show-products')
page.type('input[name="search"]', 'кабель')
page.press('input[name="search"]', 'Enter')
page.wait_for('.product-card')
seen = set()
for step in range(10):
if ctx.cancelled():
ctx.abort('Остановлено пользователем')
dom = ctx.dom(page.content(), ctx.param('catalog_url'))
added = 0
for card in dom.qa('.product-card'):
sku = card.attr('data-sku')
if not sku or sku in seen:
continue
seen.add(sku)
added += 1
ctx.emit({'sku': sku, 'name': card.text()}, sku)
if added == 0:
break
page.scroll(1, 500)
ctx.progress(step + 1, 10, 'Прокрутка каталога')
finally:
page.close()
Селекторы и предел десять шагов приведены для примера. Настройте их под источник. Наличие карточки после wait_for ещё не гарантирует, что загрузилась следующая пачка. Повтор набора без новых ключей завершает цикл.
Захват сети включайте до действия: второй аргумент open ловит первые запросы, а page.capture_responses([...]) включает последующие. Вызов очищает прежний буфер; пустой список отключает захват. wait_for_response(pattern, timeout_ms) ждёт ограниченное время, responses() возвращает накопленные результаты. Не записывайте тела приватных ответов и заголовки авторизации в журнал.
page.close() в finally обязателен: это освобождает ресурс и при HTTP/SDK-ошибке, и при остановке. Скриншот возвращает идентификатор артефакта; это не байты PNG в Python-процессе. Все методы действий и их таймауты: BrowserPage.