2025, Dec 30 00:01

Как стабилизировать сессию nodriver с Chrome 136 и пройти Cloudflare verify_cf на Fedora 42

Решение раннего завершения сессии nodriver 0.46.1 с Chrome 136: явные флаги запуска, отключение песочницы и успешный проход Cloudflare verify_cf на Fedora 42.

При связке nodriver 0.46.1 с Google Chrome 136 на Fedora 42 сессия может завершаться сразу после запуска. Окно вспыхивает и исчезает, процесс удаляет временный профиль, и целевая страница не успевает загрузиться. Особенно заметно это при переходе на маршруты, защищённые Cloudflare, и вызове verify_cf(). Такой же внезапный выход может проявляться и на других сайтах, что усложняет диагностику.

Минимальный пример, который воспроизводит поведение

Ниже приведённый фрагмент воспроизводит ранний выход: браузер запускается, запрашивается страница, ожидается verify_cf(), и скрипт почти сразу завершается.

import nodriver as drv
from time import sleep

async def entry():
    agent = await drv.start(headless=False)
    tab = await agent.get('https://dash.cloudflare.com/login')
    await tab.verify_cf()

if __name__ == '__main__':
    drv.loop().run_until_complete(entry())
    sleep(2)

Что на самом деле происходит

Со стороны это больше похоже на проблему жизненного цикла, а не на ошибку навигации: страница не успевает отрисоваться, а единственная запись в логах — что nodriver успешно удалил временный профиль в /tmp. Использование asyncio.run() вместо цикла библиотеки результата не меняет. Эффект одинаков на разных адресатах, не только на защищённых Cloudflare.

Отдельно, когда verify_cf() всё же выполняется, он может нажать на чекбокс Cloudflare, но встроенный виджет после короткой загрузки всё равно попросит повторное нажатие. Выполнив этот клик вручную в той же сессии, можно пройти проверку.

Практичный способ сохранить сессию «живой» и наблюдаемой

Запуск браузера с более явной конфигурацией помогает удержать его в работе достаточно долго, чтобы увидеть, что происходит, и выполнить verify_cf(). Ниже предложены настройки: отключение песочницы и набор флагов, снижающих системные конфликты, плюс лёгкая трассировка и явное завершение. Это не меняет основной логики вашего сценария, но придаёт сессии стабильность и прозрачность.

import nodriver as drv
import asyncio
from time import sleep

async def runner():
    try:
        session = await drv.start(
            headless=False,
            sandbox=False,
            user_data_dir=None,
            args=[
                '--no-sandbox',
                '--disable-dev-shm-usage',
                '--disable-gpu',
                '--disable-features=VizDisplayCompositor',
                '--disable-extensions',
                '--disable-plugins',
                '--disable-images'
            ]
        )

        print('Browser session initialized')

        view = await session.get('https://dash.cloudflare.com/login')
        print('Navigation completed')

        await asyncio.sleep(3)

        await view.verify_cf()
        print('verify_cf() invoked')

        await asyncio.sleep(10)

    except Exception as exc:
        print(f'Error: {exc}')
        import traceback
        traceback.print_exc()
    finally:
        try:
            await session.quit()
        except:
            pass

if __name__ == '__main__':
    asyncio.run(runner())

С такой конфигурацией браузер стабильно запускается, переходит на целевую страницу и выполняет verify_cf(). Если после этого виджет Cloudflare просит повторного взаимодействия, его можно сделать вручную в том же экземпляре — проверка пройдёт.

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

Автоматизированные стеки для веб-навигации хрупки на стыке версий браузера и сборок ОС, а преждевременные завершения легко принять за ошибки навигации или скрипта. Конфигурация, сохраняющая сессию в стабильном и наблюдаемом состоянии, необходима, чтобы понять, где именно происходит сбой. В нашем случае удержание процесса «живым» позволяет разделить вопросы жизненного цикла процесса, таймингов загрузки страницы и поведения verify_cf() внутри виджета с проверкой.

Выводы

Делайте параметры запуска явными, чтобы сессия не завершалась до выполнения ваших асинхронных задач. Добавьте минимальную трассировку, чтобы видеть, куда доходит поток управления и где он останавливается. Если verify_cf() вызывает проверку, но виджет всё ещё просит дополнительный клик, выполните его вручную в той же сессии — это позволит продолжить поток. Также убедитесь, что у вас корректные отступы и структура async в Python, чтобы выполнение доходило до ожидаемых await.

Итог прост: сначала стабилизируйте жизненный цикл браузера, затем наблюдайте этап Cloudflare. Когда сессия стабильно стартует, становится видно, что именно делает verify_cf() и где ещё требуется ручное действие.