important! 欢迎点赞收藏,会不定期更新
1. Puppeteer点击包含指定文字内容的元素
async function clickWithText(selector,text){
await page.$$eval(selector, (options=[],text) => {
options.forEach(item=>{
item.textContent.includes(text) && item.click()
})
},text)
}
// 点击包含’提交‘文字的按钮。传入选择器主要是为了缩小需要变量的元素范围和减少选取错误
// forEach无法中断循环,如果只想找到第一个匹配元素只可以使用for+break
clickWithText('button','提交')
puppeteer在headless模式下,可能会有文字渲染不完整情况(原因可能很多,比如Linux机器上没有网页中指定的字体文件),所以慎用通过文字内容作为判断条件的相关操作
2. Puppeteer按元素截图
// 方法1:
async function screenshotDOMElement(selector,path) {
const eleH = await page.$(selector)
eleH.screenshot({
path
})
}
// 方法2:计算元素位置截图
async function screenshotDOMElement(selector, path, padding = 0) {
const rect = await page.evaluate(selector => {
try {
const element = document.querySelector(selector);
const { x, y, width, height } = element.getBoundingClientRect();
if (width * height != 0) {
return { left: x, top: y, width, height, id: element.id };
} else {
return null;
}
} catch (e) {
return null;
}
}, selector);
return await page.screenshot({
path: path,
clip: rect ? {
x: rect.left - padding,
y: rect.top - padding,
width: rect.width + padding * 2,
height: rect.height + padding * 2
} : null
});
}
screenshotDOMElement('div.test','.test.png')
3. puppeteer获取打开的链接,puppeteer获取其他标签
获取Page句柄,使用page.bringToFront()将tab切换到该Page
// 方法一:browser.pages()可以获取所有打开的Page对象,可以通过遍历或筛选找到自己想获取的Page对象
//获取地址为‘http://woleigequ.net/’的Page对象
let pageList = await browser.pages();
let newPage = pageList.find(item=>item.url() == 'http://woleigequ.net/')
// 方法2:在打开新页面之前,通过browser.waitForTarget获取target
//获取地址为‘http://woleigequ.net/’的Page对象
const target = await browser.waitForTarget(t=>t.url() == 'http://woleigequ.net/')
... // 打开新页面
const newPage = await target.page();
// 方法3:browser.on(‘targetcreated’) 监听创建新的标签
const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())));
... // 打开新页面
const newPage = await newPagePromise; // newPage就是新打开窗口的Page对象
4. Puppeteer点击svg图标
page.click(selector)方法是没办法实现触发svg点击事件的,可以通过其他方式来实现:
- js 主动派发click事件
- 通过getBoundingClientRect获取图标位置,使用page.mouse来触发点击
// 方法一:
await page.evaluate(() => {
document.querySelector(selector).dispatchEvent(new Event('click'))
});
// 方法二:
const rect = await page.evaluate(() => {
try {
const element = document.querySelector('#uploadifive-UpUpFile1');
const { x, y, width, height } = element.getBoundingClientRect();
if (width * height != 0) {
return { left: x, top: y, width, height, id: element.id };
} else {
return null;
}
} catch (e) {
return null;
}
});
await page.mouse.click(rect.left + rect.width / 2, rect.top + rect.height / 2)
5.puppeteer文件上传
// 方法一:input
const inputHandler = await page.$('input[type=file]')
inputHandler.uploadFile(path.join(__dirname, 'test.js'))
// 方法二:fileChooser
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.click('#input-trigger')
]).catch(async (e) => {
console.log(e)
});
fileChooser.accept([path.join(__dirname, 'test.js')])
uploadFile接收字符串参数,选中多个文件需要传入多个文件路径作为参数,accept接收文件路径数组
6. 加载cookies
页面登录经常会遇到各种登录验证:短信验证,二维码验证,手势验证等,直接注入cookies就可以避免手动登录和验证。可以选择使用EidtThisCookie插件导出cookies,再通过setCookie进行导入:
const cookiePath = path.join(__dirname, cookiePath)
const cookies = fs.readFileSync(cookiePath, 'utf-8');
if (cookies) {
console.log(`have ${cookiePath} cookies,true`)
}
} catch (err) {
await sendEmailException('金锄头', "'cookies'", err)
}
await page.setCookie(...JSON.parse(cookies));
EditThisCookie导出的cookies基本是下面格式:
[...,{
"domain": ".aabb.cc",
"expirationDate": 1725975686.330711,
"hostOnly": false,
"httpOnly": false,
"name": "XYZ",
"path": "/",
"sameSite": "no_restriction",
"secure": true,
"session": false,
"storeId": "0",
"value": "...........",
"id": 1
},...]
如果你发现导入cookies之后没有生效,还是未登录状态,可以再补充一个url:
{
"url": "https://aabb.cc"
}
也可以通过document来设置:
page.goto(url).then(()=>{
page.evaluate(()=>document.cookie = 'XYZ=.....; path=/')
})
有问题可以留言