gpt4 book ai didi

javascript - 如何在 puppeteer 中确定性地使用 CSS 选择器?

转载 作者:行者123 更新时间:2023-12-04 14:54:14 26 4
gpt4 key购买 nike

我正在尝试自定义一个在 soundcloud 上播放歌曲并录制它的 puppeteer 脚本。使用 CSS 选择器,我也想打印歌曲持续时间。
我似乎无法让 CSS 选择器工作。我正在使用的网址是 https://soundcloud.com/octasine/octasine-audio-example-1
我现在有一个可用的 CSS 选择器,可以从页面中获取分钟和秒。我看到的挑战是有时页面还没有完成渲染,我使用 await page.waitForNavigation(); 得到一个空数组返回。导致 promise 失败。
我缺少什么才能让 puppeteer 更可靠地工作?
这就是我使用 CSS 选择器的方式:

    const work = async () => {
const inputsValues = [];
const inputElements = await page.$$('span.sc-visuallyhidden');

for (const element of inputElements) {
let inputValue;

inputValue = await element.getProperty('innerText');
inputValue = await inputValue.jsonValue();
if (inputValue.includes('Duration')){
console.log("DURATION");
mins = inputValue.split(" ")[1];
secs = inputValue.split(" ")[3];
console.log(mins);
console.log(secs);
console.log(inputValue);
}

inputsValues.push(inputValue);

}

console.log(inputsValues)
}
await work();
我的完整脚本 example.js :
// example.js -- node version v14.17.2 -- dependency installed with npm i puppeteer-stream 
const { launch, getStream } = require("puppeteer-stream");
const fs = require("fs");
const { Console } = require("console");

const file = fs.createWriteStream(__dirname + "/test.webm");

async function test() {
const browser = await launch();

const page = await browser.newPage();
await page.goto("https://soundcloud.com/octasine/octasine-audio-example-1");

// await page.waitForNavigation();

let html_var = await page.content();
// Write the file
fs.writeFile("example.html", html_var, function (err) {

// Checks if there is an error
if (err) return console.log(err);
});
console.log("Wrote html to example.html");


// await page.click("//a[contains(text(), 'Play')]");
await page.evaluate(() => {
let elements = document.getElementsByClassName('snippetUXPlayButton');
for (let element of elements)
element.click();
});

const work = async () => {
const inputsValues = [];
const inputElements = await page.$$('span.sc-visuallyhidden');

for (const element of inputElements) {
let inputValue;

inputValue = await element.getProperty('innerText');
inputValue = await inputValue.jsonValue();
if (inputValue.includes('Duration')){
console.log("DURATION");
mins = inputValue.split(" ")[1];
secs = inputValue.split(" ")[3];
console.log(mins);
console.log(secs);
console.log(inputValue);
}

inputsValues.push(inputValue);

}

console.log(inputsValues)
}
await work();


let page_url = await page.url();
console.log(page_url)



await page.evaluate(() => {
let elements = document.getElementsByClassName('sc-visuallyhidden');
for (let element of elements)
console.log(element.innerHTML);
});

const stream = await getStream(page, { audio: true, video: true });
console.log("recording");

stream.pipe(file);
setTimeout(async () => {
await stream.destroy();
file.close();
console.log("finished");
browser.close();
}, 1000 * 5 + mins * 60000 + secs * 1000);

}

test();

基于来自 https://www.npmjs.com/package/puppeteer-stream 的示例脚本的脚本

最佳答案

带有 span.sc-visuallyhidden 的元素选择器是一一动态填充到DOM中的,因此长度为$$('span.sc-visuallyhidden')随着页面加载而增长。在您填写 inputElements 的那一刻数组它可能还不包含 Duration。
为了 100% 确保它在您的元素集中可用,您需要等到它被渲染到 DOM 中。例如。通过捕获它的确切选择器:

await page.waitForSelector('.playbackTimeline__duration > span.sc-visuallyhidden')
我建议重构你的 work()用作 page.$$eval 像这样的方法:
const inputsValues = await page.$$eval('span.sc-visuallyhidden', elems => elems.map(el => el.innerText))
输出是:
8 months ago, 2,452 plays, View all likes, View all reposts, 10 followers, 2 tracks, 414 plays, View all likes, View all comments, Current time: 0 seconds, Duration: 2 minutes 26 seconds, Current track: Octasine Audio Example 1
...包含: Duration: 2 minutes 26 seconds您可以像以前一样处理到分钟和秒。

关于javascript - 如何在 puppeteer 中确定性地使用 CSS 选择器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68443623/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com