Кукольник page.evaluate - получить прогресс - PullRequest
0 голосов
/ 28 марта 2019

У меня есть следующий код, чтобы попытаться получить буфер массива с текущей страницы в puppeteer:

await page.evaluate(cb => {

    var x = new XMLHttpRequest();
    var url = location.href;
    x.onreadystatechange = function(){
        console.log((x.response));
    }
    x.responseType="arraybuffer";
    x.open("GET",url,true);
    x.send("");
});

В настоящее время я пытаюсь перехватить файл console.log, чтобы получить ответ:

page.on("console", c => {
    console.log("Consoling", c._args[0]._remoteObject); //thought this would get the arraybuffer
});

, хотя он не дает мне фактический объект массива буферов, только вот это (если я просто сделаю c):

Consoling [ JSHandle {
    _context:
     ExecutionContext { _client: [CDPSession], _world: [DOMWorld], _contextId: 3 },
    _client:
     CDPSession {
       _events: [Object],
       _eventsCount: 27,
       _maxListeners: undefined,
       _callbacks: Map {},
       _connection: [Connection],
       _targetType: 'page',
       _sessionId: '817AEFBC94D1B52BC15559269CB67A61' },
    _remoteObject:
     { type: 'object',
       subtype: 'arraybuffer',
       className: 'ArrayBuffer',
       description: 'ArrayBuffer(40285)',
       objectId: '{"injectedScriptId":3,"id":1}',
       preview: [Object] },
    _disposed: false } ]

и следующее для текущего console.log (c [0]._remoteObject):

Consoling { type: 'object',
  subtype: 'arraybuffer',
  className: 'ArrayBuffer',
  description: 'ArrayBuffer(40285)',
  objectId: '{"injectedScriptId":3,"id":1}',
  preview:
   { type: 'object',
     subtype: 'arraybuffer',
     description: 'ArrayBuffer(40285)',
     overflow: false,
     properties: [] } }

Это дает мне некоторые хорошие описания arrabuffer liek, которые я мог бы увидеть в консоли (перед расширением объекта), но я предполагаю, что он запускает JSON.stringify для всей вещи, поэтому яя предполагаю, что данные массива буфера потеряны?

Есть ли какой-либо [другой] способ получить данные из page.evaluate во время выполнения страницы, а не только в конце разрешения?Как я могу получить объект arraybuffer, сгенерированный на странице?Должен ли я просто отправить его через другой XMLHTTPRequest или веб-сокет обратно на сервер?

1 Ответ

0 голосов
/ 30 марта 2019

Типизированный массив

Выдержка из этого ответа по rsp:

В формате JSON нет ArrayBuffers (только строки, числа, логические значения, значения null, объекты и массивы), поэтому, если вы хотите сохранить ArrayBuffer в JSON, вам придется представлять его в одном из этих типов (возможно, строка или массив чисел).

Затем, когда вы читаете JSON, вам придется преобразовать его обратно в ArrayBuffer, полностью изменив преобразование, которое вы делали ранее.

В кукловоде все сериализуется, поэтому контекст теряется. Вы не можете использовать одну и ту же ссылку в узле и браузере.

Итак, мы можем преобразовать типизированный массив в строку (или строку base64), а затем передать, что всякий раз, когда мы получаем значение, мы можем просто преобразовать его обратно.

Это преобразует вашу строку в Uint8Array, как вы можете видеть. Однако для преобразования в другие типы, к сожалению, вам придется кодировать это самостоятельно, поскольку только вы знаете структуру ответа.

const stringToArray = (str) => new Uint8Array([...str].map(char => char.charCodeAt(0)));

Таким образом, вы можете войти, как это,

await page.evaluate(() => {
    var typedArrayExample = new Uint8Array(2);
    typedArrayExample[0] = 15;
    typedArrayExample[1] = 20;
    // typedArrayExample should be Uint8Array(2) [15, 20]
    // typeof typedArrayExample === "object"
    // typedArrayExample.constructor === Uint8Array

    if (typedArrayExample.constructor === Uint8Array) {
      console.log(String.fromCharCode(...typedArrayExample))
    }
})

Событие page.on ('console'),

page.on("console", c => {
    console.log(c.args())
    const {
      value
    } = c._args[0]._remoteObject;
    // convert the string back
    console.log("Consoling", stringToArray(value));
});

Теперь выполнение этого приведет к,

Consoling Uint8Array [ 15, 20 ]

Websocket / Ajax-запрос

Вы можете создать сервер веб-сокетов, используя пакет ws,

const WebSocket = require("ws");

const wss = new WebSocket.Server({
  port: 8081
});

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: ', new Uint8Array(message));
  });
});

А затем отправьте двоичные данные со страницы в этот веб-сокет,

await page.evaluate(() => {
    const ws = new WebSocket('ws://localhost:8081');

    ws.onopen = function open() {
      const array = new Uint8Array(2);
      array[0] = 15;
      array[1] = 20;

      ws.send(array);
    }
})

Результат:

received:  Uint8Array [ 15, 20 ]

После этого обязательно закройте соединения. Вы также можете воспользоваться несколькими вкладками / страницами Chrome, чтобы избежать проблем, связанных с Cors. :)

Вы получите буфер, вы можете конвертировать его в

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...