今天在看微信小程序,数据是从网上找的API请求下来的。就想能不能把数据保存到本地来,以后没有网络也可以自己搭服务器提供数据。
说干就干,我打算用node来做。
我先是在浏览器上输入豆瓣的API地址,拉下来json数据。,我去掉了不需要的头尾,留下了中间的一个数组。因为我想保存数组中的电影信息。其它的并不需要。电影信息如下:
{
"rating": {
"max": 10,
"average": 9.6,
"stars": "50",
"min": 0
},
"genres": [
"犯罪",
"剧情"
],
"title": "肖申克的救赎",
"casts": [
{
"alt": "https://movie.douban.com/celebrity/1054521/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/17525.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/17525.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/17525.jpg"
},
"name": "蒂姆·罗宾斯",
"id": "1054521"
},
{
"alt": "https://movie.douban.com/celebrity/1054534/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/34642.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/34642.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/34642.jpg"
},
"name": "摩根·弗里曼",
"id": "1054534"
},
{
"alt": "https://movie.douban.com/celebrity/1041179/",
"avatars": {
"small": "https://img1.doubanio.com/img/celebrity/small/5837.jpg",
"large": "https://img1.doubanio.com/img/celebrity/large/5837.jpg",
"medium": "https://img1.doubanio.com/img/celebrity/medium/5837.jpg"
},
"name": "鲍勃·冈顿",
"id": "1041179"
}
],
"collect_count": 1072578,
"original_title": "The Shawshank Redemption",
"subtype": "movie",
"directors": [
{
"alt": "https://movie.douban.com/celebrity/1047973/",
"avatars": {
"small": "https://img3.doubanio.com/img/celebrity/small/230.jpg",
"large": "https://img3.doubanio.com/img/celebrity/large/230.jpg",
"medium": "https://img3.doubanio.com/img/celebrity/medium/230.jpg"
},
"name": "弗兰克·德拉邦特",
"id": "1047973"
}
],
"year": "1994",
"images": {
"small": "https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p480747492.webp",
"large": "https://img3.doubanio.com/view/movie_poster_cover/lpst/public/p480747492.webp",
"medium": "https://img3.doubanio.com/view/movie_poster_cover/spst/public/p480747492.webp"
},
"alt": "https://movie.douban.com/subject/1292052/",
"id": "1292052"
}
其中有很多图片,我打算将他们全部下载到本地文件夹中。我的服务器结构如下:
app.js是服务器文件,处理不同路由的中间件都写在route文件夹中。图片就下载到public文件夹中的image下。根据豆瓣的图片地址,建立了对应的文件夹:
以下js逻辑代码中:
loadImageFromJson
该函数的功能是接收一个数组json数据的文件路径,就可以将该json中包含的所有的图片路径全部下载到public中images下对应的文件夹中。其中用到了一个异步下载第三方模块:bagpipe
var fs = require("fs");
var http = require('http');
var url = require('url');
var path = require('path');
var Bagpipe = require('bagpipe');
var request = require('request');
var Files = [];
var Type = "";
//接收一个json文件,以及存放图片的路径
//解析出里面的所有图片的连接,
//并下载所有图片到当前目录下的image文件夹中
function loadFilesFromJson(jsonURL, destDir, fileType) {
//读取文件中的所有的图片链接
fs.readFile(jsonURL, "utf-8", function(err, doc) {
//将读取到的普通字符串转换为json对象,
var jsonObj = JSON.parse(doc);
Type = fileType;
//迭代出对象中包含的url
itrator(jsonObj);
if (Files.length > 0) {
loadFilesFromNet(Files, destDir);
}
});
}
//遍历json对象的所有属性,找出所有的图片链接
function itrator(obj) {
for (var item in obj) {
if (obj[item] instanceof Object) {
itrator(obj[item]);
} else {
if ((typeof obj[item]).toLowerCase() == "string" && obj[item].indexOf(Type) > -1) {
Files.push(obj[item]);
}
}
}
}
function loadFilesFromNet(Files, destDir) {
//设置并发的任务个数
var bagpipe = new Bagpipe(10);
//真正下载图片文件的地方
var downloadFiles = function(src, dest, callback) {
request.head(src, function(err, res, body) {
if (src) {
request(src).pipe(fs.createWriteStream(dest)).on('close', function() {
//回调函数,打印出文件名
callback(null, dest);
});
}
});
};
//用for循环开启每一次下载
for (var i = 0; i < Files.length; i++) {
try {
//根据url自动生成文件夹结构
createDirAccordingToUrl(Files[i], destDir);
//下载的文件的保存路径
var destFile = path.resolve(destDir, Files[i].substr(Files[i].indexOf(".com/") + 5));
bagpipe.push(downloadFiles, Files[i], destFile, function(err, data) {
//打印的是下载成功的文件路径
console.log(data);
});
} catch (e) {
console.log(e);
}
}
}
function createDirAccordingToUrl(originurl, dest) {
var urlobj = url.parse(originurl);
//将path用"/"分割为数组
var dirs = urlobj.path.split('/');
var dir = dest;
for (var i = 0; i < dirs.length - 1; i++) {
dir += "/" + dirs[i];
console.log(dir);
//判断是否存在,且是否为文件夹
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
//如果该层文件夹存在,就继续判断下一层
} else {
console.log("文件夹不存在,创建:" + dir);
fs.mkdirSync(dir);
}
}
}
exports.loadFilesFromJson = loadFilesFromJson;
//传入源json文件,下载的文件存放的文件夹路径,以及下载的文件类型
loadFilesFromJson("./zhihuhot.json", __dirname + "/public/zhihu", ".jpg");
用以上代码就可以下载图片到本地了。但是这些数据还应该导入到数据库。我使用的是mongodb数据库,直接在命令行中输入:
mongoimport -d 数据库名 -c 集合名 文件名
即可将json文件中的对象都导入数据库。十分方便。
这里要注意一点:
导入的json文件中不能是刚才用过的数组json文件,需要做简单修改:先将数组的 []符号 删掉,然后对象之间的逗号也要删掉。最后就像这样:
{} {} {} {}
导入数据之前,记得json文件中图片的地址改成本地的地址。
因为我是打算在本地搭建服务器使用,所以我将豆瓣的图片地址域名全部改成了这样:
http://127.0.0.1:8080
我的服务器app.js文件如下:
var route = require("./route/route.js");
var express = require("express");
var app = express();
app.use(express.static('./public'));
//获取电影详情
app.get("/movie/detail/:movieid", route.detailRoute);
//获取即将上映的电影
app.get("/movie/coming", route.comingRoute);
//获取排行250电影
app.get("/movie/top250/:start/:count", route.top100);
app.listen(8080);
我的路由文件如下:
var MongoClient = require('mongodb').MongoClient;
//mongo服务器地址
var URL = 'mongodb://localhost:27017/farsight';
var detailRoute = function(req, res) {
console.log("detail");
//连接数据库farsight,如果不存在,就创建它,并将其对象返回
MongoClient.connect(URL, function(err, db) {
if (err) {
console.error(err); //输出错误信息
return;
} else {
//获取集合对象
var collection = db.collection('moviedetail');
//查询数据
collection.find({}).limit().skip().toArray(function(err, docs) {
if (err) throw err;
else {
console.log(docs);
if (docs.length == 0) {
res.send();
} else {
res.send(docs);
}
db.close();
}
});
}
});
}
var hotplaying = function(req, res) {
console.log("hotplaying");
//连接数据库farsight,如果不存在,就创建它,并将其对象返回
MongoClient.connect(URL, function(err, db) {
if (err) {
console.error(err); //输出错误信息
return;
} else {
//获取集合对象
var collection = db.collection('hotplaying');
//查询数据
collection.find({}).toArray(function(err, docs) {
if (err) throw err;
else {
console.log(docs);
if (docs.length == 0) {
res.send();
} else {
res.send(docs);
}
db.close();
}
});
}
});
}
//即将上映
var comingRoute = function(req, res) {
//连接数据库farsight,如果不存在,就创建它,并将其对象返回
MongoClient.connect(URL, function(err, db) {
if (err) {
console.error(err); //输出错误信息
return;
} else {
//获取集合对象
var collection = db.collection('coming');
//查询数据
collection.find({}).toArray(function(err, docs) {
if (err) throw err;
else {
if (docs.length == 0) {
res.send();
} else {
console.log("查到了" + docs.length);
// var jsonObj = JSON.parse(docs);
res.send(docs);
}
db.close();
}
});
}
});
}
//电影排行
var top100 = function(req, res) {
var count = req.params.count;
var start = req.params.start;
//连接数据库farsight,如果不存在,就创建它,并将其对象返回
MongoClient.connect(URL, function(err, db) {
if (err) {
console.error(err); //输出错误信息
return;
} else {
//获取集合对象
var collection = db.collection('to100');
//查询数据
collection.find({}).limit(count).skip(start).toArray(function(err, docs) {
if (err) throw err;
else {
console.log(docs);
if (docs.length == 0) {
res.send();
} else {
res.send(docs);
}
db.close();
}
});
}
});
}
exports.detailRoute = detailRoute;
exports.hotplaying = hotplaying;
exports.comingRoute = comingRoute;
exports.top100 = top100;
数据准备完成。就可以在浏览器中访问本地数据库保存的数据了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。