我在登录过程中选择按钮时遇到了 Puppeteer 的麻烦。我试图让它登录 Reddit,但登录按钮没有名称或 ID,并且可能会选择其他按钮。它还包含在其他元素中,所以我什至不确定该选择哪一个。我将在下面包含我的代码。有谁知道在输入用户名和密码后我可以做什么来按 Reddit.com 上的登录按钮?选择其他元素很容易,因为它们有 id。
const puppeteer = require ('puppeteer');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function loginToReddit(usernameText, passwordText){
const browser = await puppeteer.launch({
headless: false,
defaultViewport: false,
userDataDir: "./tmp"
});
const page = await browser.newPage();
await page.goto('https://www.reddit.com/');
await page.click('#login-button');
sleep(2000).then(() => {
enterCredentials(usernameText, passwordText, page);
});
}
async function enterCredentials(usernameText, passwordText, page){
await page.click('#login-username');
await page.keyboard.type(usernameText,{
delay: 50,
});
await page.click('#login-password');
await page.keyboard.type(passwordText,{
delay: 50,
});
sleep(2000).then(() => {
selectLoginButton(page);
});
}
async function selectLoginButton(page) {
page.waitForNavigation();
//const xp = 'faceplate-tracker button';
const xp = 'faceplate-tracker > button';
const el = await page.waitForSelector(xp);
await el.click();
}
loginToReddit('username', 'password');
在进一步使用 Puppeteer 之前,我建议先温习一下您的 Promise 基础知识。这里的代码在某些地方没有多大意义。 不要混淆
then
和await
,并确保await
所有承诺。没有 page.waitForNavigation();
的 await
没有任何作用。
还要避免过早的抽象——这些额外的函数只会让事情变得正确变得更加困难。一旦有了工作代码,就可以将其分解出来。
别睡觉。使用精确的谓词。
请注意,该页面有许多影子根,因此您需要阅读相关内容并熟悉
>>>
选择器。
这是自动化此操作的一种方法:
const puppeteer = require("puppeteer"); // ^23.6.0
const url = "<Your URL>;
let browser;
(async () => {
browser = await puppeteer.launch({headless: false});
const [page] = await browser.pages();
await page.goto(url, {waitUntil: "domcontentloaded"});
await page.locator("#login-button").click();
const un = await page.waitForSelector("#login-username");
await un.type("foo");
await page.type("#login-password", "baz");
for (let tries = 0; tries < 50; tries++) {
try {
await page.keyboard.press("Enter");
// just for this demo; use some other
// 'success' selector for the actual automation
await page.waitForSelector(
">>> ::-p-text(Invalid username or password)",
{timeout: 100}
);
break;
} catch {
//
}
}
await page.screenshot({path: "proof.png"});
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
通常情况下,这不会这么棘手,但是输入后立即按 Enter 不会提交表单,因此我选择轮询直到 Enter 按键注册 - 也许不是最好的解决方案,但对于初学者来说已经足够了。