人偶操纵者在选择 <td> 后单击它

Puppeteer clicking a <td> after selecting it

我测试了我的 xpath select 或 chrome 开发工具,它找到了我正在尝试 select.

<td>

我尝试了一些方法,使用 page.x$,然后确保元素 select 使用以下内容正确编辑:

page.waitForXPath("//td[contains(., 'All Projects')]")
.then(selector => {
    page.click(selector);
})

执行确实达到了 page.click(),我得到以下错误。我很困惑,因为我不认为我在改变环境。 UnhandledPromiseRejectionWarning: Error: JSHandles can be evaluated only in the context they were created!

编辑:这里是 HTML 代码。这是一个由 HTML table 组成的 Angular 网格。 <td> 在底部。

这是其余的代码。其他一切工作正常。对不起,如果这很笨重。

const puppeteer = require('puppeteer');
const kindle = puppeteer.devices['Kindle Fire HDX landscape'];

async function main() {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();

    //go to page and log in
    await page.emulate(kindle);
    await page.goto('http://localhost:4201/#/login');
    await page.waitForSelector('input[id="usr"]');
    await page.type('#usr', 'myusername');
    await page.type('#pwd', '');
    await page.click('button');

    //wait for homepage to load
    await page.waitForSelector('#menuData');
    await page.click('#menuData');
    await page.waitForSelector('#drCreate');
    await page.click('#drCreate');
    await page.waitForSelector('.mat-input-element'); //a request piece is loaded
    //populate fields

    var date = new Date();

    await page.type('#mat-input-0', humanReadableDate(date));
    date.setDate(date.getDate() + 1);
    await page.type('#mat-input-1', humanReadableDate(date));
    date.setDate(date.getDate() + 5)
    await page.type('#mat-input-3', humanReadableDate(date));

    await page.click('.pi-angle-double-right');

    page.waitForXPath("//td[contains(., 'All Projects')]")
    .then(selector => {
        page.click(selector);
    })
}

function humanReadableDate(date) {
    if (!date) {
        date = new Date();
    }
    return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
}

main();

它看起来像一个无效的页面上下文。尝试这样的事情:

await page.waitForXPath("//td[contains(., 'All Projects')]")
const [ projects ] = await page.$x("//td[contains(., 'All Projects')]");
projects.click()

或简称:

page.waitForXPath("//td[contains(., 'All Projects')]").then(selector => selector.click())

问题

page.click 需要一个字符串(选择器)作为参数,但您传递的是元素句柄。

引用来自 page.waitForXPath 的文档:

returns: <Promise<?ElementHandle>> Promise which resolves when element specified by xpath string is added to DOM. Resolves to null if waiting for hidden: true and xpath is not found in DOM.

这意味着您不能将该函数的结果(元素句柄)提供给 page.click

解决方案

相反,您可以使用 elementHandle.click:

编写这样的代码
await page.waitForXPath("//td[contains(., 'All Projects')]")
.then(elementHandle => elementHandle.click())

但我建议使用 async/await 语法来更符合您的代码的其余部分:

const elementHandle = await page.waitForXPath("//td[contains(., 'All Projects')]");
await elementHandle.click();