Puppeteer - 在同一弹出 Div 中使用 CSS 选择器选择多个元素

问题描述 投票:0回答:1

我正在尝试在酒店网站(

https://www.marriott.com/default.mi
)上选择例如2 Rooms and 3 Adults,但是无论我编写哪个CSS选择器,我的功能要么:

  • 我的第一个添加房间代码部分有效,然后第二个添加成人代码部分也添加到房间号(导致 5 个房间和默认 1 个成人)

  • 我的第一个“添加房间”代码部分有效,然后第二个“添加成人”代码部分返回

    TypeError: Cannot read properties of undefined (reading 'click')
    (导致 2 个房间,然后程序返回错误)。

例如输入“美国伊利诺伊州芝加哥”并选择 8 月 7 日至 8 月 10 日作为日期。

这是我的异步函数代码:

// Helper fx: Fill in number of rooms and number of guests (Room, Adult constants)
async function fill_room_and_guest(page, constants) {
  // Click drop-down menu for Room, Guest 
  await page.click('.search__rates.t-font-s[type="button"]');
  await page.waitForSelector('[class^="StyledPopupDiv"]');
  
  // Add Rooms - this adds the first element (Rooms)
  const add_rooms_icon = await page.$$('[class^="StyledPopupDiv"] .icon-plus:nth-of-type(1)');
  for (let i = 1; i < constants.NUM_ROOMS; i++) {
    // Press the "+" button in Rooms
    await add_rooms_icon[0].click();
  }

  //! Add Adults - NOT WORKING 
  // TypeError: Cannot read properties of undefined (reading 'click')
  const add_adults_icon = await page.$$('[class^="StyledRowDiv"]:nth-of-type(2) > [class^="StyledIncrementDiv"] > .icon-plus');
  // const add_adults_icon = await page.$$('[class^="StyledPopupDiv"] .icon-plus:nth-of-type(2)');
  
  // Test:
  console.log(add_adults_icon); // sometimes returns empty array
  console.log(typeof add_adults_icon);

  for (let j = 1; j < constants.NUM_ADULTS; j++) {
    // Press the "+" button in Adults
    await add_adults_icon[0].click();
  }
}

截图:

css node.js css-selectors puppeteer
1个回答
0
投票

将我的评论转化为答案,选择器

'[class^="StyledRowDiv"]:nth-of-type(2) > [class^="StyledIncrementDiv"] > .icon-plus'

太死板了。在

<button>
StyledIncrementDiv
之间有一个
.icon-plus
,但是
>
只看直接孩子的内部。删除它以搜索整个子树。

一般情况下,避免

>
除非有必要消除歧义,例如:

<div class="wrapper">
  <div>
    <span>I want this element</span>
    <span>I want this element</span>
    <div>
      <span>But not this element</span>
      <span>But not this element</span>
    </div>
  </div>
</div>

这是一个奇怪的边缘情况,其中

.wrapper > div > span
可用于避免
.wrapper span
匹配的嵌套元素。但这并没有显示太多。 98% 的时间,避免
>
.


另外,

page.$$()
选择多个元素,所以如果你只想要第一个,更喜欢
page.$()
。如果该元素未始终显示,请改用
const el = await page.waitForSelector(...)
。如果这失败了,请检查选择器或检查页面的动态行为以找出使其出现的实际条件。

© www.soinside.com 2019 - 2024. All rights reserved.