Puppeteer-常規操做一

這裏不講 Puppeteer 怎麼使用,主要講一些常規操做在這裏如何經過另類方法實現。等實現後,你就會感受,嗯~~ 真香!javascript

場景一

已經找出要的元素,如今有需求再繼續尋找他的子元素java

  • 第一種、將父元素帶入 evaluate 事件中
// 已經找出父元素
const foo = await page.$('.foo');
// 將父元素帶入 `evaluate` 事件中,經過原生方法繼續後續操做
const bar = await page.evaluate(fooEle => fooEle.querySelector('.bar'), foo);

這裏的 evaluate 好處就是 callback 裏面能夠經過原生js進行操做,callback 後面的 argument 以逗號形式分割,順序傳入 callback 中。dom

  • 第二種、繼續經過本來的操做
// 已經找出父元素
const foo = await page.$('.foo');
// 繼續經過本來的操做
const bar = await foo.$('.bar');

這裏比較通俗易懂,page 找出的對象後面實際上是繼續給了 page 的全部方法,但因爲 page 大部分方法都是異步 <Promise> 的,因此必須等待完成才能夠操做,不能使用鏈式操做。異步

這裏主要看習慣哪種操做,第一種的好處習慣原生js,可是大部分操做只能在 callback 中操做,相似 page.$eval 等操做;第二種的好處是直接操做,不含糊,讓人以爲更舒服一點,無論之後作輸入仍是點擊,都很是方便。async

場景二

每次作點擊/輸入以前都要進行驗證即將操做對象是否存在lua

// 封裝須要等待
// 等待出現
const waitPre = async(st) => 
  await page.waitFor(selector =>
    !!document.querySelector(selector), {}, st);
// 等待消失
const waitFade = async(st) => 
  await page.waitFor(selector =>
    !document.querySelector(selector), {}, st);

await waitPre('.foo'); // await page.waitFor('.foo');
await page.click('.foo');
// await waitPre('.foo');
// dosomething...

這裏不作過多解釋,非人操做都很快,不像人同樣還看到後再操做。spa

場景三

當點擊形成頁面跳轉或者從新加載時,須要等待頁面加載完成。code

const [response] = awiat Promise.all([
    page.waitFroNavigation(),
    page.click('.btn'), // 點擊致使頁面跳轉(重載)
]);

response

response 是加載dom時的響應對象。對象

場景四

當主動讓頁面跳轉(重載),並且這裏也須要監聽重載後的某個請求的響應對象。事件

  • 第一種、等待 reload 完成後再監聽
await page.reload(); // 也能夠加option,但這裏想到要監聽某個請求,故爲空
await const response = await page.waitForResponse(response => {});

response

這種監聽方式有可能會漏掉某些請求。

  • 第二種、直接經過 on 監聽
page.on('response', response => {});
await page.reload();

這裏的監聽無任何限制,不管頁面作什麼操做,都不會逃過 on 的法眼。

場景五

我想刪除全部文本,這裏只能經過 keyboard 來實現。

  • 第一種、計算長度,逐個刪除
const cls = '.foo';
await page.waitFor(cls);
await page.focus(cls);
const len = await page.$eval(cls, el => el.textContent.length);
for (let i = 0; i < len; i++) {
    await page.keyboard.press('Backspace');
}
await page.type(cls, 'something');

經過循環刪除,不推薦

  • 第二種、計算長度,選中,刪除
const cls = '.foo';
await page.waitFor(cls);
await page.focus(cls);
const text = await page.$eval(cls, el => el.textContent.length);
await page.keyboard.down('Shift');
for (let i = 0; i < text.length; i++) {
    await page.keyboard.press('ArrowLeft');
}
await page.keyboard.up('Shift');
await page.keyboard.press('Backspace');
await page.type(cls, 'something');

循環選中,一次性刪除。

  • 第三種、全選,一次性刪除
const cls = '.foo';
await page.waitFor(cls);
await page.focus(cls);
const text = await page.$eval(cls, el => el.textContent.length);
await page.keyboard.down('ControlLeft');
await page.keyboard.press('KeyA');
await page.keyboard.up('ControlLeft');
await page.keyboard.press('Backspace');
await page.type(cls, 'something');

Mac os x 上這裏未實現,這種方法不可用。目前推薦使用第二種方法,等官方消息。
Mac os x 上 不支持。

相關文章
相關標籤/搜索