一、知識點
- page.mouse
- elementHandle.boundingBox()
-
ignoreDefaultArgs:['--enable-automation']
-
waitUntil
二、解析知識點
1.page.mouse
以下,截圖來自github puppeteer api(自行對照github) ,puppeteer已經提供給我們使用方法,很簡單,move - 移動,down - 按下, up - 抬起 ,通過這個我們可以很簡單的明白,場景拖拽的時候,我們先按下(down),再移動(move),最后松開(up),是不是很好理解
2.elementHandle.boundingBox()
boundingBox() 又是用來干嘛呢,我們看api, 他返回的是 x,y 坐標,還有寬度,長度,那就很好理解了,比如我上面運用了page.mouse,進行拖拽,但是我拖拽什么呢,拖拽的東西,鼠標點擊后肯定有x,y坐標,也有固定的長度,不可能一直讓你無限拖拽。
3.ignoreDefaultArgs:['--enable-automation']
這個是干嘛的,當我們運行發現chrome 左上角有個 Chrome 正受自動軟件控制,但是有時候有的網站會檢測到自動化腳本,會禁止掉,這時候我們如何避免puppeteer 被前端JS檢測到
const brower = await puppeteer.launch({ executablePath:'D:\\wangxiao\\chrome-win\\chrome-win\\chrome.exe', headless:false, ignoreDefaultArgs:['--enable-automation'] });
三、實例
1. 登入大麥網,我們今天來注冊一下,但是發現他需要滑動驗證,那么我們來試一下
2. 如何定位,如何切換iframe 這邊省略,前面已經講過了,這邊直接進入正題,前面代碼
/**1.切換iframe,2.向輸入框中輸入密碼**/
const brower = await puppeteer.launch({ executablePath:'D:\\wangxiao\\chrome-win\\chrome-win\\chrome.exe', headless:false }); const page = await brower.newPage(); await page.goto('https://passport.damai.cn/register',{waitUntil:'networkidle2'}); const frame = await page.frames().find(f => f.url().includes('https://ipassport.damai.cn/member')); await frame.waitFor('.next-input.next-large input[placeholder="輸入密碼"]'); await frame.type('.next-input.next-large input[placeholder="輸入密碼"]','122222');
3. 定位到滑動塊 const element = '.nc_iconfont.btn_slide' ; 調用boundingBox(),
問:為什么要調用boundingBox()
答:為了獲取滑動塊的x,y 坐標
const start = await frame.waitForSelector('.nc_iconfont.btn_slide');
const startinfo = await start.boundingBox();
4.定位整個拖動的塊,如何定位(省略,自己多聯系) const element = '.nc-lang-cnt‘
const end = await frame.waitForSelector('.nc-lang-cnt');
const endinfo = await end.boundingBox();
5. 分析下面該怎么做,首先我們獲取了start 滑動塊x,y坐標后,怎么滑動呢,毫無疑問肯定調用page.mouse 方法啊,所以下面代碼應該這么寫
1.確定要移動的目標x,y軸
2.按下
await page.mouse.move(startinfo.x,endinfo.y);
await page.mouse.down();
6. 有了以上的操作,按下后,我們怎么移動呢,我們分析一下滑動長度是不是不能大於滑動塊的寬度? 那么我們是不是得到了最大的長度 endinfo.width (前面介紹了,實在不知道調用啥的自己看api文檔)
然后我們在分析,有了最大跨度,移動的時候是不是只有x軸移動,y軸沒有移動呢,那么就很好做了,代碼如下,代碼應該很好理解,就是x 軸不能超過滑動塊的寬度,並且x軸是遞增的y軸是不動的,這個很好理解
for(var i=0;i<endinfo.width;i++) { await page.mouse.move(startinfo.x+i,endinfo.y); }
7.完整的代碼
const puppeteer = require('puppeteer'); (async () => { const brower = await puppeteer.launch({ executablePath:'D:\\wangxiao\\chrome-win\\chrome-win\\chrome.exe', headless:false }); const page = await brower.newPage(); await page.goto('https://passport.damai.cn/register',{waitUntil:'networkidle2'}); const frame = await page.frames().find(f => f.url().includes('https://ipassport.damai.cn/member')); const start = await frame.waitForSelector('.nc_iconfont.btn_slide'); const startinfo = await start.boundingBox(); const end = await frame.waitForSelector('.nc-lang-cnt'); const endinfo = await end.boundingBox(); await page.mouse.move(startinfo.x,endinfo.y); await page.mouse.down(); for(var i=0;i<endinfo.width;i++) { await page.mouse.move(startinfo.x+i,endinfo.y); } await page.mouse.up(); //await brower.close(); })().catch(error =>{console.log('error')});
8.結果如圖,滑動了,但是最后出錯了,為什么呢 ,分析原因之一,網站檢測出,我們用自動化腳本跑了,如何避免被前端JS檢測到呢,用到上面講的知識ignoreDefaultArgs:['--enable-automation']
完整代碼:我們加上ignoreDefaultArgs:["--enable-automation"] 這個屬性的時候發現,還是報錯,那么我們在分析一下,為什么?一般自動化跑的速度要比人快的多,那么最后一步松開是不是太快導致的呢,那我們就等待1-2秒,再松開,也有可能是滑動太慢了,總之能簡單處理先簡單處理,以后再深入
const puppeteer = require('puppeteer'); (async () => { const brower = await puppeteer.launch({ executablePath:'D:\\wangxiao\\chrome-win\\chrome-win\\chrome.exe', headless:false, ignoreDefaultArgs:["--enable-automation"] }); const page = await brower.newPage(); await page.goto('https://passport.damai.cn/register',{waitUntil:'networkidle2'}); const frame = await page.frames().find(f => f.url().includes('https://ipassport.damai.cn/member')); await frame.waitFor('.next-input.next-large input[placeholder="輸入密碼"]'); await frame.type('.next-input.next-large input[placeholder="輸入密碼"]','122222'); const start = await frame.waitForSelector('.nc_iconfont.btn_slide'); const startinfo = await start.boundingBox(); const end = await frame.waitForSelector('.nc-lang-cnt'); const endinfo = await end.boundingBox(); await page.mouse.move(startinfo.x,endinfo.y); await page.mouse.down(); for(var i=0;i<endinfo.width;i=i+5) { await page.mouse.move(startinfo.x+i,endinfo.y); } await page.waitFor(3000) await page.mouse.up(); //await brower.close(); })().catch(error =>{console.log('error')});