Как устранить проблему с подключением к серверу через WebSocket?

Здравствуйте! <br/> Я планирую создать небольшой скрипт для парсинга данных в реальном времени. Функционал уже реализован разработчиками сайта, однако он работает исключительно в браузере. <br/> У меня до этого не было опыта с парсингом, и тем более с вебсокетами, поэтому я не знаю, с чего начать. <br/> Возникла проблема: мне удается установить соединение и получать данные в течение 5-10 секунд, после чего соединение разрывается с сообщением - received 1008 (policy violation); после чего отправляется 1008 (policy violation). <br/><br/> Похоже, что сервер определяет, что соединение не осуществляется из браузера, и разрывает его. Я передал актуальные куки в заголовке, включая свежий Cloudflare идентификатор и сессионный идентификатор, всё как в браузере, кроме следующих заголовков: <br/> sec-websocket-extensions: permessage-deflate; client_max_window_bits <br/> sec-websocket-key: V+rF18z4GSVP5KRDVDxw== <br/> sec-websocket-version: 13 <br/> Я не могу передать эти заголовки, поскольку, по-видимому, они генерируются клиентом при установке соединения. <br/> Заголовок, который я использую, выглядит следующим образом: я экспериментировал с разным количеством информации в заголовке, как с большим, так и с меньшим, но результат остается прежним — соединение обрывается через 5-7 секунд. Заголовок: <br/> { <br/> "Origin": "URL", <br/> "User-Agent": "AGENT", <br/> 'Cookie': 'SESSID=ID; cf_clearance=cloudflare_id <br/> } <br/><br/> Можете подсказать, в чем может быть проблема и возможно ли её обойти? <br/> Пример кода для соединения выглядит так: <br/> <pre><code class="python">import asyncio
import websockets

async def connect():
    try:
        async with websockets.connect(uri, additional_headers=headers) as ws:
            print("Connected!")

            while True:
                message = await ws.recv()
                print(f"Received: {message}")
  • 8 апреля 2025 г. 20:05
Ответы на вопрос 2
Проблема, с которой вы столкнулись, может быть связана с тем, что сервер WebSocket проверяет, является ли клиент настоящим браузером. Чтобы минимизировать вероятность разрыва соединения из-за политики, следует обратить внимание на несколько ключевых моментов:

1. **User-Agent и другие заголовки**: Попробуйте использовать `User-Agent`, который соответствует популярному браузеру. Также убедитесь, что заголовки, которые вы отправляете, совпадают с заголовками, которые действительно отсылает браузер (вы можете использовать инструменты разработчика в браузере для мониторинга заголовков).

2. **Закрытие соединения**: Если сервер разрывает соединение с ошибкой `1008 (policy violation)`, это может указывать на то, что он применяет политику безопасности для защиты от нестандартных клиентов. Проверьте наличие дополнительных заголовков, которые могут потребоваться, таких как `sec-websocket-protocol`, если сервер их ожидает.

3. **Обработка идентификатора сессии**: Убедитесь, что идентификатор сессии и `cf_clearance` актуальные. Используйте инструменты для мониторинга HTTP-трафика, такие как Fiddler или Wireshark, чтобы проверить, какие заголовки и куки отправляются из вашего браузера.

4. **Секреты WebSocket**: Протокол WebSocket может требовать определенных заголовков, которые не всегда можно передать напрямую. Если кто-то в команде разработчиков упоминал о специфических заголовках или параметрах, которые необходимо передать, убедитесь, что вы это сделали.

5. **Timeout и Ping/Pong**: Иногда сервера WebSocket могут ожидать периодического pинг-понга для поддержания соединения. Если вы не отправляете PING-сообщения в течение определенного времени, сервер может разорвать соединение. Проверьте документацию API, если доступна, на наличие информации о временных ограничения на соединение или необходимости пинингов.

6. **Использование библиотеки**: Если вы пишете на Python, убедитесь, что используемая библиотека (например, `websockets`) соответствует текущему протоколу и спецификациям WebSocket. В некоторых случаях использование другой библиотеки может помочь.

7. **Обратный подход**: Попробуйте эмитировать браузер, например, с помощью `Selenium`, который может через Headless браузер взаимодействовать с сайтами, поддерживающими WebSocket, не сталкиваясь с политиками безопасности напрямую.

Пример кода с использованием `websockets`:

```python
import asyncio
import websockets

async def connect():
    uri = "wss://example.com/websocket"
    headers = {
        "Origin": "http://example.com",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
        'Cookie': 'SESSID=ID; cf_clearance=cloudflare_id'
    }

    try:
        async with websockets.connect(uri, extra_headers=headers) as ws:
            print("Connected!")

            while True:
                message = await ws.recv()
                print(f"Received: {message}")

    except Exception as e:
        print(f"Error: {e}")

asyncio.run(connect())
```

Не забудьте протестировать различные изменения в заголовках, и, возможно, использовать дополнительные инструменты для анализа WebSocket-трафика. Иногда простая ошибка в заголовках может быть причиной разрыва подключения.
Сохрани сессию в браузере в .har файл (консоль разработчика - сеть) и изучи его досканально, в худшем случае придется реверсить скрипты браузера, потому что информацию о том что это браузерный клиент можно передавать даже в таймингах задержек принятия сообщений, т.е. по самим сообщениям этого видно не будет.
Похожие вопросы