2025, Oct 18 20:16

Скачивание защищённого PDF с NYSCEF через SeleniumBase и CDP Mode

Столкнулись с 403 и пустым просмотрщиком на NYSCEF? Показываем, как надежно скачать защищённый PDF с помощью SeleniumBase в CDP Mode и настроек external_pdf.

Скачивание защищённого PDF с портала NYSCEF кажется обманчиво простым, пока вы не натыкаетесь на привычный 403 Forbidden или пустую страницу просмотрщика. Если вы уже пробовали подставлять браузерные заголовки в requests или сканировать страницу через Selenium, но не нашли тега <embed> и увидели пустой интерфейс, значит, столкнулись с теми же препятствиями. Ниже — краткое объяснение, почему это происходит и как надёжно настроить загрузку с SeleniumBase.

Воспроизведение ошибки

Первая мысль — получить документ по HTTP или прибегнуть к автоматизации браузера: извлечь URL PDF из <embed>, а затем скачать бинарный файл, используя куки текущей сессии. Ниже минимальный пример, который делает именно это, но на данном сайте не срабатывает:

from seleniumbase import SB
import requests
import os
import time
def pull_pdf_via_browser_then_http():
    doc_link = "https://iapps.courts.state.ny.us/nyscef/ViewDocument?docIndex=cdHe_PLUS_DaUdFKcTLzBtSo6zw=="
    out_dir = os.path.join(os.getcwd(), "downloads")
    os.makedirs(out_dir, exist_ok=True)
    out_path = os.path.join(out_dir, "NYSCEF_Document.pdf")
    with SB(headless=True) as browser:
        browser.open(doc_link)
        time.sleep(5)
        try:
            node_embed = browser.find_element("embed")
            pdf_link = node_embed.get_attribute("src")
            print(f"PDF URL detected: {pdf_link}")
        except Exception as err:
            print(f"Embed tag not found: {err}")
            return
        cookies_from_driver = browser.driver.get_cookies()
        http_sess = requests.Session()
        for c in cookies_from_driver:
            http_sess.cookies.set(c["name"], c["value"])
        net_headers = {
            "User-Agent": "Mozilla/5.0",
            "Referer": doc_link,
        }
        resp = http_sess.get(pdf_link, headers=net_headers)
        if resp.status_code == 200 and "application/pdf" in resp.headers.get("Content-Type", ""):
            with open(out_path, "wb") as fh:
                fh.write(resp.content)
            print(f"Saved to: {out_path}")
        else:
            print(f"Download failed. Status: {resp.status_code}")
            print(f"Content-Type: {resp.headers.get('Content-Type')}")
            print(f"Resolved URL: {resp.url}")
if __name__ == "__main__":
    pull_pdf_via_browser_then_http()

Обычно итог — либо 403 на HTTP-запрос, либо отсутствие узла <embed> после рендеринга страницы. Даже прямой requests.get с правдоподобными User-Agent и Referer стабильно возвращает 403.

Почему это не работает здесь

Для этого эндпоинта одних заголовков недостаточно. Сервер отличает настоящие браузеры от скриптов с помощью таких механизмов, как TLS-фингерпринтинг и проверки во время выполнения через JavaScript. Поэтому статический HTTP-запрос, который внешне выглядит корректно, всё равно блокируется, а браузерная сессия может показывать пустую страницу, не раскрывая ни <embed>, ни прямой URL PDF. Важно понимать: файл не в открытом доступе, доступ контролируется, а не-человеческие клиенты отсекаются. Если вы уверены, что имеете право на доступ, но всё ещё заблокированы, обратитесь к владельцам сайта.

Рабочий подход

В данном случае помогает SeleniumBase в особом режиме. Запуск в CDP Mode с параметрами, позволяющими автоматически скачивать PDF, помогает сессии пройти проверку на ботов и сохранить файл прямо в папку загрузок по умолчанию. Это снимает необходимость искать <embed> или повторно инициировать скачивание через requests.

from seleniumbase import SB
with SB(uc=True, test=True, external_pdf=True) as driver:
    resource_url = "https://iapps.courts.state.ny.us/nyscef/ViewDocument?docIndex=cdHe_PLUS_DaUdFKcTLzBtSo6zw=="
    driver.activate_cdp_mode(resource_url)
    driver.sleep(10)

Файл сохраняется в каталог ./downloaded_files/. По сути, включение CDP Mode позволяет пройти защиту, препятствующую получению ресурса не-человеческими клиентами, а настройка сессии на загрузку PDF как файла, а не на встроенное отображение, избавляет от проблемы с пустым просмотрщиком.

Почему это важно

Современные публичные ресурсы часто ограничивают доступ через антибот-проверки. Одного копирования заголовков недостаточно, а порой даже безголовый браузер не покажет ожидаемые DOM-узлы. Понимание, когда нужно перейти от «голого» HTTP к полноценной автоматизации браузера, способной пройти фингерпринт-проверки, спасает часы бесплодной отладки. Также важно распознавать случаи, когда ресурс намеренно защищён и его нельзя получить, не пройдя такие проверки.

Выводы

Если прямой запрос возвращает 403, а на странице нет <embed>, который можно было бы использовать, скорее всего, срабатывает антибот-защита, а не «потерянный селектор». Применяйте инструмент автоматизации браузера, способный работать в режиме, рассчитанном на прохождение таких проверок, и настраивайте его на загрузку PDF как файла, а не на встроенный просмотр. Если у вас есть законные основания для доступа, но загрузка всё равно недоступна, свяжитесь с администраторами сайта для предоставления корректного доступа.

Статья основана на вопросе с StackOverflow от Daremitsu и ответе Michael Mintz.