欢迎来到李舸的博客

如果有天你忘了努力,那我就把科比的故事讲给你听。
扩大
缩小

使用 node 写一个简单爬虫,爬取疫情数据

技术概述

  • 简单来讲,爬虫就是一个探测机器,它的基本操作就是模拟人的行为去各个网站溜达,点点按钮,查查数据,或者把看到的信息背回来。就像一只虫子在一幢楼里不知疲倦地爬来爬去。结对第二次作业中为了实现疫情统计可视化,需要爬取相关网站上的疫情数据,并显示到我们的疫情地图上,因此学习了该技术。

技术详述

  • yarn add superagent cheerio下载依赖的包,也可以通过 npm 下载

    • superagent 是个 http 方面的库,可以发起 get 或 post 请求
    • cheerio为服务器特别定制的,快速、灵活、实时的 jQuery. 用来从网页中以 css selector 取数据,使用方式跟 jquery 一样。
  • 爬取丁香园网站

    function crawlerData() {
      // superagent模拟浏览器去请求丁香园网站 获取数据
      var targetUrl = 'https://ncov.dxy.cn/ncovh5/view/pneumonia'
      superagent
        .get(targetUrl)
        .then(result => {
          // console.log(result) // 爬取回来的html字符串
        })
        .catch(err => {
          console.log(err)
        })
    }
    
  • 通过 cheerios 筛选获取数据

    //  封装eval解析js字符串函数
    let originDataObj = {}
    //  封装执行js字符串函数
    function evalJsStr() {
      if (arguments.length <= 0) return
      for (let i = 0; i < arguments.length; i++) {
        let params = arguments[i].replace(/window/gi, 'originDataObj')
        eval(params)
      }
    }
    //  获取数据
    const $ = cheerio.load(result.text)
    //  获取省
    const $provinceStr = $('#getListByCountryTypeService1').html()
    //  获取省和地级市
    const $provinceAndCityStr = $('#getAreaStat').html()
    //  统计数据
    const $getStatisticsStr = $('#getStatisticsService').html()
    //  全国所有省数据
    //  执行函数获取数据
    evalJsStr($provinceStr, $provinceAndCityStr, $getStatisticsStr)
    console.log(originDataObj)
    
  • 将爬取的 json 数据写入本地文件中存储

    fs.writeFile(path.join(__dirname, './data.json'), JSON.stringify(originDataObj), err => {
      if (err) throw err
      console.log('数据写入成功')
    })
    
  • 创建 express 服务器将爬取的数据通过接口响应

    • yarn add express下载 express
    • 新建index.js文件编写接口
       //  引入模块
       const fs = require('fs')
       const path = require('path')
       const express = require('express')
       const cors = require('cors')
       //  创建服务器应用
       const app = express()
       app.use(cors())
       //  监听请求
       app.get('/api/data', (req, res) => {
         //  读取本地数据
         fs.readFile(path.join(__dirname, './data.json'), 'utf8', (err, data) => {
           if (err) throw err
           res.send(data)
         })
         //  响应数据
       })
       //  分配端口号启动服务
       app.listen(8088, () => {
         console.log('服务启动了 http://127.0.0.1:8088')
       })
    

技术使用中遇到的问题和解决过程

  • eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。eval 存在安全问题,因为它会执行任意传给它的代码,在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 eval 函数。eval 简述

  • 浏览器请求访问时,跨源请求被拦截。在接口文件index.js监听请求时设置允许跨域

    //  监听请求
    app.all('*', function(req, response, next) {
    
      //设置允许跨域的域名,*代表允许任意域名跨域
      response.header("Access-Control-Allow-Origin", "*");
      //允许的header类型
      response.header("Access-Control-Allow-Headers", "X-Requested-With");
      //跨域允许的请求方式
      response.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
      //设置响应头信息
      response.header("X-Powered-By",' 3.2.1')
      response.header("Content-Type", "application/json;charset=utf-8");
    
      next();
      });
    
    app.get('/api/data', (req, res) => {
      // 要将爬取到的json数据返回
      fs.readFile(path.join(__dirname, './data.json'), 'utf8', (err, data) => {
        if (err) throw err
        console.log(data)
        res.send(data)
      })
    })
    

总结

  • 第一次接触爬虫技术时,我感到复杂难以理解。随着成功实现了疫情数据实时统计可视化,看着国内各地甚至国外每天的数据更新到我们的疫情地图上,让我感觉到了其实我们每个人都能在我们的能力范围内做到许多有需求、有用处的事情,来实现我们的社会责任感和使命感。仿佛我也是前线抗击疫情的一份子,这让我充满动力和成就感。

参考

posted on 2020-06-25 15:13  李舸  阅读(350)  评论(0编辑  收藏  举报

导航