记录一下Node结合Puppeteer爬虫经历

介绍

爬虫就是自动化浏览网站程序,收集我们所需要的数据信息,不需要人为频繁的执行一些操作。
什么是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只能爬取服务端渲染的页面,而且只能是静态页面。而Puppeteer是模拟一个浏览器,请求网站数据信息,并能够进行任何模拟的操作(点击、滑动等),并且支持跳转页面,动态的获取页面内的数据。就是模拟人浏览网站获取数据。
官方介绍: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, // 使无头浏览器可见,便于开发过程当中观察
    executablePath: chromePaths.chrome, //可执行文件的路劲,默认是使用它自带的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)') // 等待爬取内容加载完成

  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()

接下来看看我们打印出来的爬取到的数据
image.png
  • 爬虫解决登录问题
    做过爬虫的小伙伴应该都知道,很多电商网站都会做反爬,分类商品页,详情页,订单页等需要我们登录之后才可以浏览,在登录页会做一系列检测判断是否为爬虫。我们试着正常去登录。
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, // 使无头浏览器可见,便于开发过程当中观察
    executablePath: chromePaths.chrome, //可执行文件的路劲,默认是使用它自带的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可设置随机数,(大于滑动条-滑动框)就好
        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()

自信满满去跑这段代码,结果出现:


image.png

无论刷新几次,滑块都无法验证通过!!!只能卧槽感慨一下。再去看看是嘛问题,本来以为因为多次刷新,导致ip被识别出来为爬虫。但是在正常的浏览器打开淘宝登录页,使用滑块验证还是无法通过!!!再次使用卧槽感慨一下。没办法,只好再去百度,谷歌‘爸爸’那里求答案。发现是因为被淘宝反爬机制识别出了chrome webdriver,那我们只需要把无头浏览器伪装一下就可以了。
在前往页面前插入这段代码,把无头浏览器伪装一下。

await page.evaluateOnNewDocument(() => { //在每个新页面打开前执行以下脚本,否则会被识别出为chrome webdriver
    const newProto = navigator.__proto__;
    delete newProto.webdriver;  //删除navigator.webdriver字段
    navigator.__proto__ = newProto;
    window.chrome = {};  //添加window.chrome字段,为增加真实性还需向内部填充一些值
    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

小技巧

爬虫页面时,需要选中需要部分的标签,中间有一个标签错误,就会出问题,获取不到信息,然后小编写出的:

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

……
……
……

这还只是一部分,非常容易出错。然后发现了
image.png

原来是我无知了,希望能帮到小伙伴们。
小总结

以上是小编使用Puppeteer初次爬虫的经历(兴趣使然)。以前只了解python爬虫,原来大Node也可以。因为是初次尝试,所以还有很多不足,如果有什么问题,可以在评论区讨论一下,有什么错误,欢迎各位大佬指出,小弟一定更正。希望可以帮到大家,爬虫虽好,不要过度哦!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容