亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

詳解Node使用Puppeteer完成一次復雜的爬蟲

2019-11-19 14:00:27
字體:
來源:轉載
供稿:網友

本文介紹了詳解Node使用Puppeteer完成一次復雜的爬蟲,分享給大家,具體如下:

架構圖

Puppeteer架構圖

  1. Puppeteer 通過 devTools 與 browser 通信
  2. Browser 一個可以擁有多個頁面的瀏覽器(chroium)實例
  3. Page 至少含有一個 Frame 的頁面
  4. Frame 至少還有一個用于執行 javascript 的執行環境,也可以拓展多個執行環境

前言

最近想要入手一臺臺式機,筆記本的i5在打開網頁和vsc的時候有明顯卡頓的情況,因此打算配1臺 i7 + GTX1070TI or GTX1080TI的電腦,直接在淘寶上搜需要翻頁太多,并且圖片太多,腦容量接受不了,因此想爬一些數據,利用圖形化分析一下最近價格的走勢。因此寫了一個用Puppeteer寫了一個爬蟲爬去相關數據。

什么是Puppeteer?

Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.

簡而言之,這貨是一個提供高級API的node庫,能夠通過devtool控制headless模式的chrome或者chromium,它可以在headless模式下模擬任何的人為操作。

和cheerio的區別

cherrico本質上只是一個使用類似jquery的語法操作HTML文檔的庫,使用cherrico爬取數據,只是請求到靜態的HTML文檔,如果網頁內部的數據是通過ajax動態獲取的,那么便爬去不到的相應的數據。而Puppeteer能夠模擬一個瀏覽器的運行環境,能夠請求網站信息,并運行網站內部的邏輯。然后再通過WS協議動態的獲取頁面內部的數據,并能夠進行任何模擬的操作(點擊、滑動、hover等),并且支持跳轉頁面,多頁面管理。甚至能注入node上的腳本到瀏覽器內部環境運行,總之,你能對一個網頁做的操作它都能做,你不能做的它也能做。

開始

本文不是一個手把手教程,因此需要你有基本的Puppeteer API常識,如果不懂,請先看看官方介紹
Puppeteer官方站點
PuppeteerAPI

首先我們觀察要爬去的網站信息 GTX1080

這是我們要爬取的淘寶網頁,只有中間的商品項目是我們需要爬取的內容,仔細分析它的結構,相信一個前端都有這樣的能力。

我使用的Typescript,能夠獲得完整的Puppetter及相關庫的API提示,如果你不會TS,只需要將相關的代碼換成ES的語法就好了

// 引入一些需要用到的庫以及一些聲明import * as puppeteer from 'puppeteer' // 引入Puppeteerimport mongo from '../lib/mongoDb' // 需要用到的 mongodb庫,用來存取爬取的數據import chalk from 'chalk' // 一個美化 console 輸出的庫const log = console.log // 縮寫 console.logconst TOTAL_PAGE = 50 // 定義需要爬取的網頁數量,對應頁面下部的跳轉鏈接// 定義要爬去的數據結構interface IWriteData {  link: string // 爬取到的商品詳情鏈接 picture: string // 爬取到的圖片鏈接 price: number // 價格,number類型,需要從爬取下來的數據進行轉型 title: string // 爬取到的商品標題}// 格式化的進度輸出 用來顯示當前爬取的進度function formatProgress (current: number): string {  let percent = (current / TOTAL_PAGE) * 100 let done = ~~(current / TOTAL_PAGE * 40) let left = 40 - done let str = `當前進度:[${''.padStart(done, '=')}${''.padStart(left, '-')}]  ${percent}%` return str}

接下來我們開始進入到爬蟲的主要邏輯

// 因為我們需要用到大量的 await 語句,因此在外層包裹一個 async functionasync function main() { // Do something}main()
// 進入代碼的主邏輯async function main() { // 首先通過Puppeteer啟動一個瀏覽器環境 const browser = await puppeteer.launch() log(chalk.green('服務正常啟動')) // 使用 try catch 捕獲異步中的錯誤進行統一的錯誤處理 try {  // 打開一個新的頁面  const page = await browser.newPage()  // 監聽頁面內部的console消息  page.on('console', msg => {   if (typeof msg === 'object') {    console.dir(msg)   } else {    log(chalk.blue(msg))   }  })  // 打開我們剛剛看見的淘寶頁面  await page.goto('https://s.taobao.com/search?q=gtx1080&imgfile=&js=1&stats_click=search_radio_all%3A1&initiative_id=staobaoz_20180416&ie=utf8')  log(chalk.yellow('頁面初次加載完畢'))  // 使用一個 for await 循環,不能一個時間打開多個網絡請求,這樣容易因為內存過大而掛掉  for (let i = 1; i <= TOTAL_PAGE; i++) {   // 找到分頁的輸入框以及跳轉按鈕   const pageInput = await page.$(`.J_Input[type='number']`)   const submit = await page.$('.J_Submit')   // 模擬輸入要跳轉的頁數   await pageInput.type('' + i)   // 模擬點擊跳轉   await submit.click()   // 等待頁面加載完畢,這里設置的是固定的時間間隔,之前使用過page.waitForNavigation(),但是因為等待的時間過久導致報錯(Puppeteer默認的請求超時是30s,可以修改),因為這個頁面總有一些不需要的資源要加載,而我的網絡最近日了狗,會導致超時,因此我設定等待2.5s就夠了   await page.waitFor(2500)   // 清除當前的控制臺信息   console.clear()   // 打印當前的爬取進度   log(chalk.yellow(formatProgress(i)))   log(chalk.yellow('頁面數據加載完畢'))   // 處理數據,這個函數的實現在下面   await handleData()   // 一個頁面爬取完畢以后稍微歇歇,不然太快淘寶會把你當成機器人彈出驗證碼(雖然我們本來就是機器人)   await page.waitFor(2500)  }  // 所有的數據爬取完畢后關閉瀏覽器  await browser.close()  log(chalk.green('服務正常結束'))  // 這是一個在內部聲明的函數,之所以在內部聲明而不是外部,是因為在內部可以獲取相關的上下文信息,如果在外部聲明我還要傳入 page 這個對象  async function handleData() {   // 現在我們進入瀏覽器內部搞些事情,通過page.evaluate方法,該方法的參數是一個函數,這個函數將會在頁面內部運行,這個函數的返回的數據將會以Promise的形式返回到外部    const list = await page.evaluate(() => {        // 先聲明一個用于存儲爬取數據的數組    const writeDataList: IWriteData[] = []    // 獲取到所有的商品元素    let itemList = document.querySelectorAll('.item.J_MouserOnverReq')    // 遍歷每一個元素,整理需要爬取的數據    for (let item of itemList) {     // 首先聲明一個爬取的數據結構     let writeData: IWriteData = {      picture: undefined,      link: undefined,      title: undefined,      price: undefined     }     // 找到商品圖片的地址     let img = item.querySelector('img')     writeData.picture = img.src     // 找到商品的鏈接     let link: HTMLAnchorElement = item.querySelector('.pic-link.J_ClickStat.J_ItemPicA')     writeData.link = link.href     // 找到商品的價格,默認是string類型 通過~~轉換為整數number類型     let price = item.querySelector('strong')     writeData.price = ~~price.innerText          // 找到商品的標題,淘寶的商品標題有高亮效果,里面有很多的span標簽,不過一樣可以通過innerText獲取文本信息     let title: HTMLAnchorElement = item.querySelector('.title>a')      writeData.title = title.innerText     // 將這個標簽頁的數據push進剛才聲明的結果數組     writeDataList.push(writeData)    }    // 當前頁面所有的返回給外部環境    return writeDataList       })   // 得到數據以后寫入到mongodb   const result = await mongo.insertMany('GTX1080', list)   log(chalk.yellow('寫入數據庫完畢'))  } } catch (error) {  // 出現任何錯誤,打印錯誤消息并且關閉瀏覽器  console.log(error)  log(chalk.red('服務意外終止'))  await browser.close() } finally {  // 最后要退出進程  process.exit(0) }}

思考

1、為什么使用Typescript?

因為Typescript就是好用啊,我也背不住Puppeteer的全部API,也不想每一個都查,所以使用TS就能智能提醒了,也能避免因為拼寫導致的低級錯誤?;旧嫌昧薚S以后,敲代碼都能一遍過

puppeteer.png

2、爬蟲的性能問題?

因為Puppeteer會啟動一個瀏覽器,執行內部的邏輯,所以占用的內存是蠻多的,看了看控制臺,這個node進程大概占用300MB左右的內存。

我的頁面是一個個爬的,如果想更快的爬取可以啟動多個進程,注意,V8是單線程的,所以在一個進程內部打開多個頁面是沒有意義的,需要配置不同的參數打開不同的node進程,當然也可以通過node的cluster(集群)實現,本質都是一樣的
我在爬取的過程中也設置了不同的等待時間,一方面是為了等待網頁的加載,一方面避免淘寶識別到我是爬蟲彈驗證碼

3、Puppeteer的其它功能

這里僅僅利用了Puppeteer的一些基本特性,實際上Puppeteer還有更多的功能。比如引入node上的處理函數在瀏覽器內部執行,將當前頁面保存為pdf或者png圖片。并且還可以通過const browser = await puppeteer.launch({ headless: false })啟動一個帶界面效果的瀏覽器,你可以看見你的爬蟲是如何運作的。此外一些需要登錄的網站,如果你不想識別驗證碼委托第三方進行處理,你也可以關閉headless,然后在程序中設置等待時間,手動完成一些驗證從而達到登錄的目的。

當然google制作了一個這么牛逼的庫可不只是用來做爬蟲爬取數據的,這個庫也用作于一些自動化的性能分析、界面測試、前端網站監控等

4、一些其它方面的思考

總得來說制作爬蟲爬取數據是一項較為復雜并考察多項基本功的練習項目,在這個爬蟲里多次使用到了async,這就需要對async、Promise等相關知識充分的了解。在分析DOM收集數據時,也多次利用了原生的方法獲取DOM屬性(如果網站有jquery也可以直接用,沒有的話需要外部注入,在typescript下需要進行一些配置,避免報錯未識別的$變量,這樣就可以通過jquery語法操作DOM),考察了對DOM相關API的熟練程度。

另外這只是一個面向過程的編程,我們完全可以將它封裝為一個類進行操作,這也考察了對ES的OOP理解

最后

本文的源代碼Github,喜歡的朋友給個star吧

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品网站在线播放gif| 国产成人一区二区三区小说| 91亚洲精品久久久久久久久久久久| 欧美一级黑人aaaaaaa做受| 国自在线精品视频| 亚洲欧美在线免费| 中文字幕av一区中文字幕天堂| 黄网站色欧美视频| 国产精品久久国产精品99gif| 美女999久久久精品视频| 欧美午夜精品伦理| 久久久久久成人| 91精品国产自产在线观看永久| 久久综合伊人77777尤物| 亚洲午夜未满十八勿入免费观看全集| 亚洲国产99精品国自产| 成人精品视频99在线观看免费| 777国产偷窥盗摄精品视频| 日韩网站免费观看| 久久久精品亚洲| 欧美一区在线直播| 91久久久久久国产精品| 国产精品第2页| 欧美猛少妇色xxxxx| 97精品视频在线观看| 欧美精品一区二区免费| 久久精品在线视频| 亚洲精品一区二区网址| 欧美日韩综合视频| 日韩一区在线视频| 久久久国产成人精品| 国产z一区二区三区| 国产精品jizz在线观看麻豆| 少妇高潮 亚洲精品| 国产午夜一区二区| 国产91色在线播放| 欧美激情免费在线| 成人有码视频在线播放| 麻豆国产精品va在线观看不卡| 欧美另类老女人| 亚洲图中文字幕| 国产成人在线一区| 亚洲视频免费一区| 91成人性视频| 国产日本欧美一区| 欧美精品在线看| 免费av一区二区| 成人xvideos免费视频| 在线日韩欧美视频| 欧美日韩亚洲视频一区| 68精品国产免费久久久久久婷婷| 亚洲精品成人网| 国产欧美日韩免费看aⅴ视频| 国产一区二区激情| 精品久久久久久久久中文字幕| 国产精品私拍pans大尺度在线| 91豆花精品一区| 久久国产精品首页| 欧美激情视频在线观看| 91影院在线免费观看视频| 久久久久久久久久久av| 狠狠色狠狠色综合日日五| 欧美视频中文字幕在线| 夜夜躁日日躁狠狠久久88av| 青草青草久热精品视频在线网站| 日韩av在线一区| 欧美激情喷水视频| 日本久久亚洲电影| 久久国内精品一国内精品| 久久亚洲精品中文字幕冲田杏梨| 日韩国产欧美精品一区二区三区| 欧美日韩在线第一页| 91亚洲精品久久久久久久久久久久| 国产精品视频最多的网站| 日本sm极度另类视频| **欧美日韩vr在线| 欧美制服第一页| 精品国产一区av| 亚洲一区二区三区乱码aⅴ蜜桃女| 国精产品一区一区三区有限在线| 538国产精品一区二区在线| 精品中文字幕在线| 成人黄色av免费在线观看| 欧美激情xxxx性bbbb| 亚洲成年人影院在线| 国模精品视频一区二区| 久久91亚洲人成电影网站| 欧美日韩亚洲91| 国产一区二区三区三区在线观看| 欧美性生活大片免费观看网址| 国产91网红主播在线观看| 亚洲视频网站在线观看| 久久91亚洲精品中文字幕| 亚洲一区二区在线播放| 国产suv精品一区二区| 色偷偷噜噜噜亚洲男人的天堂| 2019中文字幕在线观看| 91免费人成网站在线观看18| 亚洲a在线观看| 亚洲精品综合久久中文字幕| 欧美最猛性xxxxx亚洲精品| 午夜免费在线观看精品视频| 国产精品www网站| 亚洲第一精品自拍| 国产精品一区二区三区免费视频| 久久久久久亚洲精品| 91热福利电影| 国产精品高清在线观看| 日韩av中文字幕在线播放| 亚洲成色999久久网站| 欧美日韩国产成人在线| 亚洲成年人影院在线| 91精品视频在线播放| 红桃av永久久久| 色噜噜亚洲精品中文字幕| 中文字幕亚洲一区在线观看| 亚洲国产免费av| 亚洲成人xxx| 国产在线精品一区免费香蕉| 大荫蒂欧美视频另类xxxx| 国产精品99久久久久久白浆小说| 亚洲人成自拍网站| 色综合久久88| 在线观看欧美日韩国产| 色播久久人人爽人人爽人人片视av| 久久免费视频在线| 日韩免费av一区二区| 久久久精品国产一区二区| 亚洲综合中文字幕在线| 国产精品看片资源| 久国内精品在线| 亚洲一级一级97网| 亚洲最大福利视频网| 亚洲欧美色婷婷| 日韩欧美在线看| 欧美在线一区二区三区四| 日本久久久久亚洲中字幕| 97国产精品免费视频| 欧美亚洲视频一区二区| 亚洲精品资源在线| 亲子乱一区二区三区电影| 亚洲va电影大全| 最近2019中文字幕一页二页| 国产精品美女呻吟| 91在线观看免费高清完整版在线观看| 国产精品精品久久久久久| 日韩中文字幕视频在线观看| 欧美激情图片区| 国产精品久久久久久一区二区| 欧美性理论片在线观看片免费| 欧美综合国产精品久久丁香| 青青草精品毛片| 欧美性猛交xxxx富婆弯腰| 亚洲精品成a人在线观看| 日韩精品在线影院| 亚洲a成v人在线观看| 亚洲a成v人在线观看| 亚洲电影第1页| 亚洲国产精品va在看黑人| 国产精品aaaa| 亚洲图片在区色| 国产丝袜视频一区| 国产精品视频999| 庆余年2免费日韩剧观看大牛|