Node.js是一个Javascript运行环境,对于我这种前端出身的小白而言是涉及后端学习的最快的路径。所以我就尝试用node做个简单的爬虫去获取第三方开放信息的网页存入自己数据库的demo(不建议大家去做爬政府以及敏感网站)。为了能让所有人都能看明白我尽量从0开始搭建,如果只想看爬虫代码建议直接翻到最后。 我这里用了最常规的开发方式基于express+mysql开发, 但是如果大家用于公司产品开发我还是推荐用egg.js或者nest.js 简直爽的飞起。废话不多说看栗子:
1.目录结构
既然是demo那就简单来写在根目录下新起一个server.js文件可以参考我的目录结构:
2.服务配置
在server.js里面引用express并监听端口服务:
const express = require('express')
const app = express()
const server = app.listen(8888, (res) => {
console.log("服务器已启动" + 8888)
})
这样一个简单的express服务就写好了,如果我们需要映射前端的静态页面可以利用静态文件托管去把html文件映射出来
const express = require('express')
const app = express()
app.use(express.static('dist')); //静态托管
const server = app.listen(8888, (res) => {
console.log("服务器已启动" + 8888)
})
我的dist目录是vue项目打包出来的, dist目录下需要有index.html。 如果想自定义设置可以把静态文件托管代码改为app.use(express.static(__dirname + '/自己的html相对路径.html'))
这样在控制台输入命令node server.js启动服务你的静态页就会被映射到http://localhost:8888/
3.接口配置
既然服务已经启动了我们就配置个简单的get接口
如果是post需要安装body-parser插件, Express 依赖 bodyParser 对请求的包体进行解析,默认支持:application/json, application/x-www-form-urlencoded, multipart/form-data
const express = require('express')
const bodyParser = require('body-parser') //post请求需要引入中间件
const app = express()
app.use(express.static('dist')); //静态托管
app.get('/testGet', (req, res) => { //get接口
res.status(200)
const responseData = {
statusCode: 200,
body: [{aa:1},{bb:2}]
}
res.send(responseData)
})
app.post('/testPost', function (req, res) { //post接口
console.log(req.body);
res.send(req.body);
});
const server = app.listen(8888, (res) => {
console.log("服务器已启动" + 8888)
})
4.mysql配置
使用mysql前提是你本地已经安装了(或者链接远程数据库也行) 不懂的可以移步菜鸟教程https://www.runoob.com/mysql/mysql-install.html 。如果你已经安装好数据库 那么打开控制台npm i mysql 安装mysql包 (切记mysql包不是mysql只是用于能操作数据库的包文件 所以还是需要先安装数据库才能操作)完整代码如下:
const express = require('express')
const bodyParser = require('body-parser') //post请求需要引入中间件
const mysql = require('mysql') // 引入数据库包
const app = express()
app.use(express.static('dist')); //静态托管
app.get('/testGet', (req, res) => { //get接口
res.status(200)
const responseData = {
statusCode: 200,
body: [{aa:1},{bb:2}]
}
res.send(responseData)
})
app.post('/testPost', function (req, res) { //post接口
console.log(req.body);
res.send(req.body);
});
/**********************链接数据库*************************/
//创建连接
const db = mysql.createConnection({
host: '你的ip',
user: 'root',
port: '3306',
password: '123456', //密码
database: 'nodemysql' // 这里等数据库创建之后放开就可以
})
//connect 连接数据库
db.connect(function (err) {
if (err) throw err;
console.log('mysql connected success')
})
//创建表
app.get("/user", (req, res) => { // 访问该地址 user会返回send内容 也可以Navicat 里直接创建表
let sql = "CREATE TABLE video_list(id int AUTO_INCREMENT,title VARCHAR(255),body VARCHAR(255),PRIMARY KEY(id),url VARCHAR(255),img VARCHAR(255))"
db.query(sql, (err, result) => {
if (err) throw err;
res.send('user表已经建立')
})
})
/**********************插入数据*************************/
let addSqlCount = (_title, _url, _img) => { //调用addSqlCount 函数往user表中插入数据
var insertSqlStr = 'INSERT INTO user(id,title,body,url,img) VALUES(0,?,?,?,?)';
var addSqlParams = [_title, '', _url, _img];
db.query(insertSqlStr, addSqlParams, function (err, results, fields) {
if (err) {
console.log(err);
} else {
// console.log(results);
}
})
}
const server = app.listen(8888, (res) => {
console.log("服务器已启动" + 8888)
})
5.定时任务
既然引入数据库 那么想如果想定时跑脚本插入数据怎么办 这时候需要定时任务去定时插入数据
npm i node-schedule 文件中 加入const schedule = require('node-schedule');
//每天的凌晨1点1分30秒触发
schedule.scheduleJob('30 1 1 * * *', () => {
addSqlCount (_title, _url, _img) //插入到数据库中
});
5.请求转发
服务端请求第三方服务器这时候需要安装request 包用于请求第三方 这里举例的是get请求 如果需要post可以参考如下代码:
request.post({url:'https://jsonplaceholder.typicode.com/posts',formData:{aa:2,bb:1}},(err,res,body)=>{
console.log(res);
})
如果想爬取别人页面可以装 cheerio 抓取获取的内容(类似jquery)按照jquery方法去获取页面元素。
整理一下代码 我把完整代码贴在下面(会有不少重复代码 但是方便大家黏贴复制)
const express = require('express')
const bodyParser = require('body-parser') //post请求需要引入中间件
var request = require('request') //服务端请求
const mysql = require('mysql') // 引入数据库包
const schedule = require('node-schedule'); //定时任务
const cheerio = require('cheerio') //抓取获取的内容(类似jquery)
const app = express()
app.use(express.static('dist')); //静态托管
app.get('/testGet', (req, res) => { //get接口
res.status(200)
const responseData = {
statusCode: 200,
body: [{aa:1},{bb:2}]
}
res.send(responseData)
})
app.post('/testPost', function (req, res) { //post接口
res.send(req.body);
});
const scheduleCronstyle = () => { //定时任务
//每天的凌晨1点1分30秒触发
schedule.scheduleJob('30 1 1 * * *', () => {
//定时任务插入你所需要的数据
const url = `${videoHttp}/`
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
//cheerio 类似于jqyery 用于在服务的操作dom
var $ = cheerio.load(response.body)
//把拿到的数据塞入数据库
addSqlCount(_title, _url, _img)
}
});
});
}
scheduleCronstyle();
/**********************链接数据库*************************/
//创建连接
const db = mysql.createConnection({
host: '你的ip',
user: 'root',
port: '3306',
password: 'xxxxxx', //密码
database: '数据库库名' // 这里等数据库创建之后放开就可以
})
//connect 连接数据库
db.connect(function (err) {
if (err) throw err;
console.log('mysql connected success')
})
//创建表
app.get("/user", (req, res) => { // 访问该地址 user会返回send内容 也可以Navicat 里直接创建表
let sql = "CREATE TABLE video_list(id int AUTO_INCREMENT,title VARCHAR(255),body VARCHAR(255),PRIMARY KEY(id),url VARCHAR(255),img VARCHAR(255))"
db.query(sql, (err, result) => {
if (err) throw err;
res.send('user表已经建立')
})
})
/**********************插入数据*************************/
let addSqlCount = (_title, _url, _img) => { //调用addSqlCount 函数往user表中插入数据
var insertSqlStr = 'INSERT INTO user(id,title,body,url,img) VALUES(0,?,?,?,?)';
var addSqlParams = [_title, '', _url, _img];
db.query(insertSqlStr, addSqlParams, function (err, results, fields) {
if (err) {
console.log(err);
} else {
// console.log(results);
}
})
}
const server = app.listen(8888, (res) => {
console.log("服务器已启动" + 8888)
})