puppeteer入门及使用electron打包(一)

参考文档

官方Github地址:github.com/puppeteer/p…

iT邦幫忙系列教程:ithelp.ithome.com.tw/articles/10…

博客总结:www.cnblogs.com/paris-test/…

掘金安装问题:juejin.im/post/5b99c9…

csdn切换page:blog.csdn.net/w20101310/a…

csdn切换iframe:blog.csdn.net/qupan1993/a…

chromium浏览器下载地址:npm.taobao.org/mirrors/chr…

1、安装

一、自带浏览器版,(打包有450M)

mkdir my-app
    cd my-app
    npm init -y
    npm i puppeteer
    # or "yarn add puppeteer"
复制代码

二、生产安装轻量核心版(不带浏览器打包145M)

npm i puppeteer-core
# or "yarn add puppeteer-core"
复制代码

2、配置

//import puppeteer from "puppeteer-core";//核心板
import puppeteer from "puppeteer";
const isDevelopment = process.env.NODE_ENV !== 'production'
this.browser = await puppeteer.launch({
        headless: !isDevelopment,
        executablePath: "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
         defaultViewport: {
                width: 1349,
                height: 600
           }
      })
复制代码

headless默认true,开发环境使用false,能够看到可视化页面 executablePath:默认node_modules下的Chromium浏览器,能够改成本地的chrome浏览器 defaultViewport:窗口大小,默认800×600页面显示不全html

使用

截图

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

  await browser.close();
})();
复制代码

生成PDF

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
  await page.pdf({path: 'hn.pdf', format: 'A4'});

  await browser.close();
})();
复制代码

获取视图大小node

const puppeteer = require('puppeteer');

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

  // Get the "viewport" of the page, as reported by the page.
  const dimensions = await page.evaluate(() => {
    return {
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight,
      deviceScaleFactor: window.devicePixelRatio
    };
  });

  console.log('Dimensions:', dimensions);

  await browser.close();
})();
复制代码

3、采坑

一、hover没法显示

await page.waitFor(2000);//hover前不加延迟,就会超时?????
 await page.hover(moreBtnSelector)
复制代码

二、切换page

(1)browser.pages()jquery

browser.pages()[0]
复制代码

(2)page.url()、page.name()git

const page2 = (await browser.pages()).find(p => p.url().indexOf('beijing') > -1)
复制代码

(3)使用targetcreated事件github

const newPagePromise = new Promise(x => this.browser.once('targetcreated', target => x(target.page()))); // targetcreated发生时就能够获得page
复制代码

三、iframe嵌套,获取iframe

(1)page.frames()chrome

const frame1 = ( await page.frames() )[0]
复制代码

(2)page.url()、page.name()。 page.url()获得的地址和看到的src有时不相同, page.name()多是重复的npm

const frame1 = await page.frames().find(f => f.name() === 'allbox');
复制代码

四、网络慢的时候会发生,操做iframe报错,iframe为undefined

解决方法浏览器

const frame1 = await new Promise((resolve, reject) => {
        let timer
        let fn = () => {
            if (timer) clearTimeout(timer)
            let frame = page.mainFrame().childFrames().find(f => f.url().indexOf('xxx') > -1)
            if (frame) {
            resolve(frame)
            } else {
            timer = setTimeout(fn, 200)
            }
        }
            fn()
})

const frame2 = await new Promise((resolve, reject) => {
    let timer
    let fn = () => {
    if (timer) clearTimeout(timer)
        let frame = frame1.childFrames().find(f => f.name() === 'lhsbIframe')
        if (frame) {
        resolve(frame)
        } else {
        timer = setTimeout(fn, 200)
        }
    }
    fn()
})
复制代码

五、隐藏弹框

await frame1.$eval('div[id="layui-layer1"]', f => f.style.display = 'none')
复制代码

六、填写input,使用xpath获取所有的可编辑input,而后填写

await this.typeInput('//input[@type="text" and @jpath and not(@readonly)]', page, frame2)
async typeInput(xPath, page, frame) {
    if (!frame) frame = page;
    const elementHandle = await frame.$x(xPath)
    for (let i = 0; i < elementHandle.length; i++) {
    let jpath = await frame.evaluate(el => el.getAttribute('jpath'), elementHandle[i])
    let value = this.gf(jpath)
    if (typeof value !== 'string') continue
    await elementHandle[i].focus()
    await this.inputClear(page)
    await elementHandle[i].type(value)
    }
    await this.inputBlur(page);
}
复制代码

七、page.type()方法会在旧数据的后面继续输入

//清空input
async inputClear(page) {
    await page.keyboard.down('Control');
    await page.keyboard.down('KeyA');
    await page.keyboard.press('Backspace');//Backspace/Delete
    await page.keyboard.up('Control');
    await page.keyboard.up('KeyA');
}
复制代码

八、有focus方法,没有找到blur方法,点击其余地方模拟blur

//input失去焦点
async inputBlur(page) {
    await page.click('body')
}
复制代码

九、input type="radio" 使用page.click

十、填写select,使用page.select()

十一、 喜欢使用jquery的能够,使用cheerio操做

const body = await page.content();
const $ = await cheerio.load(body);
await page.evaluate(async () => {
    const selector = await $('input[jpath="zzsybsbSbbdxxVO.qtkspzmxb.txffs"]')
    await selector.focus();
    await selector.val(7777);
    await selector.trigger("input").trigger('propertychange').trigger("change")
    //ng使用了modal双向绑定,须要手动触发onInput事件
    await selector.blur();
}, $);
复制代码
相关文章
相关标签/搜索