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();
}, $);
複製代碼
相關文章
相關標籤/搜索