写在前面
个人因为写学校的毕业设计项目,作为前端,也是第一次接触用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
里面的属性。