Puppetter и WebSocket
Проблема: Я скраплю страницу при помощи Puppetter на которой есть несколько Websocket соединений. И одно из соединений представляет собой видеострим который сильно тормозит работу (я запускаю через google cloud function + использую прокси = для меня очень важен вопрос минимизации трафика, ресурсов и скорость выполнения).
Задача: Заблокировать одно из соединений.
Варианты решения:
- Запретить доступ к этому URL
- Оборвать соединение после подключения
- Обернуть нативный WebSocket
Что я попытался сделать
Запретить доступ к этому URL. К сожалению, через page.on('request', () => {})
не видно этих запросов. Об этом есть вот такая ветка https://github.com/puppeteer/puppeteer/issues/2974
Запуская вот так, получаешь все соединения кроме WebSocket
await page.setRequestInterception(true);
page.on('request', async (request) => {
console.log(request.url());
})
Оборвать соединение после подключения. Здесь я вообще не нашел никаких решений. Я понимаю как при помощи CDPSession
получить инфу о WS подключениях, скрапить данные оттуда, но вот если и можно как-то отрубить соединение - я незнаю как.
const session = await page.target().createCDPSession();
const subscribe = async (session: CDPSession) => {
session.on('sessionattached', (s) => {
subscribe(s);
});
session.send('Network.enable');
session.on('Network.webSocketCreated', (payload) => {
console.log('webSocketCreated', payload.url)
})
session.send('Runtime.runIfWaitingForDebugger');
}
await session.send('Target.setAutoAttach', {
autoAttach: true,
flatten: true,
waitForDebuggerOnStart: true,
});
subscribe(session);
Что я делать не хочу
Оборачивать нативный WS и самому решать что там делать с подключениями. Я понимаю как это реализовать, но мне очень не хочется идти по этому пути
Буду признателен за любую подсказку!
UPD Страница спрятана за авторизацию, не публичную. Так что дать адрес не могу. Потестировать свое решение можно например вот здесь https://piehost.com/websocket-tester Подключившись к этому Websocket серверу wss://stream.binance.com:9443/ws/etheur@trade
Ответы (1 шт):
Решение основано на переопределении метода send
, пример снифера на github
Объяснение: в моменте вызова ws.send()
узнать url
текущего сокета и если он совпадает с искомым — закрыть его.
Приведенный ниже код работает для сервиса из вопроса.
(function () {
WebSocket.prototype._send = WebSocket.prototype.send;
WebSocket.prototype.send = function (data) {
this._send(data); // отсылаем данные через оригинальную функцию
if (this.url === 'wss://demo.piesocket.com/v3/channel_123?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV¬ify_self')
this.close()
}
})()
Воспроизведение:
- открываем https://piehost.com/websocket-tester
- производим соединение вебсокета через веб-интерфейс
- запускаем наш снипет в консоли
dev-tools
- отсылаем сообщение через веб-интерфейс сервиса.