Один из лучших способов автоматизировать получение данных с сайта — создать веб-сборщика, выполняющего эту работу. Вы можете запрограммировать его на сбор данных различными методами. Например, чтобы получать данные с сайта один раз в несколько часов или в неделю, нужно написать программу, которая будет автоматически отправлять HTTP-запрос или открывать браузер. Однако, если вам необходимо получать данные в течение нескольких секунд, все же лучше подключаться через веб-сокет (протокол дуплексной связи).
Прежде чем перейти к практической части программирования веб-сборщика, рассмотрим вкратце, что это такое и в каких случаях используется.
Проведем аналогию с ситуацией из повседневной жизни. Вы сказали другу, что позвоните ему, чтобы обсудить непонятную вам концепцию. Когда вы звоните ему (подтверждение соединения), он сначала проверяет, кто звонит, а затем решает, принимать ли звонок (верификация). Завершив проверку и приняв звонок, друг начнет объяснять концепцию и держать линию открытой для ваших входящих запросов (поток данных с сервера).
Обычно WebSocket используют для получения данных:
- о курсах криптовалют;
- о текущих ценах на акции;
- о ставках в реальном времени;
- об обмене сообщениями в live-режиме;
- о торговой платформе.
Теперь перейдем от теории к практике. Представьте, что вам нужно создать live-бота для торговли криптовалютами и вы уже разработали набор стратегий, чтобы обойти рынок. Что дальше?
Понадобится сайт, с которого можно получать данные в реальном времени. Вы перебираете разные варианты API, но опасаетесь, что они могут выйти из строя и вы потеряете деньги. Итак, вы решаете найти сайт, который предоставляет реальные цены на криптовалюты.
Допустим, ваш выбор падает на Cryptocompare — поставщика данных о мировом криптовалютном рынке.
Исследование
Зайдя на этот сайт через Chrome, выполните следующие действия.
- Щелкните правой кнопкой мыши и выберите пункт
inspect
. - Перейдите во вкладку WS — вам откроется изображение, похожее на скриншот выше (вы увидите, что url запроса для этого веб-сокета
wss://streamer.cryptocompare.com/v2?format=streamer
). - Перейдите во вкладку Message, чтобы получить сообщение, которое необходимо отправить на сервер для завершения верификации.
Обратите внимание на два типа стрелок.
- Зеленые указывают на исходящие сообщения, которые браузер отправляет на сервер.
- Красные обозначают входящие данные, получаемые браузером от сервера.
На данном этапе нужно просто скопировать 5 сообщений, отмеченных зеленой стрелкой. Для этого щелкните правой кнопкой мыши по каждому сообщению и выберите copy message
. Эти сообщения понадобятся при написании кода.
Написание кода
from websocket import create_connection
import json
# Скопируйте заголовок браузера и вставьте его в виде словаря
headers = json.dumps({
'Pragma': 'no-cache',
'Origin': 'https://www.cryptocompare.com',
'Accept-Language': 'en-US,en;q=0.9',
'Sec-WebSocket-Key': 'QknTzkhVwUs8UY+xAE22Kg==',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36',
'Upgrade': 'websocket',
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
'Cache-Control': 'no-cache',
'Connection': 'Upgrade',
'Sec-WebSocket-Version': '13',
})
# Запустите соединения с сервером (выполнение рукопожатия)
ws = create_connection('wss://streamer.cryptocompare.com/v2?format=streamer',headers=headers)
# Отправка исходящих сообщений на сервер
ws.send(json.dumps({"action":"SubAdd","subs":["24~CCCAGG~BTC~USD~H"]}))
ws.send(json.dumps({"action":"SubAdd","subs":["24~CCCAGG~ETH~USD~H"]}))
ws.send(json.dumps({"action":"SubAdd","subs":["5~CCCAGG~LTC~USD","24~CCCAGG~LTC~USD~H"]}))
ws.send(json.dumps({"action":"SubAdd","subs":["24~CCCAGG~XRP~USD~H"]}))
ws.send(json.dumps({"action":"SubAdd","subs":["11~BTC","21~BTC","5~CCCAGG~BTC~USD","11~ETH","21~ETH","5~CCCAGG~ETH~USD","11~SHIB","21~SHIB","5~CCCAGG~SHIB~USD","11~SOL","21~SOL","5~CCCAGG~SOL~USD","11~OMG","21~OMG","5~CCCAGG~OMG~USD","11~XRP","21~XRP","5~CCCAGG~XRP~USD","11~DOT","21~DOT","5~CCCAGG~DOT~USD","11~BUSD","21~BUSD","5~CCCAGG~BUSD~USD","11~ADA","21~ADA","5~CCCAGG~ADA~USD","11~SAND","21~SAND","5~CCCAGG~SAND~USD"]}))
# Получение входящих сообщений
while True:
try:
result = ws.recv()
print(result)
except Exception as e:
print(e)
break
Выше представлен фрагмент кода для примера. Обратите внимание на то, что необходимо изменить ключ WebSocket (Sec-WebSocket-Key
) на тот, который вы получите из браузера во вкладке Headers. Пример ниже:
Вот краткое описание того, что выполняет приведенный выше фрагмент кода.
- Создает соединения с url запроса.
- Отправляет 5 исходящих сообщений на сервер.
Теперь ждите входящих сообщений (обычно это происходит в течение нескольких секунд).
Результат
Сохраните фрагмент кода в файл python
и запустите его. Вы должны увидеть результат, аналогичный приведенному выше.
Возможные проблемы
Вот некоторые проблемы, с которыми можно столкнуться, и способы их решения.
1. Сообщение об ошибке: Connection is already closed
Это сообщение обычно означает, что сервер мешает вам подключиться. Самый быстрый способ решить эту проблему — сменить прокси-сервер или использовать VPN.
2. Код состояния HTTP: 401 (Unauthorized)
Ответ 401 означает, что сервер не принимает запрос на подключение. Если сервер работает нормально, значит, проблема в самом запросе. Возможно, вы используете неправильные учетные данные. Чтобы решить эту проблему, проверьте заголовки запроса и измените их соответствующим образом.
3. Код состояния HTTP: 403 (Forbidden)
Аналогично 401, но в данном случае повторная аутентификация ничего не изменит. Это может означать, что первоначальная логика приложения изменилась, например изменился процесс подтверждения соединения. Чтобы убедиться в отлаженной работе приложения, проверьте заголовки запросов и сообщения, которые необходимо отправить на сервер.
Читайте также:
- Использование вебсокетов в промис-стиле
- 4 Способа обмена данными между вкладками браузера в режиме реального времени
- API, WebSocket или WebHook: что выбрать?
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Low Wei Hong: Why you should use WebSocket to retrieve live crypto data