Puppeteer에서 텍스트가있는 요소를 클릭하는 방법 있습니다. <div class=”elements”> <button>Button

텍스트가있는 요소를 클릭하는 방법 (API에서 찾을 수 없음)이나 솔루션이 있습니까?

예를 들어 html이 있습니다.

<div class="elements">
    <button>Button text</button>
    <a href=#>Href text</a>
    <div>Div text</div>
</div>

그리고 다음과 같이 텍스트가 래핑 된 요소를 클릭하고 싶습니다 (.elements 내부의 버튼 클릭).

Page.click('Button text', '.elements')



답변

짧은 대답

이 XPath 표현식은 “버튼 텍스트”텍스트가 포함 된 버튼을 쿼리합니다.

const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
    await button.click();
}

<div class="elements">버튼 주변 도 존중하려면 다음 코드를 사용하세요.

const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");

설명

경우에 따라 텍스트 노드 ( text())를 사용하는 것이 잘못된 이유를 설명하기 위해 예제를 살펴 보겠습니다.

<div>
    <button>Start End</button>
    <button>Start <em>Middle</em> End</button>
</div>

먼저 다음을 사용할 때 결과를 확인하겠습니다 contains(text(), 'Text').

  • //button[contains(text(), 'Start')]예상대로 노드를 모두 반환합니다.
  • //button[contains(text(), 'End')]두 개의 텍스트 ( 및 ) 가있는 목록을 반환하므로 하나의 노드 (첫 번째) 만 반환 하지만 첫 번째 노드 만 확인합니다.text()Start Endcontains
  • //button[contains(text(), 'Middle')] 반환하지 않습니다 같은 결과를 text()자식 노드의 텍스트를 포함하지 않는다

에 대한 XPath 표현식 contains(., 'Text')은 하위 노드를 포함하여 요소 자체에서 작동합니다.

  • //button[contains(., 'Start')] 버튼을 모두 반환 합니다.
  • //button[contains(., 'End')]다시 두 개의 버튼을 모두 반환 합니다.
  • //button[contains(., 'Middle')]하나 를 반환합니다 (마지막 버튼).

따라서 대부분의 경우 XPath 표현식에서 대신를 사용하는 .것이 더 합리적 text()입니다.


답변

page. $ x (expression) 과 함께 XPath 선택기를 사용할 수 있습니다 .

const linkHandlers = await page.$x("//a[contains(text(), 'Some text')]");

if (linkHandlers.length > 0) {
  await linkHandlers[0].click();
} else {
  throw new Error("Link not found");
}

clickByText요점 에서 완전한 예를 확인하십시오 . XPath 표현식에서는 약간 까다로운 따옴표 이스케이프를 처리합니다.


답변

를 사용 page.evaluate()하여 document.querySelectorAll()텍스트 콘텐츠로 필터링 된 에서 얻은 요소를 클릭 할 수도 있습니다 .

await page.evaluate(() => {
  [...document.querySelectorAll('.elements button')].find(element => element.textContent === 'Button text').click();
});

또는를 page.evaluate()사용하여 document.evaluate()및 해당 XPath 표현식을 사용하여 텍스트 콘텐츠를 기반으로 요소를 클릭 할 수 있습니다 .

await page.evaluate(() => {
  const xpath = '//*[@class="elements"]//button[contains(text(), "Button text")]';
  const result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);

  result.iterateNext().click();
});


답변

“: contains (text)”와 같은 고급 CSS 선택기를 사용할 수있는 빠른 솔루션을 만들었습니다.

라이브러리 를 사용하면

const select = require ('puppeteer-select');

const element = await select(page).getElement('button:contains(Button text)');
await element.click()


답변

내 해결책은 다음과 같습니다.

let selector = 'a';
    await page.$$eval(selector, anchors => {
        anchors.map(anchor => {
            if(anchor.textContent == 'target text') {
                anchor.click();
                return
            }
        })
    });


답변

해결책은

(await page.$$eval(selector, a => a
            .filter(a => a.textContent === 'target text')
))[0].click()


답변

텍스트 선택기 또는 결합 자 옵션에 대해 지원되는 CSS 선택기 구문이 없습니다. 이에 대한 해결 방법은 다음과 같습니다.

await page.$$eval('selector', selectorMatched => {
    for(i in selectorMatched)
      if(selectorMatched[i].textContent === 'text string'){
          selectorMatched[i].click();
          break;//Remove this line (break statement) if you want to click on all matched elements otherwise the first element only is clicked
        }
    });