技术
曙光很近,理想不远
因为博客的模板有一个instagram的九宫格插件,可以显示ig的图片,我觉得挺好看的,打算也整一个。不过上网搜了一下才知道,因为ig的api修改了,已经不能无限地获取图片了,需要申请api key才可以,并且这个key是有时间限制的,每隔一段时间就需要重新获取。而且考虑到我的博客是在国内主机上的,无法直接请求到ig的api,并且我不能要求每一个访客都能够访问ig(感谢伟大的防火墙),所以我需要一个中转来定时地获取ig的图片并同步到博客。
如果只是为了同步ig图片的话,重新购买国外的主机显然不经济,目前为止我也没有很多需要单独使用国外主机才能进行的骚操作,所以我想到了Amazon的serverless服务。海外区的Amazon有着一系列永久免费的套餐,其中包括了每月100万次免费的AWS lambda请求,这对于实现同步ig图片的请求足够了。
另外,为了能够简单的请求到ig的账户的发文数据,我使用了rapidapi的api接口。这个接口的免费套餐可以每个月请求100次,一天同步3次绰绰有余。
我使用了这个接口的Get account posts接口,在请求中附上要请求的ig账户的id和需要的发文数量就可以直接获取到json数据了。ig账户id可以访问
https://www.instagram.com/账户名/?__a=1
这个链接获取,虽然这个链接也可以直接获取到账户的发文,但因为这个链接是需要登录状态的,所以我们不能直接使用这个链接进行同步请求,因此我还是选择了使用rapidapi的接口。
观察一下这个接口返回的数据:
在edges里面有一个list,这个list里面的node就是每条po文的数据了。
我只想要同步一下封面的图片以供博客显示,并且能够在点击封面之后直接跳转到ig相对应的po文。观察一下ig每条po文的链接:
所以我想要同步的字段就是node里面的shortcode字段和thumbnail_src字段。
接下来我们进入海外版Amazon的控制台,注册什么的就不详细说了,地区我选择了香港,搜索Lambda进入控制面板,点击创建函数。
然后选择从头开始创作,并且填写函数名称,选择函数语言,我选择的是node.js,然后点击创建函数,一个函数就创建好了。接下来进入函数我们可以看到一个编辑器(这个要看你选择的什么语言,我一开始选择的java就不可以直接编辑代码,我觉得麻烦所以就用了node.js)。我们就可以开始编写代码了,把instagram的po文同步到自己的博客上有几个步骤呢?
分析好了之后我们就可以开始编写代码了,代码很简单,就几个post/get请求罢了,我直接把我的贴上来。
console.log('Loading function');
const http = require('https');
exports.handler = async (event, context) => {
let posts = await getPosts();
let nodes = posts.edges;
let thumbnails = [];
for (var i = 0; i < nodes.length; i++) {
let src = nodes[i].node.thumbnail_src;
let image = await getImages(src);
let shortcode = nodes[i].node.shortcode;
let filename = i+'.jpg';
let file = {
'file': image,
'filename': filename,
'shortcode': shortcode
};
thumbnails.push(file);
}
let upload = await postImage(thumbnails);
return thumbnails;
};
async function getPosts() {
return new Promise((resolve, reject) => {
const options = {
host: 'instagram40.p.rapidapi.com',
path: '/account-medias?userid=你的instagram账户id&first=请求的po文数量',
headers: {
"x-rapidapi-key": "你的key",
"x-rapidapi-host": "instagram40.p.rapidapi.com",
"useQueryString": true
},
method: 'GET'
};
console.log('request...');
const req = http.request(options, (res) => {
const chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
const body = Buffer.concat(chunks);
resolve(JSON.parse(body));
});
});
req.on('error', (e) => {
reject(e.message);
});
req.end();
});
}
async function getImages(url) {
return new Promise((resolve, reject) => {
const options = {
method: 'GET'
};
console.log('request image...', url);
const req = http.request(url,options, (res) => {
const chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
const body = Buffer.concat(chunks);
resolve(Buffer.from(body).toString('base64'));
});
});
req.on('error', (e) => {
reject(e.message);
});
req.end();
});
}
async function postImage(fileList) {
let postData = {
'fileList': fileList,
'ak': '',
};
return new Promise((resolve, reject) => {
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
};
const req = http.request('后台同步接口URL',options, (res) => {
const chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
const body = Buffer.concat(chunks);
resolve(body.toString());
});
});
req.on('error', (e) => {
reject(e.message);
});
req.write(JSON.stringify(postData));
req.end();
});
}
然后我们需要设置一下定时器,使这个同步任务自动执行。
点击配置,然后点击触发器,添加触发器,搜索CloudWatch events。
选择创建新规则,填写规则名称,规则类型选择计划表达式。你可以填写例如rate(1 day), cron(0 17 ? * MON-FRI *)的表达式,需要注意的是,这边的cron表达式是从分开始的,我当时是从秒开始,结果怎么都通不过,你可以点击这里查看语法。我选择每天凌晨1点同步。
接下来还需要配置一下超时时间,因为默认的超时时间是3秒,而我们要发送很多http请求,3秒不太够,所以我改为30秒。
进入配置-常规配置,点击编辑,然后将超时时间更改为30秒,这里你也可以分配给函数的最大内存。
保存之后,一个serverless函数就写好啦,这样就可以每天定时向博客同步ig照片了!最后放一张效果图:
暂无评论