Node爬虫

176 阅读3分钟

前言

最近一段时间在学习小程序,文档很长,但是对于前端开发者来说,并不是很难。然而在准备实践的时候,却犯难了。虽然只是练手,但起码要做一个有意义的东西。所以,第一时间,就想到利用爬虫来爬取自己想要的内容。在打算实践时,却也发现,由于小程序的的一些限制,要想实现我的想法,太麻烦,对于我来说,有点浪费时间。不过,既然都想到过爬虫了,就趁这次机会练练手。

通过本次的粗浅的实践,可以将爬虫的过程总结为,获取静态页面或获取接口数据 => 分析页面结构或分析接口数据 => 提取数据保存。基于Node的爬虫方式,要么是加载页面,要么是请求API,所以相对来说都很容易实现。

puppeteer

puppeteer 应该算是最简单的方式了,通过模拟用户的行为与浏览器交互,然后我们就可以分析页面抓去需要的信息。puppeteer 文档很详实,而且手把手教学,你想要的功能基本上都能在它的 github 上找到相应的例子。

puppeteer 是基于 Chromium 的,在安装 puppeteer时,会同时安装 Chromium。而因为众所周知的缘故,整个安装的过程并不是很顺利,文档里提供了不安装 Chromium 的方法,不过,我们也可以使用淘宝的镜像来加快安装时间。

npm config set puppeteer_download_host https://npm.taobao.org/mirrors

下面通过一个打卡🌰来使用 puppeteer,

const login = async () => {
  const browser = await puppeteer.launch({ headless: false });  // 默认true。置为 false,整个操作过程可视
  const page = await browser.newPage();
  await page.goto(logURL);  // 跳转目标网页logURL,默认 load 事件触发
  await page.type('#member_number', '123456')  // 输入卡号
  await page.click('#btn_member_number')  // 点击确定
  await page.waitForSelector('#check_in')  // 等待签到 Dom 渲染完成
  await page.click('#check_in')  // 点击签到按钮
  await browser.close()
}

代码流程和用户操作浏览器的流程一致,这种方式相比接下来要说的方式,可以说是傻瓜式操作了。当然 puppeteer 还可以生成截图,性能分析等。

接口请求

不管是静态还是动态页面的获取,都是通过接口请求来实现的,即通过url向后端服务请求相应的数据。按照之前的爬取流程,要做的就是数据的请求和数据的分析。如果需要保存的话,就要使用存储工具储存数据。

一般情况下,在 Node 环境中请求数据,我们会使用封装好的 htttp 库,比如 request,axios等。那么分析数据呢?这就要看情况了,如果爬取的是静态页面,返回的是 HTML,这时我们就需要借助 Cheerio 或 JSDOM 来分析页面结构。如果返回的是常见的 JSON,那就很简单了。

不过本次实践没有通过以上的方式,而是在 github 搜索相关信息时,恰巧看到了 crawler。原理上都是差不多的,而且它也集成了 Cheerio。

const Crawler = require("crawler");
const crawlerWebPage = obj => {
  let {uri, selector} = obj;  // uri 请求的uri,selector 选择器;
  crawler.direct({
    uri: uri,
    skipEventRequest: false,
    callback: function(error, response) {
        if(error) {
            console.log(error)
        } else {
          var $ = response.$;
          var content = $(selector).text();
            console.log(response.statusCode, content, uri);
        }
    }
  })

上面这个也只是 crawler 的简单用法。

node-schedule

虽然可以爬取了,但是数据并不是一成不变的,所以,更多的时候,我们需要定时重复爬取网页。 node-schedule 就是用来定义定时任务的。

const schedule = require('node-schedule');
const loginSchedule = () => {
  schedule.scheduleJob({
    start: startTime,
    endTime: endTime,
    rule: config.schedule.login[loginIndex]
  }, () => {
    let now = new Date();
    let loginLog = `${now} login successed! /r/n`;
    try {
      login();
      fs.appendFileSync('log.txt', loginLog)
    } catch (error) {
      let loginErrorLog = `${now} - ${logURL} login failed: ${error.message}! /r/n`;
      fs.appendFileSync('log.txt', loginErrorLog)
      throw error
    }
  })
}

定义好相关的规则后,任务就可以按制定的规则执行。

pm2

以上的任务是可以执行了,可是关闭了命令窗口,进程中断,那么功夫白费。这时候就需要一个工具来管理 node 进程,pm2 倒是一个好工具。pm2 不仅支持热加载,还可以监控等功能,很方便很强大。

# 安装
npm install pm2 -g

# 启动、监听 app.js
pm2 start app.js  --watch

# 监控
pm2 monit

# 终止
pm2 stop

......

debug

在写 Node 应用时,难免磕磕绊绊,学会调试也是很有必要的。本次项目很简单,所以所使用的调试技巧也很粗浅。

  • 使用 VSCode 提供的调试工具。

  • 在项目中加入 debugger,执行 node debug --inspect app.js,开启调试模式。

  • 借助其他调试工具。

over