【问题标题】:Puppeteer - testing different selectors for pagePuppeteer - 测试页面的不同选择器
【发布时间】:2020-04-21 12:59:35
【问题描述】:

我正在尝试让我的 puppeteer 脚本遍历选择器。

原因是 - 根据我通过脚本查询的内容,我可以在页面上获得稍微不同的元素。

基本上我有一个 page.evaluate 方法可以像这样进行抓取

    while (currentPage <= pagesToScrape) {

        let newProducts = await page.evaluate(({identified}) => {
          let results = [];

          let items = document.querySelectorAll(
            identified
          );
console.log(items)


          items.forEach((item) => {
            var prod, price;
            if (identified == selectors[0]) {
              prod = item.querySelector("div>div>div>div>div>a>h3").innerText;
              price = item.querySelector("div>div>div>div>div>div>span>span")
                .innerText;
            } else {
              prod = item.querySelector("div>a>h4").innerText;
              price = item.querySelector("div>div>div>div>span>span").innerText;
            }
            results.push({
              Product: prod !== "" ? prod : "",
              Price: price !== "" ? price : "",
            });
          });
          console.log("results");
          console.log(results.length);
          return results;
        });
        product_GSH = product_GSH.concat(newProducts);
        if (currentPage < pagesToScrape) {
          console.log(identified)
          await Promise.all([
            await page.click(buttonSelector),
            await page.waitForSelector(identified),
          ]);
        }

现在在脚本开始之前,我需要确保我有正确的选择器。

const selectors = ['div[class = "sh-dlr__list-result"',"div[class = 'sh-dgr__content'"]
  //works
  const chooseSelector = await page.waitForFunction((selectors) => {
    for (const selector of selectors) {
      if (document.querySelector(selector) !== null) {
        return selector;
      }
    }
    return false;
  }, {}, selectors);

  const identified = await chooseSelector.jsonValue();

console.log(已识别)

我遇到的问题是,在 page.evaluate 中,我可以轻松运行标识符并找到要使用的正确标识符。但是我需要在查询结束时再次对其进行解析以抓取下一页。当我尝试将变量名称重新分配给 page.evaluate 中的正确标识符时,它不会解析它。

当我运行它时,代码会运行,但我无法使用 page.waitfor 更改底部承诺中的选择器(因此它适用于某些页面,但当它是错误页面时,我无法替换选择的选择器)。这是完整的代码仅供参考。

        product_GSH = product_GSH.concat(newProducts);
        if (currentPage < pagesToScrape) {
          await Promise.all([
            await page.click(buttonSelector),

            page.waitForNavigation()
          ]);
        }
        currentPage++;
      }
      browser.close();

      return res.send(product_GSH);
    } catch (e) {
      return res.send(e);
    }
  });
});

我正在考虑解决此问题的一种方法是查看 promise.all 函数并将其替换为稍有不同的东西。

感谢您帮助解决此问题!

如果您可以提供帮助,最后一个问题 - 我如何确保当我选择说 5 页并且只有 3 页结果时,它会发送 3 页。我发现如果我说还有更多页面,它不会发送任何响应。

理想情况下,我试图让这段代码能够遍历不同的选择器。我尝试了很多不同的方法,除了 CORS 错误等等,非常迷茫。最好能从 puppeteer 那里得到某种明确的错误!

感谢帮助:)

【问题讨论】:

    标签: javascript puppeteer


    【解决方案1】:

    您必须使用 page.waitForNavigationpage.click(buttonSelector) 承诺。此外,要使用Promise.all,您必须像您正在做的那样传递实际的承诺和未解决的承诺

    if (currentPage < pagesToScrape) {
      await Promise.all([
        page.click(buttonSelector),
        page.waitForNavigation()
      ]);
    }
    

    你可以简化选择器,例如

    div[class = "sh-dlr__list-result"
    

    可以

    div.sh-dlr__list-result
    

    选择器

    const buttonSelector = "a[id='pnnext']>span[style='display:block;margin-left:53px']";
    

    错了;你永远不应该依赖样式来查询选择器;可以很容易地动态改变;相反,您可以这样定义它

    const buttonSelector = "a#pnnext";
    

    进行这些更改后,我们将获得正确的结果,例如它将输出:

    product_GSH.length 100
    product_GSH [...]
    

    更新

    如果你想处理少于pagesToScrape 页面的结果,那么你必须在点击它之前寻找buttonSelector

    if (currentPage < pagesToScrape && await page.$(buttonSelector) !== null) {
      await Promise.all([
        page.click(buttonSelector),
        page.waitForNavigation()
      ]);
    }
    

    【讨论】:

    • @christosLystras 非常感谢,waitfornav 工作得很好>
    • 点击前必须检查buttonSelector是否存在;如果它不存在,这意味着我们在最后一页,我们没有点击它。我已经更新了我的答案,请查看。
    • 很高兴你让它工作了;不知道为什么你投了反对票,赞成票。
    • 如果可能的话 - 如果你能删除完整的 Puppeteer 脚本部分,那就太好了。可能是偏执狂,但不是全部在线
    • 我刚刚删除了 puppeteer 脚本。如果您觉得可以,请检查答案。如果您认为其中包含您不想出现的信息,您也可以对其进行编辑。
    【解决方案2】:

    Promise.all 看起来像是解决这个问题的地方。虽然我不是最擅长承诺功能的人

    【讨论】:

    • 谢谢。我认为您可能是对的,但是由于某种原因,当我在 promise 函数周围使用不同的 if 语句时,它不会解析正确的标识符。
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2019-06-23
    • 2019-04-17
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多