使用带空格的属性选择器单击 Puppeteer 页面

发布于 2025-01-09 18:36:02 字数 1227 浏览 0 评论 0原文

此 Meteor 代码在服务器上使用 Puppeteer 13.1.2。它使用 for 循环使用其 title 属性打开 a 链接。只要该值不包含空格,它就可以工作,但无法打开包含空格的属性值的弹出页面。知道如何打开这些弹出窗口吗? 谢谢

const headings = ['One', 'Tow', 'Three/Four', 'Five Six', "Seven and more"]
for (let i = 0; i < headings.length; i++) {
  console.log('headings: ', headings[i])
  const [popup] = await Promise.all([
    new Promise((resolve) => page.once('popup', resolve)),
    page.click('a[title~="' + headings[i] + '"]'),
  ]);
}
<tr class="rowDark">
    <td width="10%" align="center">
        <input type="checkbox" name="selectedCheckboxes" value="Five Six" disabled="disabled" id="FiveSix" />
    </td>
    <td width="90%" class="smallText" align="left">
        <a href="/is/ASD.do?action=create&area=Five Six&iType=e" class="textLink" target="sons" title="Five Six (opens new window)" onclick="return displayReason(this.href);">
      Five Six
      </a>
    </td>

</tr>

使用上面的代码,我收到以下错误:错误:找不到选择器的节点:a[title〜=“五六”]

This Meteor code uses Puppeteer 13.1.2 on the server. It uses a for loops to open an a link using its title attribute. It works as long as the value has no spaces but it failes to open the popup page with the attribute values that contains spaces. Any idea how to open these popups?
Thanks

const headings = ['One', 'Tow', 'Three/Four', 'Five Six', "Seven and more"]
for (let i = 0; i < headings.length; i++) {
  console.log('headings: ', headings[i])
  const [popup] = await Promise.all([
    new Promise((resolve) => page.once('popup', resolve)),
    page.click('a[title~="' + headings[i] + '"]'),
  ]);
}
<tr class="rowDark">
    <td width="10%" align="center">
        <input type="checkbox" name="selectedCheckboxes" value="Five Six" disabled="disabled" id="FiveSix" />
    </td>
    <td width="90%" class="smallText" align="left">
        <a href="/is/ASD.do?action=create&area=Five Six&iType=e" class="textLink" target="sons" title="Five Six (opens new window)" onclick="return displayReason(this.href);">
      Five Six
      </a>
    </td>

</tr>

With above code I got following error: Error: No node found for selector: a[title~="Five Six"]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

庆幸我还是我 2025-01-16 18:36:02

您可以首先选择所有 .textLink 元素,然后按其标题值的文本过滤找到的元素。以下是两个用于按属性过滤元素的辅助函数:

// allows selecting a property from an elementhandle like title OR text or something,
async function getPropertyValue(element, property) {
  const textElement = await element.getProperty(property)
  const text = await textElement.jsonValue()
  return text.trim()
}

// filters an array of elementHandles against some property. 
// Ideal for filtering elements by its title value for example.
async function filterByPropertyValiue(elements, property, searchValue) {
  for(let element of elements) {

    // you can apply some transformations to value OR searchValue
    // in order to remove some stuff or make the matching appropriate to your
    // use case.
    const value = await getPropertyValue(element, property)
    if(value === searchValue) {
      // when found return element
      return element
    }
  }

  // if not found throw.
  throw 'Element not found by propertyValue. property: ' + property + ', value: ' + searchValue
}

在您的特定示例中,这现在应该可以工作:

const openPopup = async (page, titleText, timeoutMs) => {

  // return whole promise so timeout can be applied.
  const links = await page.$('a.textLink')

  // throws if target is not found.
  const target = await filterByPropertyValiue(links, 'title', titleText)

  const popup = new Promise((resolve, reject) => {
    page.once('popup', resolve)
    // it is nice to have a timeout on this.
    setTimeout(reject, timeoutMs)
  })

  // run the click not directly for letting the above
  // promise work first.
  process.nextTick(() => {
    page.click(target)
  })

  return popup
}

// ope the popups..
const headings = ['One', 'Tow', 'Three/Four', 'Five Six', "Seven and more"]
  // select links in advance..
  for (let i = 0; i < headings.length; i++) {
    console.log('headings: ', headings[i])
    const popup = await openPopup(page, headings[i], 15 * 1000)
  }

You could first select all .textLink elements and then filter the found elements by its title value's text. Here are 2 helper functions for filtering elements by its properties:

// allows selecting a property from an elementhandle like title OR text or something,
async function getPropertyValue(element, property) {
  const textElement = await element.getProperty(property)
  const text = await textElement.jsonValue()
  return text.trim()
}

// filters an array of elementHandles against some property. 
// Ideal for filtering elements by its title value for example.
async function filterByPropertyValiue(elements, property, searchValue) {
  for(let element of elements) {

    // you can apply some transformations to value OR searchValue
    // in order to remove some stuff or make the matching appropriate to your
    // use case.
    const value = await getPropertyValue(element, property)
    if(value === searchValue) {
      // when found return element
      return element
    }
  }

  // if not found throw.
  throw 'Element not found by propertyValue. property: ' + property + ', value: ' + searchValue
}

On your particular example this should now work:

const openPopup = async (page, titleText, timeoutMs) => {

  // return whole promise so timeout can be applied.
  const links = await page.$('a.textLink')

  // throws if target is not found.
  const target = await filterByPropertyValiue(links, 'title', titleText)

  const popup = new Promise((resolve, reject) => {
    page.once('popup', resolve)
    // it is nice to have a timeout on this.
    setTimeout(reject, timeoutMs)
  })

  // run the click not directly for letting the above
  // promise work first.
  process.nextTick(() => {
    page.click(target)
  })

  return popup
}

// ope the popups..
const headings = ['One', 'Tow', 'Three/Four', 'Five Six', "Seven and more"]
  // select links in advance..
  for (let i = 0; i < headings.length; i++) {
    console.log('headings: ', headings[i])
    const popup = await openPopup(page, headings[i], 15 * 1000)
  }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文