node 爬蟲,使用 Google puppeteer 抓取 One一個 的網頁資料

豬不樂意發表於2018-01-09

node 爬蟲,使用 Google puppeteer 抓取 One一個 的網頁資料

puppeteer 就不多介紹了,就是一個無介面化的谷歌瀏覽器。 作者本人是前端,後端方面的知識不太擅長,感覺漏洞還是蠻多的。 本教程是作者見獵心喜然後把玩了一下寫的,有不合理的地方還請包涵。

爬蟲思路

本例子是使用順序爬取,沒有用並行爬取,並設定了延時器,主要是擔心訪問頻次太高會被遮蔽訪問。

puppeteer 寫爬蟲感覺思路比別的更簡單,按視覺化的流程去走就可以。

  1. 啟動瀏覽器和開啟一個新頁面
  2. 跳轉到要抓取資料的頁面
  3. 獲取頁面上的資訊和圖片
  4. 列印資訊和儲存圖片
  5. 重複 2 ~ 4 步,直到所有頁面抓取結束
  6. 關閉瀏覽器退出程式

爬蟲程式碼

要抓取的頁面:http://wufazhuce.com/one/35

對於要抓取的資源,沒有弄複雜的邏輯,根據 URL 推斷是按ID排列的。 那麼只要對頁面 ID 依次累加就行了成功就抓取,錯誤就跳過。

const puppeteer = require('puppeteer');
const fs = require('fs');
const request = require('request');

// 延時器
let timeout = function (delay) {
  console.log('延遲函式:', `延遲 ${delay} 毫秒`)
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        resolve(1)
      } catch (error) {
        reject(error)
      }
    }, delay);
  })
}

/**
 * One 爬蟲類
 */
class OnePaChong {
  constructor () {
    // 最大索引
    this.maxIndex = 40
    // 初始化
    this.init()
  }
  // 初始化函式
  async init () {
    console.log('正在啟動瀏覽器...')
    this.browser = await puppeteer.launch();
    console.log('正在開啟新頁面...')
    this.page = await this.browser.newPage();
    // 順序爬取頁面
    for (let i = 30; i < this.maxIndex; i++) {
      await this.getPageInfo(i)
    }
    this.closeBrowser()
  }
  // 抓取頁面內容
  async getPageInfo (actPage) {
    // 延時 1000 毫秒
    await timeout(1000);
    let page = this.page
    await page.goto(`http://wufazhuce.com/one/${actPage}`);
    // 獲取資訊
    try {
      // 獲取文字
      let sText = await page.$eval('.one-cita', el => el.innerText);
      // 獲取圖片描述,清除空格和特殊字元 & 和 /
      let sImgName = await page.$eval('.one-imagen-leyenda', el => {
        let str = el.innerText
        str = str.replace(/^\s+|\s+$/g, '')
        str = str.replace(/\&+|\/+/g, '-')
        return str;
      });
      // 獲取圖片URL
      let sImgURL = await page.$eval('.one-imagen img', el => el.src);

      console.log('-------------------------------------------- start')
      console.log('頁面頁碼:', actPage);
      console.log('採集狀態:', '成功');
      console.log('標題句子:', sText);
      console.log('圖片描述:', sImgName);
      console.log('圖片地址:', sImgURL);
      console.log('-------------------------------------------- end')
      
      // 儲存圖片
      await request(sImgURL).pipe(fs.createWriteStream(`data/${sImgName}.png`));
    
    } catch (error) {
      console.log('-------------------------------------------- start')
      console.log('頁面頁碼:', actPage);
      console.log('採集狀態:', '失敗');
      console.log('錯誤資訊:', error)
      console.log('-------------------------------------------- end')
    }
  }
  // 關閉瀏覽器
  async closeBrowser () {
    console.log('正在關閉瀏覽器...')
    await this.browser.close()
  }
}

// 啟用爬蟲
new OnePaChong()
複製程式碼

相關文章