Как перейти по ссылке, которая содержит определенный контент в кукловоде?

Если у меня есть контент на моей странице, такой как:

<a>Hi!</a>

Как я могу использовать Google Puppeteer для автоматизации нажатия этого элемента?

Мне нужно иметь возможность выбрать его на основе только его содержимого, а не идентификатор, класс или атрибут.

Есть ли что-то вроде $('a:contains("Hi!")') что я могу использовать, чтобы выбрать этот элемент?

Как я могу сделать это с помощью https://github.com/GoogleChrome/puppeteer

Спасибо

1 ответ

Решение

Сначала мы должны найти элемент за текстом.

/**
 * findElemByText - Find an Element By Text
 *
 * @param  {String} str                case-insensitive string to search
 * @param  {String} selector = '*'     selector to search
 * @param  {String} leaf = 'outerHTML' leaf of the element
 * @return {Array}                     array of elements
 */
function findElemByText({str, selector = '*', leaf = 'outerHTML'}){
  // generate regex from string
  const regex = new RegExp(str, 'gmi');

  // search the element for specific word
  const matchOuterHTML = e => (regex.test(e[leaf]))

  // array of elements
  const elementArray = [...document.querySelectorAll(selector)];

  // return filtered element list
  return elementArray.filter(matchOuterHTML)
}

// usage
// findElemByText({str: 'Example', leaf: 'innerHTML', selector: 'title'});
// findElemByText({str: 'Example', selector: 'h1'});
// findElemByText({str: 'Example'});

Сохраните его в той же папке, что и ваш сценарий кукловода, назовите его script.js,

Теперь мы можем использовать это в нашем сценарии кукловода. Мы можем использовать ElementHandle, но для простоты понимания я буду использовать .evaluate() Функция обеспечена кукловодом.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');

  // expose the function
  await page.addScriptTag({path: 'script.js'});

  // Find Element by Text and Click it
  await page.evaluate(() => {
   // click the first element 
   return findElemByText({str: 'More'})[0].click();
  });

  // Wait for navigation, Take Screenshot, Do other stuff
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
})();

Не копируйте и не вставляйте приведенный выше код, постарайтесь понять его и наберите их самостоятельно. Если приведенный выше код не работает, попробуйте найти причину сбоя.

Альтернативный подход с использованием XPath

Есть гораздо более простой способ сделать это с помощью выражения XPath:

const aElementsWithHi = await page.$x("//a[contains(., 'Hi!')]");
await aElementsWithHi[0].click();

С помощью page.$x, этот код находит все a элементы с текстом Hi!внутри. Результатом будет массив, содержащий совпадающиеaэлемент ручки. Используя elementHandle.click функции, затем мы можем щелкнуть элемент.

Другие вопросы по тегам