Node+ts+mongodb 爬取接口数据存入数据库

1,953

写在前面

个人因为写学校的毕业设计项目,作为前端,也是第一次接触用node写后端接口以及爬取数据,一开始本来是打算爬取页面的数据,但是发现很多页面并未没有独一无二的id或者class,导致爬取数据的难度系数很高,刚好爬取数据的网页的接口是开放的,所以打算换个方式获取数据----爬取接口(当然,也可以手动导入数据库,但是由于本人比较懒,以及毕设的数据比较多,想着手动的成本比较大,自己也想多学习知识,就开始动手各种网上查资料......)话不多说,进入正题

爬取的数据格式

{
  IsSuccess: true,
  Data: [
    { os: 'android', count: 2102 },
    { os: 'ios', count: 276 },
    { os: 'win10', count: 42 },
    { os: 'win7', count: 29 },
    { os: 'mac', count: 15 },
    { os: 'Others', count: 14 }
  ]
}

🔗连接数据库

  • 首先安装mongodb数据库,网上有教程 www.runoob.com/mongodb/mon…
  • 安装依赖 npm install mongoose
  • 创建一个config文件夹(我这里把数据库的连接,和数据库的地址分开了)

  • config.ts 文件 由于mongodb初始化就是不需要密码的,我在本地跑的,也就没有设置密码,如果是想部署在服务器上跑,则需要设置账号密码
// 数据库地址: 'mongodb://用户名:密码@ip地址:端口号/数据库';

module.exports = {
  mongodb:'mongodb://127.0.0.1:27017/analyst'
}
  • mongoose.ts
// 用于连接数据库并且定义schema和model
const mongoose = require('mongoose');
const config = require('./config');

const mongooseData = () => {
  mongoose.connect(config.mongodb, { useNewUrlParser: true, useUnifiedTopology: true }, (err) => {
    if (err) {
      throw err;
    } else {
      console.log("MongoDB连接成功!")
    }
  });//连接数据库
}

export default mongooseData;

确保数据库是开启的,只要执行 mongooseData() 的方法就可以进行连接

创建数据库的 model 和 schema

model

  • TestModel.ts 因为爬取的接口数据比较简单
const mongoose = require('mongoose');
const Schema = mongoose.Schema

// 创建schema
// @ts-ignore
export const TestSchema = new Schema({
  os: String,
  count: Number
})

  • TestModel.ts
import { TestSchema } from '../schemas/TestSchema';
const mongoose = require('mongoose');


//创建model,这个地方的test对应mongodb数据库中test的conllection。
export const Test = mongoose.model('test', TestSchema);

封装数据创建方法

mongoose 有自带的 Model.create() 方法往数据库中插入数据,但是为了方便我后期毕设的写接口,我把增删查改都封装成一个单独的方法,避免代码冗余

// 往model 里面插入数据
// model -> 数据库的表 import { Test } from '../../db/models/TestModel'; // 引入模型

// param 是插入的数据
// callback是一个回调函数
export const Create = (model, param,callback) => {
  model.create(param, (err, data) => {
    if (err) throw err;
    if (data) {
      const req = {
        data: data
      }
      callback(req)
    } else {
      const req = {
        msg: '创建失败',
        error: '34000'
      }
      callback(req)
    }
  })
}

爬取接口方法

为了便于分辨请求的方法,我也统一封装好了一个请求方法

const request = require("request");//request请求库

/*
* baseUrl -> 爬取接口的url
* method  -> 接口请求的方法
* params  -> 除get外的请求参数,如果是get 方法在url上拼接就好了
* callBack -> 请求完成的回调
*/
export const crawlerPostFun = (baseUrl, method, params, callBack) => {
  request({
    url: baseUrl,//你要请求的地址
    method: method,//请求方法 post get
    json: true,
    headers: {
      "content-type": "application/json; charset=utf-8",
      "Access-Control-Allow-Methods": 'POST,GET,OPTIONS',
    },
    body: params,//这里是post 传的参数 如果是get 方法在url上拼接就好了
  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      callBack(body);
    }
  })

}

爬取核心接口

说了那么多,核心代码来了,现在用封装的各种方法来爬取接口数据了

import mongooseData from '../db/config/mongoose';
import { Test } from '../db/models/TestModel';
import { Create } from './utils';
import { crawlerPostFun } from './utils/crawler';

mongooseData(); // 连接数据库

// 爬取数据后的回调方法
// value就是接口执行后获取到的数据
const test = (value) => {
  console.log('----value',value)
  if(value){
    const rows = value.Data;
    rows.forEach((item) => {
      Create(Test, {
        os: item.os,
        count: item.count,
      }, (res) => {
       //  存入数据库的回调
        console.log('-----res',res);

      })
    })
  }
}

crawlerPostFun("https://backsite.hubing.online/Monitor/OsStatis","POST",{
  "TimeQuantum": 4,
  "appKey": "5ea9a55e5b0dd76c634bed78",
  "eTime": "",
  "sTime": ""
},test)

  • 执行完这个文件后,控制台打印的数据

  • 此时数据库

总结

一开始运行成功,但是爬到的数据一直为空,排查到的问题就是request的post请求body参数没有传给服务端,后面才发现是没有允许post的请求方法,所以一定要注意请求头head里面的属性。