我正在尝试使用这段代码从一个使用puppeteer的网站获取响应正文
#!/usr/bin/env node
require('dotenv').config();
const puppeteer = require('puppeteer');
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
const path = require('path');
const fs = require('fs');
//
console.log('Starting Puppeteer...');
let responseBody = [];
(async () => {
const browser = await puppeteer.launch({
headless: false,
executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
});
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', (request) => {
request.continue();
});
//
page.on('requestfinished', async (request) => {
const response = await request.response();
const url = response.url();
// store chunks url
if( url.startsWith('https://audio-akp-quic-control-examplecdn-com.akamaized.net/audio/') ){
console.log(await response.buffer());
//responseBody.push(response.buffer());
}
});
//
await page.goto('https://accounts.examplecdn.com/login', {
waitUntil: ['load', 'networkidle2']
});
const emailField = await page.waitForSelector('#login-username', {timeout: 3000});
await emailField.type(process.env.EMAIL, {delay: 100});
const passwordField = await page.waitForSelector('#login-password', {timeout: 3000});
await passwordField.type(process.env.PASSWORD, {delay: 100});
const submitButton = await page.waitForSelector('#login-button', {timeout: 3000});
await submitButton.click();
//
const navigation = await page.waitForNavigation({ waitUntil: ['load', 'networkidle2'] });
//if( navigation.url().endsWith('status') ){
await page.goto('https://example.cdn.com/search', {
waitUntil: ['load', 'networkidle2']
}).then( async (response) => {
//console.log(response);
const cookieButton = await page.$('#onetrust-accept-btn-handler');
await cookieButton.click();
const searchField = await page.$('[data-testid="search-input"]');
await readline.question('What track do you want to search for?', (input) => {
console.log('answer:', input);
searchField.type(input).then( async () => {
await page.waitForXPath('//*[@id="searchPage"]/div/div/section[1]/div[2]/div/div/div/div[4]').then( async (element) => {
element.focus().then( async () => {
// //*[@id="searchPage"]/div/div/section[1]/div[2]/div/div/div/div[3]/button
const playButton = await page.waitForXPath('//*[@id="searchPage"]/div/div/section[1]/div[2]/div/div/div/div[3]/button');
await playButton.click();
});
});
});
});
});
//}
})();
我有它的问题,这个错误将被记录,脚本将终止。
/Users/dev/Desktop/test/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:208
this._callbacks.set(id, { resolve, reject, error: new Error(), method });
^
Error: Protocol error (Network.getResponseBody): No resource with given identifier found
at /Users/dev/Desktop/test/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:208:63
at new Promise (<anonymous>)
at CDPSession.send (/Users/dev/Desktop/test/node_modules/puppeteer/lib/cjs/puppeteer/common/Connection.js:207:16)
at /Users/dev/Desktop/test/node_modules/puppeteer/lib/cjs/puppeteer/common/HTTPResponse.js:99:53
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:93:5)
at async /Users/dev/Desktop/test/index.js:40:25
我需要做的是收集所有的响应体的内容时,某个网址被调用,然后使用ffmpeg我想把它转换回一个完整的长度轨道.我怎么能解决这个问题,是可能的,得到每个请求的响应体,然后加入所有togheter?
1条答案
按热度按时间m0rkklqb1#
这里有很多问题和反模式。有几个
.then
回调从来没有返回任何东西。例如:应该是
以下模式不正确:
异步函数通常要么返回一个promise要么接受一个callback,而不是两者都接受。
await
欺骗你,让你以为你在promise链中保留了这一点,而实际上你在等待undefined
。实际的“promise”是回调。几乎总是never mix
await
andthen
。promise的目的是扁平化代码,以便您可以以同步风格编写它。如果您发现您有许多嵌套回调或.then(async () => ...
层,则应该发出红旗,并且您未能处理错误或放弃promise链的可能性增加。如果需要承诺回调,您可以:
现在你可以在你的代码中“同步”使用它,就像:
还有Node的
utils.promisify
,它在机械上或多或少地执行相同的操作。没有用户名和密码我无法运行你的代码,但是如果你删除所有的
then
(是的,最后一个!),await
在一个单一的承诺链中的所有内容,并承诺任何基于回调的异步函数,你应该能够避免这个错误。我还建议避免使用浏览器生成的那些冗长、死板的XPath,它们对结构做了太多的假设,很容易出错,而且几乎总是有更健壮的选择器或路径可以使用。
退一步说,我建议你慢慢地写代码,每一步都运行代码,这样你就可以验证每一个假设。这样做,你就可以最小化问题并立即解决它们,避免出现混乱、复杂的情况,因为有多个问题很难一次性调试。