【问题标题】:Puppeteer issue: Same button cannot be pressed twice after page content changes (but button id did not)Puppeteer 问题:页面内容更改后,无法按两次相同的按钮(但按钮 ID 没有)
【发布时间】:2021-08-01 09:27:01
【问题描述】:

我正在尝试使用最新的 nodeJS 和 puppeteer 自动执行结帐过程。一切正常,除了最后一次按下按钮,据我了解,这应该可以正常工作,但无论如何都没有发生任何事情。

这是我的代码:

            else if (statusCode == 200) {
            let data = await page.evaluate(() => document.body.innerHTML);
            // Accepting cookies
            const cookieButton = 'button[id="privacy-layer-accept-all-button"]';
            await page.waitForSelector(cookieButton);
            await page.click(cookieButton);
            // Confirm cart data
            bench = new Date().getTime();
            let checkoutButton = 'div[data-test="checkout-continue-desktop-enabled"]';
            await page.waitForSelector(checkoutButton);
            await page.click(checkoutButton);
            await page.waitForNavigation({waitUntil:'networkidle0'})
            // Confirming checkout
            data = await page.evaluate(() => document.body.innerHTML);
            checkoutButton = 'div[data-test="checkout-continue-desktop-enabled"]';
            await page.waitForSelector(checkoutButton);
            await page.click(checkoutButton);

第一个按钮的代码(确认购物车数据) - 正在被点击(有效):

<div><div class="BasketResumeHeader__BasketResumeHeaderWrapper-k9sckg-0 dWBNeC"><h3 color="black" font-family="default" spacing="base" font-size="lg" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN">Zusammenfassung</h3><span font-size="xxs" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 ejSGsu">Gutscheine können im Zahlungsschritt hinzugefügt werden</span></div><div class="ResumeTable__StyledTableValues-sc-109drs2-0 hUoXfQ"><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 dHuLzW"></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div>Zwischensumme</div><span>101,99&nbsp;€</span></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 eYsMjW">Lieferkosten<div color="#918e8c" height="20" width="20" class="Icon-sc-1vrq823-0 cScGKb InfoIcon__StyledInfoIcon-sc-1vh1773-0 clmMtr"><svg width="32" height="32" viewBox="0 0 24 24"><path d="M12 2a10 10 0 1010 10A10 10 0 0012 2zm0 18a8 8 0 118-8 8 8 0 01-8 8zm1-7.5a.5.5 0 00-.5-.5h-1a.5.5 0 00-.5.5v3a.5.5 0 00.5.5h1a.5.5 0 00.5-.5zm0-4a.5.5 0 00-.5-.5h-1a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5z"></path></svg></div></div><div>Gratis</div></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div><h3 color="black" font-family="default" spacing="base" font-size="lg" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN">Gesamtsumme</h3><div class="mms-checkout-basket-summary__vat"><span color="grey2" font-size="xxs" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 blKxsn">inkl. MwSt.</span></div></div><h3 color="black" font-family="default" spacing="base" font-size="lg" data-test="checkout-total" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN"><span>101,99&nbsp;€</span></h3></div><div class="BasketResume__StyledSummaryButtons-sc-1pu65vy-0 fFBBbE"><div data-test="checkout-continue-desktop-enabled" class="ContinueButton__StyledContinue-sc-17lzxkg-0"><button type="button" class="Buttonstyled__StyledButton-sc-140xkaw-1 jjXwnX">Zur Kasse gehen</button></div><a class="Linkstyled__StyledLinkAnchor-sc-1drhx1h-0 cSeNct BasketResume__StyledLink-sc-1pu65vy-1 duDsob" target="_self" href="/" color="black"><span color="black" font-size="sm" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 iMnkvI Linkstyled__Text-sc-1drhx1h-4 Uqzhg">Weiter einkaufen</span></a></div></div>

确认结帐页面的第二个按钮的代码(整个 URL 在此过程中从 /checkout 更改为 checkout/summary) - 不起作用,也没有被点击:

<div><div class="BasketResumeHeader__BasketResumeHeaderWrapper-k9sckg-0 dWBNeC"><h3 color="black" font-family="default" spacing="base" font-size="lg" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN">Zusammenfassung</h3><a class="Linkstyled__StyledLinkRouter-sc-1drhx1h-2 kgubGI BasketResumeHeader__StyledLink-k9sckg-1 dEwdDh" data-test="mms-router-link" href="/checkout/payment#discounts"><span class="Linkstyled__StyledIconWrapper-sc-1drhx1h-3 ctFeV"><div color="primary" class="Icon-sc-1vrq823-0 cRMyVe"><svg width="32" height="32" viewBox="0 0 24 24"><path d="M15.78 11.28a.75.75 0 01.22.53v.38a.77.77 0 01-.22.53l-5.14 5.13a.5.5 0 01-.71 0l-.71-.71a.49.49 0 010-.7L13.67 12 9.22 7.56a.5.5 0 010-.71l.71-.7a.5.5 0 01.71 0z"></path></svg></div></span><span color="grey5" font-size="xxs" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 jjFdpe Linkstyled__Text-sc-1drhx1h-4 Uqzhg">Haben Sie einen Gutscheincode oder eine Geschenkkarte?</span></a></div><div class="ResumeTable__StyledTableValues-sc-109drs2-0 hUoXfQ"><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 dHuLzW"></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div>Zwischensumme</div><span>101,99&nbsp;€</span></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 eYsMjW">Lieferkosten<div color="#918e8c" height="20" width="20" class="Icon-sc-1vrq823-0 cScGKb InfoIcon__StyledInfoIcon-sc-1vh1773-0 clmMtr"><svg width="32" height="32" viewBox="0 0 24 24"><path d="M12 2a10 10 0 1010 10A10 10 0 0012 2zm0 18a8 8 0 118-8 8 8 0 01-8 1zm1-7.5a.5.5 0 00-.5-.5h-1a.5.5 0 00-.5.5v3a.5.5 0 00.5.5h1a.5.5 0 00.5-.5zm0-4a.5.5 0 00-.5-.5h-1a.5.5 0 00-.5.5v1a.5.5 0 00.5.5h1a.5.5 0 00.5-.5z"></path></svg></div></div><div>Gratis</div></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div><div direction="horizontal" class="Spacer__StyledSpacer-sc-1wx27iz-0 cfFOme"></div></div><div display="flex" class="FlexBox__StyledBox-sc-1vld6r2-0 emVcHd"><div><h3 color="black" font-family="default" spacing="base" font-size="lg" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN">Gesamtsumme</h3><div class="mms-checkout-basket-summary__vat"><span color="grey2" font-size="xxs" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 blKxsn">inkl. MwSt.</span></div></div><h3 color="black" font-family="default" spacing="base" font-size="lg" data-test="checkout-total" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 eUyjYN"><span>101,99&nbsp;€</span></h3></div><div class="BasketResume__StyledSummaryButtons-sc-1pu65vy-0 fFBBbE"><div data-test="checkout-continue-desktop-enabled" class="ContinueButton__StyledContinue-sc-17lzxkg-0"><button type="button" class="Buttonstyled__StyledButton-sc-140xkaw-1 jjXwnX">Fortfahren und bezahlen</button><p font-size="xxs" class="Typostyled__StyledInfoTypo-sc-1jga2g7-0 iEQpGm ContinueButton__StyledDescription-sc-17lzxkg-1 dGihln">Mit Klick auf "Fortfahren und bezahlen" stimme ich den <a class="Linkstyled__StyledLinkAnchor-sc-1drhx1h-0 RsClv Summarystyled__StyledLink-sc-1euxzmh-10 fYjVAT" target="_blank" rel="noopener noreferrer" href="https://www.mediamarkt.de/de/legal/terms">AGB</a> zu. Ich habe die <a class="Linkstyled__StyledLinkAnchor-sc-1drhx1h-0 RsClv TransLink__StyledLink-sc-1f101w2-0 gwpXWL" target="_blank" rel="noopener noreferrer" href="https://www.mediamarkt.de/de/legal/terms#terms.withdrawal">Widerrufsbelehrung</a> und die <a class="Linkstyled__StyledLinkAnchor-sc-1drhx1h-0 RsClv TransLink__StyledLink-sc-1f101w2-0 gwpXWL" target="_blank" rel="noopener noreferrer" href="https://www.mediamarkt.de/de/shop/datenschutzhinweis_shop.html">Datenschutzerklärung</a> zur Kenntnis genommen.</p></div></div></div>

遗憾的是,除了那些代码 sn-ps 之外,我无法为您提供更好的示例/超链接,因为如果网站上没有工作 cookie,网站将无法加载。

如您所见,选择器应该选择按钮(因为它在两个页面上具有完全相同的名称),但是在成功按下第一个按钮后页面发生更改后,它会以某种方式难以按下按钮。我尝试添加await page.waitForNavigation();{ waitUntil: 'networkidle0'}await page.waitForTimeout(1000);,因为我认为数据可能尚未加载,但它并没有真正帮助,我似乎不明白为什么它不起作用。

我得到的错误信息是:

(node:16524) UnhandledPromiseRejectionWarning: Error: Node is either not visible or not an HTMLElement

如果您能帮我解决这个问题,或者至少指出我正确的方向如何进一步调试和解决这个问题,我们将不胜感激。

【问题讨论】:

    标签: javascript forms button puppeteer clicking


    【解决方案1】:

    我有一些建议。添加这个以确保您的查看窗口大小合适:

    await page.setViewport({width: 1024, height: 1600});
    

    您可以尝试使用evaluate 直接在网络浏览器上下文中单击该按钮:

    await page.evaluate(selector=>{
      document.querySelector(selector).click();
    },checkoutButton);
    

    您可能需要滚动到元素:

    await page.evaluate(selector=>{
      elem = document.querySelector(selector);
      elem.scrollIntoView({ block: "center", inline: "center" });
      elem.click();
    },checkoutButton);
    

    作为调试/测试工具,截图看看加载后的页面是否如你所愿:

    await page.screenshot({path: 'test.png'});
    

    【讨论】:

    • 非常感谢您的回复!我已经在使用await page.setViewport({ width: 1920, height: 1080 })headless: false, defaultViewport: null, args: ['--start-maximized']。所以我看到页面加载正确,按钮在那里(并且可以很容易地手动单击),当我使用cheerio 获取其文本时它也可以工作(当我执行console.log($('button[id="privacy-layer-accept-all-button"]').text); 时将“Fortfahren und bezahlen”打印到控制台)。 ..但不知何故,我无法通过 Puppeteer 选择或单击它。相关:github.com/puppeteer/puppeteer/issues/1771
    【解决方案2】:

    从 puppeteer 文档中,他们建议您将 click 和 waitForNavigation 承诺合并为一个承诺,然后等待它们都解决,这是因为如果您分别执行它们中的每一个,它可能会卡住,因为 waitForNavigation 可能在点击被解决之前完成,因此,改变这个:

    await page.click(checkoutButton);
    await page.waitForNavigation({waitUntil:'networkidle0'})
                
    

    到这里:

    await Promise.all([
    page.click(checkoutButton),
    page.waitForNavigation({waitUntil:'networkidle0'})
    ])
            
    

    【讨论】:

    • 感谢您的回复,但它不起作用,页面卡住不是这里的问题。问题似乎是它在第一次触发按钮后根本找不到按钮,即使我使用await page.waitForTimeout(10000); 并手动观看页面完成加载(并且可以通过开发工具检查按钮)。这与我的问题几乎 100% 相同,但遗憾的是这种方法对我也不起作用:(github.com/puppeteer/puppeteer/issues/1771
    • @l4m0r 有什么东西遮住了按钮吗? puppeteer 上的 click 方法与内置的 click 方法不同。 puppeteer 单击会触发鼠标单击,因此如果该按钮在页面上不可见或在其顶部有另一个元素,它将不起作用。除此之外,如果没有看到您正在抓取的网站,我想不出任何可能导致此问题的东西。
    • 再次感谢您的回复。不,没有什么可以掩盖按钮。另外,我不单击带有cheerio 的按钮(这甚至可以吗?),我只是打印其文本以查看cheerio 是否可以找到它(或上一个具有不同文本的按钮)...因此cheerio 可以访问更新的按钮,但是傀儡师不能。该网站是:mediamarkt.de/checkout(第一个按钮)和mediamarkt.de/checkout/summary(第二个按钮)。不过,对于第二个 url/按钮,您将需要一个帐户
    猜你喜欢
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多