記錄一下Node結(jié)合Puppeteer爬蟲經(jīng)歷

介紹

爬蟲就是自動化瀏覽網(wǎng)站程序判哥,收集我們所需要的數(shù)據(jù)信息,不需要人為頻繁的執(zhí)行一些操作挺身。
什么是Puppeteer锌仅?

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

Puppeteer是一個Node庫热芹,它提供了一個高級API來通過DevTools控制Chrome或Chromium。Puppeteer默認運行無頭伊脓,但可以配置為(有頭)Chrome或Chromium报腔。

Puppeteer是怎么爬的呢?

使用Node爬蟲還可以采用cheerio來爬取纤房,但是cheerio只能爬取服務(wù)端渲染的頁面翻诉,而且只能是靜態(tài)頁面。而Puppeteer是模擬一個瀏覽器剑令,請求網(wǎng)站數(shù)據(jù)信息拄查,并能夠進行任何模擬的操作(點擊、滑動等),并且支持跳轉(zhuǎn)頁面碍脏,動態(tài)的獲取頁面內(nèi)的數(shù)據(jù)。就是模擬人瀏覽網(wǎng)站獲取數(shù)據(jù)役拴。
官方介紹:Puppeteer官方地址
PuppeteerAPI介紹:PuppeteerAPI钾埂,這個需要看下褥紫。

實踐
  • 簡單爬取一個頁面(以淘寶首頁為例)
const chromePaths = require('chrome-paths');
const puppeteer = require('puppeteer-core');
//自動滾動請求
async function autoScroll(page) {
  await page.evaluate(async () => {
    await new Promise((resolve, reject) => {
      var totalHeight = 0;
      var distance = 100;
      var timer = setInterval(() => {
        var scrollHeight = document.body.scrollHeight;
        window.scrollBy(0, distance);
        totalHeight += distance;
        if (totalHeight >= scrollHeight) {
          clearInterval(timer);
          resolve();
        }
      }, 100);
    });
  });
}
async function main() {
  const browser = await puppeteer.launch({ //啟動配置
    headless: false, // 使無頭瀏覽器可見髓考,便于開發(fā)過程當(dāng)中觀察
    executablePath: chromePaths.chrome, //可執(zhí)行文件的路勁,默認是使用它自帶的chrome webdriver儡炼,chrome-paths.chrome會返回本機chrome地址
    ignoreDefaultArgs: ["--enable-automation"],
  });
  const page = await browser.newPage();//打開新的空白頁

  await page.goto('https://www.taobao.com/')//填寫前往頁面地址

  await page.waitForSelector('.taobao') // 等待首頁加載出來

  await autoScroll(page); // 滾到到底部(高度可以自己計算)查蓉,保證爬取部分全部加載

  await page.waitForSelector('.taobao>div:nth-child(9)') // 等待爬取內(nèi)容加載完成

  const result = await page.evaluate( () => {
    let arrList = [];
    const itemList = document.querySelectorAll("body > div.layer.clearfix > div > div > div > ul > a");
    for (var element of itemList) {
      const List = {};
      const title = element.querySelector('.info>h4').innerText
      List.title = title;
      arrList.push(List);
    }
    return arrList
  });
  console.log(result)
}
main()

接下來看看我們打印出來的爬取到的數(shù)據(jù)
image.png
  • 爬蟲解決登錄問題
    做過爬蟲的小伙伴應(yīng)該都知道奶是,很多電商網(wǎng)站都會做反爬,分類商品頁秆麸,詳情頁及汉,訂單頁等需要我們登錄之后才可以瀏覽坷随,在登錄頁會做一系列檢測判斷是否為爬蟲。我們試著正常去登錄缸匪。
const chromePaths = require('chrome-paths');
const puppeteer = require('puppeteer-core');
//滑塊滑動方法
async function move(page, initialX, initialY, xlength = 0, ylength = 0) {
  const mouse = page.mouse
  await mouse.move(initialX, initialY)
  await mouse.down()
  await mouse.move(initialX + xlength, initialY + ylength, { steps: 20 })
  await page.waitForTimeout(2000)
  await mouse.up()
}
async function main() {
  const browser = await puppeteer.launch({ //啟動配置
    headless: false, // 使無頭瀏覽器可見类溢,便于開發(fā)過程當(dāng)中觀察
    executablePath: chromePaths.chrome, //可執(zhí)行文件的路勁露懒,默認是使用它自帶的chrome webdriver懈词,chrome-paths.chrome會返回本機chrome地址
    ignoreDefaultArgs: ["--enable-automation"],
  });
  const page = await browser.newPage();//打開新的空白頁
 
  await page.goto('https://login.taobao.com/member/login.jhtml?spm=a21bo.jianhua.754894437.1.5af911d913DtRD&f=top&redirectURL=https%3A%2F%2Fwww.taobao.com%2F')//填寫前往頁面

  //等待登錄表單加載出來
  await page.waitForSelector("#login-form") 

  // 填充賬號密碼
  await page.type('#fm-login-id', '*******', { delay: 50 }); 
  await page.type('#fm-login-password', '******', { delay: 50 });

  // 判斷是否需要滑塊驗證
  const isShowSlider = await page.$eval("#login-form > div.fm-field.baxia-container-wrapper > div.baxia-container.tb-login", el=>window.getComputedStyle(el).display != 'none');
  if (isShowSlider) {
    // 獲取滑塊iframe
    const frame = await page.frames().find(frame => !!~frame.url().search("login.taobao.com//newlogin/account/check.do/"))
    // 獲取iframe中的滑塊
    const verifyBlock = await frame.$('#nc_1_n1z');
    if (verifyBlock) {
      const box = await verifyBlock.boundingBox(); //boundingBox獲取滑塊的位置
      const initialX = Math.floor(box.x + box.width / 2);
      const initialY = Math.floor(box.y + box.height / 2);
      for (let i = 0; i < 4; i++) {
        await page.waitForTimeout(1000)
        move(page, initialX, initialY, 310)  //自定義的move方法,310可設(shè)置隨機數(shù)坎弯,(大于滑動條-滑動框)就好
        await page.waitForTimeout(1000)
        const errEl = await frame.$('#nocaptcha > div > span');
        if (errEl) {
          //出錯译暂, 將錯誤重置
          console.log("登錄失敗")
          await frame.click('#nocaptcha > div > span > a')
          await frame.waitForSelector('#nc_1_n1z') 
        } else {
          console.log("登錄成功")
          let slideEl = await frame.$('#nocaptcha > div')
          if (!slideEl) {
            //即沒有錯誤秧秉, 也沒有滑塊
            break
          }
        }
      }
    }
  }
await page.click('#login-form > div.fm-btn > button', { delay: 50 }) //登錄
}
main()

自信滿滿去跑這段代碼,結(jié)果出現(xiàn):


image.png

無論刷新幾次,滑塊都無法驗證通過@省L吠!只能臥槽感慨一下劫乱。再去看看是嘛問題锥涕,本來以為因為多次刷新层坠,導(dǎo)致ip被識別出來為爬蟲。但是在正常的瀏覽器打開淘寶登錄頁破花,使用滑塊驗證還是無法通過W俊!舰绘!再次使用臥槽感慨一下。沒辦法叉橱,只好再去百度者蠕,谷歌‘爸爸’那里求答案。發(fā)現(xiàn)是因為被淘寶反爬機制識別出了chrome webdriver粪小,那我們只需要把無頭瀏覽器偽裝一下就可以了抡句。
在前往頁面前插入這段代碼,把無頭瀏覽器偽裝一下逞壁。

await page.evaluateOnNewDocument(() => { //在每個新頁面打開前執(zhí)行以下腳本锐锣,否則會被識別出為chrome webdriver
    const newProto = navigator.__proto__;
    delete newProto.webdriver;  //刪除navigator.webdriver字段
    navigator.__proto__ = newProto;
    window.chrome = {};  //添加window.chrome字段雕憔,為增加真實性還需向內(nèi)部填充一些值
    window.chrome.app = {"InstallState":"hehe", "RunningState":"haha", "getDetails":"xixi", "getIsInstalled":"ohno"};
    window.chrome.csi = function(){};
    window.chrome.loadTimes = function(){};
    window.chrome.runtime = function(){};
    Object.defineProperty(navigator, 'userAgent', {  //userAgent在無頭模式下有headless字樣,所以需覆寫
        get: () => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36",
    });
    Object.defineProperty(navigator, 'plugins', {  //偽裝真實的插件信息
        get: () => [{"description": "Portable Document Format",
                    "filename": "internal-pdf-viewer",
                    "length": 1,
                    "name": "Chrome PDF Plugin"}]
    });
    Object.defineProperty(navigator, 'languages', { //添加語言
        get: () => ["zh-CN", "zh", "en"],
    });
    const originalQuery = window.navigator.permissions.query; //notification偽裝
    window.navigator.permissions.query = (parameters) => (
    parameters.name === 'notifications' ?
      Promise.resolve({ state: Notification.permission }) :
      originalQuery(parameters)
    );
  })

再試一下,Nice琉苇,不需要滑塊驗證就可以登錄,完全模擬了人為操作趁冈。
借鑒地址:https://www.cnblogs.com/qjfoidnh/p/12779265.html

小技巧

爬蟲頁面時拜马,需要選中需要部分的標(biāo)簽俩莽,中間有一個標(biāo)簽錯誤,就會出問題取刃,獲取不到信息,然后小編寫出的:

#page>div:nth-child(2)>div:nth-child(3)>div>div>div>.login-content>.login-password>form

……
……
……

這還只是一部分坯辩,非常容易出錯崩侠。然后發(fā)現(xiàn)了
image.png

原來是我無知了却音,希望能幫到小伙伴們。
小總結(jié)

以上是小編使用Puppeteer初次爬蟲的經(jīng)歷(興趣使然)系瓢。以前只了解python爬蟲夷陋,原來大Node也可以。因為是初次嘗試清蚀,所以還有很多不足爹谭,如果有什么問題榛搔,可以在評論區(qū)討論一下践惑,有什么錯誤,歡迎各位大佬指出凉袱,小弟一定更正侦铜。希望可以幫到大家,爬蟲雖好涤躲,不要過度哦贡未!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市害幅,隨后出現(xiàn)的幾起案子岂昭,更是在濱河造成了極大的恐慌,老刑警劉巖叼风,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件无宿,死亡現(xiàn)場離奇詭異枢里,居然都是意外死亡,警方通過查閱死者的電腦和手機彬碱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門巷疼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灵奖,“玉大人,你說我怎么就攤上這事骡尽∩帽啵” “怎么了爱态?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長故河。 經(jīng)常有香客問我吆豹,道長凑阶,這世上最難降的妖魔是什么姨俩? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上洁闰,老公的妹妹穿的比我還像新娘襟雷。我一直安慰自己咧虎,他們只是感情好征唬,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布善镰。 她就那樣靜靜地躺著熏兄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上防嗡,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音钢属,去河邊找鬼酷师。 笑死,一個胖子當(dāng)著我的面吹牛串前,可吹牛的內(nèi)容都是我干的玩荠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼匆骗,長吁一口氣:“原來是場噩夢啊……” “哼盟广!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起桨武,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤七咧,失蹤者是張志新(化名)和其女友劉穎蛉顽,沒想到半個月后悼粮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翘地,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡衙耕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年昧穿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片时鸵。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖厅瞎,靈堂內(nèi)的尸體忽然破棺而出饰潜,到底是詐尸還是另有隱情,我是刑警寧澤和簸,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布彭雾,位于F島的核電站,受9級特大地震影響比搭,放射性物質(zhì)發(fā)生泄漏冠跷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一身诺、第九天 我趴在偏房一處隱蔽的房頂上張望蜜托。 院中可真熱鬧,春花似錦霉赡、人聲如沸橄务。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜂挪。三九已至,卻和暖如春嗓化,著一層夾襖步出監(jiān)牢的瞬間棠涮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工刺覆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留严肪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像驳糯,于是被迫代替她去往敵國和親篇梭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容