Вы можете легко добавить дополнительные функции к Page
, используя prototype
.И получите конкретный элемент, используя page.elementHandle .
Единственное отличие между page.evaluate
и page.evaluateHandle
состоит в том, что page.evaluateHandle
возвращает объект на странице (JSHandle
).
Создание функции elementContains
Модуль Puppeteer экспортирует классы следующим образом.Вы можете расширить их функциональные возможности, как вы хотите.
// extract the Page class
const { Page } = require("puppeteer/lib/Page");
Обычно создаваемый вами page
становится this
внутри прототипа.page.evaluateHandle
станет this.evaluateHandle
.
/**
* @name elementContains
* @param {String} selector specific selector globally search and match
* @param {String} text filter the elements with the specified text
* @returns {Promise} elementHandle
*/
Page.prototype.elementContains = function elementContains(...args) {
return this.evaluateHandle((selector, text) => {
// get all selectors for this specific selector
const elements = [...document.querySelectorAll(selector)];
// find element by text
const results = elements.filter(element => element.innerText.includes(text));
// get the last element because that's how querySelectorAll serializes the result
return results[results.length-1];
}, ...args);
};
Создание функции .get
Теперь, когда мы получили нашу замечательную elementContains
, пришло время получить функцию get
.
/**
* Replicate the .get function
* gets an element from the executionContext
* @param {String} selector
* @returns {Promise}
*/
const { JSHandle } = require("puppeteer/lib/JSHandle");
JSHandle.prototype.get = function get(selector) {
// get the context and evaluate inside
return this._context.evaluateHandle(
(element, selector) => {
return element.querySelector(selector);
},
// pass the JSHandle which is itself
this,
selector
);
};
Имеемвесело с новой функцией
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.setContent(html); // your specified html text
// get the element
const elem = await page.elementContains('div', 'title1')
// use it like any other normal element, click it, eval it, remove it etc.
const content = await elem.$eval('h1', e=>e.innerText);
console.log(content) // prints "title1"
// OR use the built in click function
const btn = await page.$('a', elem); // <-- pass the handle here
await btn.click();
// OR use our .get function to get another element
const targetBtn = await elem.get('a');
targetBtn.click(); // click it
})();
Результат: