【问题标题】:Puppeteer: Escape square brackets in selectorPuppeteer:在选择器中转义方括号
【发布时间】:2018-09-10 05:27:03
【问题描述】:

我需要选择 id 包含方括号的元素。

#element[0]

但是,我不断得到:

错误:找不到匹配选择器“element[0]”的元素

我已经使用\ 转义了选择器中的元素,但这不起作用。

page.select("#fruit\[0\]", "apples")

双反斜杠转义也不起作用。即:

page.select("#fruit\\[0\\]", "apples")

更新:我要选择的元素:

<select id="fruit[0]">
  <option>Please make a selection</option>
  <option>apples</option>
</select>

注意:即使我尝试在上面的查询中使用 page.waitFor 方法,也会遇到同样的错误。

【问题讨论】:

    标签: javascript google-chrome-devtools google-cloud-functions puppeteer


    【解决方案1】:

    使用[id="fruit[0]"]:

    您可以使用 CSS attribute selector 引用元素的 id 属性:

    await page.waitFor( '[id="fruit[0]"]' );
    
    await page.select( '[id="fruit[0]"]', 'apples' );
    

    【讨论】:

      【解决方案2】:

      使用编码数据转义

      如果您甚至尝试在浏览器上执行document.querySelector('#fruit[0]'),您将得到同样的错误。转义不起作用,因为当 puppeteer 读取它时,它已经被解析并且没有相同的转义值。逃避它们的方法很少。

      假设我们有一个这样的元素,

      <a href="/" id="sample[112]">Bar</a>
      

      现在如果你想用vanila JS,你可以试试下面的,

      内容如下:

      < document.querySelector(CSS.escape('#sample[112]'))
      > null
      
      < document.querySelector('#sample[112]')
      > Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sample[112]' is not a valid selector.
      
      < document.querySelector('#sample\5b 112\5d')
      > ncaught DOMException: Failed to execute 'querySelector' on 'Document': '#sampleb 112d' is not a valid selector.
      
      < document.querySelector('#sample\\5b 112\\5d')
      > <a href="/" id="sample[112]">Bar</a>
      

      正如你在上面看到的,左括号是5b,右括号是5d,我们甚至不得不转义它并必须放置空格以便浏览器可以解析它。

      您应该尝试上述代码并找出适合您网站的代码。

      真实案例脚本

      让我们面对现实吧,您的目标网站没有这些选项的价值。最好的办法是文字选择,无耻地抄袭this answer

      另外,我可以对其进行两次转义并在不编码的情况下获取数据。毕竟,nodeJS 与浏览器控制台不同,在脚本上一切都会有所不同。

      用于 HTML 的源代码,

      <select id="sample[1]"><option>mango</option><option>apple</option></select>
      

      以及用于测试的 puppeteer 代码,

      const puppeteer = require("puppeteer");
      
      function setSelectByText(selector, text) {
        // Loop through sequentially//
        const ele = document.querySelector(selector);
        console.log(ele);
      
        for (let ii = 0; ii < ele.length; ii++) {
          if (ele.options[ii].text == text) {
            // Found!
            ele.options[ii].selected = true;
            return true;
          }
        }
        return false;
      }
      
      puppeteer.launch().then(async browser => {
        console.log("Opening browser");
        const page = await browser.newPage();
      
        console.log("Going to site");
        await page.goto("http://0.0.0.0:8080"); // temporary website created for testing
      
        await page.evaluate(setSelectByText, "#sample\\[1\\]", "apple"); // we can use this over and over, without creating a separate function, just passing them as arguments
      
        await page.screenshot({ path: "test.png" });
      
        await browser.close();
      });
      

      【讨论】:

      • 我刚试过这个。没有运气:(。我得到完全相同的错误:(节点:4995)UnhandledPromiseRejectionWarning:错误:评估失败:DOMException:无法在“文档”上执行“querySelector”:“#fruit [0]”不是有效的选择器。在 puppeteer_evaluation_script:1:33
      • 啊等一下,我想起了这个问题,让我尽快回复一个可靠的答复。
      • @kashiB 现在我添加了更多答案。 :) 和平。
      • 关于反引号的部分具有误导性:"#fruit[0]" 与反引号版本一样有效,如果您担心奇怪和不常见的选择器,后者会在您尝试匹配 input[value="${foo}"] 时中断.关于文本匹配,鉴于我们正在谈论 Puppeteer,use $x with a contains clause 比滚动您自己的功能更有效和可靠。
      【解决方案3】:

      您可能错误地引用了 ID。

      如果您在创建 HTML 元素(即fruit[0]fruit[1])时以编程方式生成 ID,那么存储的是 值而不是引用。

      示例:我有一个数组fruit = [apple, banana],我创建了一个元素... <button id=fruit[0]>Click me</button> 如果我想选择那个按钮,那么我需要page.select('#apple')而不是 page.select('#fruit[0]')

      【讨论】:

      • 没关系。我看到您在示例中使用了引号,因此它应该完全按照您的设置方式存储字符串。
      • 也许吧。但是为什么这也失败了:await page.waitFor('#answerlist[0]')
      • 请注意,这取决于您创建元素的方式。如果我说document.body.innerHTML = "&lt;button id=fruit[0]&gt;Click me&lt;/button&gt;",ID 将是文字字符串fruit[0],而不是fruit 数组的第一个元素,正确的选择器将是#fruit\[0\]
      猜你喜欢
      • 2012-01-14
      • 2011-08-10
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      相关资源
      最近更新 更多