Puppeteer - 单击具有指定文本的跨度

Puppeteer - click on span with specified text

我目前正在使用 puppeteer 抓取网页。我正在尝试做一些可以加快我工作速度的东西。

我的 HTML 标记看起来像这样

<div class="inner-wrapper" style="">
<div class="style-001">
    <ul role="listbox" aria-multiselectable="true" class="style-002">
    <li role="option" aria-selected="false" class="style-003">
        <span class="style-004">First Option</span>
    </li>
    <li role="option" aria-selected="false" class="style-003">
        <span class="style-004">Second Option</span>
    </li>
    <li role="option" aria-selected="false" class="style-003">
        <span class="style-004">Third Option</span>
    </li>      
    </ul>
</div>

我试图根据 span 的文本 select 具体 'li' 。此页面是动态的,因此有时 'Third Option' 会有索引 [3],有时会有其他索引。它必须仅由 span 的文本 select 编辑,因为它在其他情况下不起作用。我不能使用 class 因为这个网站对每个 'li'.

使用相同的 classes

我研究了 google 和 Whosebug,但没有找到可行的解决方案。我尝试通过 xpath、js select 或更多 selecting。甚至我也尝试过这样的事情:

const [link] = await page.$x('//div[2]/div/div/section/div[2]/div/div/div/ul/li[2]/span[contains(text(), "First Option")]'); 
await link.click();

let selectOption = await page.waitForXPath(`//div[2]/div/div/section/div[2]/div/div/div/ul/li[contains(text(),'First Option')]`);
await selectOption.click();

如果有人能帮助我,我将不胜感激。

@编辑 如果点击任何选项很重要,本网站会将 aria-selected="false" 更改为 "true"。也许它会以任何方式帮助?

您可以尝试使用 page.evaluate 而不是使用 querySelectorAllfilter 通过文本 li 而不是使用 forEach 单击 il 与特定文本。

await page.evaluate(() => {
  Array.from(document.querySelectorAll('li')).filter(li => {
    return li.innerText == 'First Option' // filter il for specific text
  }).forEach(element => {
    if (element) element.click(); // click on il with specific text
  });
});

如果第一个不行可以试试

await page.evaluate(() => {
  Array.from(document.querySelectorAll('div > div > ul > li')).filter(li => {
    return li.innerText == 'First Option' // filter il for specific text
  }).forEach(element => {
    if (element) element.click(); // click on il with specific text
  });
});

您也可以尝试一下,我认为这是最好的方法。

await page.evaluate(() => {
  const elements = [...document.querySelectorAll('div > div > ul > li')];
  const targetElement = elements.find(e => e.innerText == 'First Option');
  if (targetElement) targetElement.click();
});

await page.evaluate(() => {
  const elements = [...document.querySelectorAll('li')];
  const targetElement = elements.find(e => e.innerText == 'First Option');
  if (targetElement) targetElement.click();
});