利用Amazon的lambda进行instagram的图片同步显示到博客中

  • Share this:
post-title

因为博客的模板有一个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的接口。

观察一下这个接口返回的数据:

接口返回数据.png

在edges里面有一个list,这个list里面的node就是每条po文的数据了。

我只想要同步一下封面的图片以供博客显示,并且能够在点击封面之后直接跳转到ig相对应的po文。观察一下ig每条po文的链接:

ig的po文链接.png

不难发现我们要想直接跳转到相应的po文,需要的其实就是 “https://www.instagram.com/p/”后面的一串字符串了,这串字符串对应的就是node里面的shortcode字段:
需要的字段.png

所以我想要同步的字段就是node里面的shortcode字段和thumbnail_src字段。

接下来我们进入海外版Amazon的控制台,注册什么的就不详细说了,地区我选择了香港,搜索Lambda进入控制面板,点击创建函数。

lambda控制面板.png

然后选择从头开始创作,并且填写函数名称,选择函数语言,我选择的是node.js,然后点击创建函数,一个函数就创建好了。接下来进入函数我们可以看到一个编辑器(这个要看你选择的什么语言,我一开始选择的java就不可以直接编辑代码,我觉得麻烦所以就用了node.js)。我们就可以开始编写代码了,把instagram的po文同步到自己的博客上有几个步骤呢?

  1. 定时触发同步任务。
  2. 向api请求账户po文数据。
  3. 分析po文数据,获取封面图片。
  4. 把获取到的封面和shortcode一起发送到博客的接口。
  5. 博客比较有没有新的po文,有的话就保存下来。
  6. 访问博客时直接显示保存下来的图片,用户点击图片时跳转到instagram相应的页面。

分析好了之后我们就可以开始编写代码了,代码很简单,就几个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。

进入触发器.png

选择创建新规则,填写规则名称,规则类型选择计划表达式。你可以填写例如rate(1 day), cron(0 17 ? * MON-FRI *)的表达式,需要注意的是,这边的cron表达式是从分开始的,我当时是从秒开始,结果怎么都通不过,你可以点击这里查看语法。我选择每天凌晨1点同步。

触发器配置.png

接下来还需要配置一下超时时间,因为默认的超时时间是3秒,而我们要发送很多http请求,3秒不太够,所以我改为30秒。

超时配置.png


进入配置-常规配置,点击编辑,然后将超时时间更改为30秒,这里你也可以分配给函数的最大内存。

保存之后,一个serverless函数就写好啦,这样就可以每天定时向博客同步ig照片了!最后放一张效果图:

ig效果.png
Comments

暂无评论

Leave a Reply
清除