我有以下代码尝试从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
});
尽管它没有给我实际的arraybuffer对象,但是(如果我只是这样做的话)就是这样:
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,所以我猜到了arraybuffer数据丢失了吗?
是否有任何其他方法可以从page.evaluate中获取页面数据,而不只是在解析结束时进行评估?如何获得在页面上生成的arraybuffer对象?我是否只需将其通过另一个XMLHTTPRequest或websocket发送回服务器?
答案 0 :(得分:0)
rsp摘录自this answer:
没有JSON格式的ArrayBuffer(只有字符串,数字,布尔值,null,对象和数组),因此,如果要以JSON保存ArrayBuffer,则必须以其中一种类型表示(可能字符串或数字数组。
然后,当您读取JSON时,必须将其转换回ArrayBuffer,并逆转之前所做的转换。
在puppeteer中,所有内容都被序列化,因此上下文丢失。您不能在节点和浏览器中共享相同的引用。
因此,我们可以将类型化的数组转换为字符串(或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 ]
您可以使用ws
软件包创建一个websocket服务器,
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));
});
});
然后将页面中的二进制数据发送到该websocket,
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相关的问题。 :)
您将收到一个缓冲区,可以将其转换为