无处不再的广告_我的机器人现在无处可去。 无家可归。 无服务器。

无处不再的广告

我通常会关注各种网站-最新出版物,热门新报价,限时游戏和竞赛等。

其中大多数不提供“干净”的通知系统,例如RSS feed。 因此,我经常不得不刮擦他们HTML才能达到我的需求。

这意味着我经常需要运行一些自定义的字符串操作魔术来达到所需。

而且我需要它是周期性的(谁知道下一次热更新何时出现?)。

并且是自动的(我白天还有很多重要的事情要做)。

并且是远程托管的(我不想让我的笔记本电脑不间断地运行24×7,并且互联网连接不中断)。

到目前为止,我一直依靠Google Apps脚本 (最近是Google App Engine )来驱动这类自制的集成“代码段”。 但是,随着全世界都沉浸在无服务器环境中 ,我为什么不这样做呢?

因此,我开始迁移我的一个脚本,该脚本是为监视中国零售网站而编写的。 该网站偶尔会发布各种折扣优惠和季节性游戏,在这些游戏中,我可以通过日常游戏获得不错的优惠券和积分。 但是由于某种原因,该网站没有向我的电子邮件地址发送促销电子邮件,这意味着我必须不时检查一下该网站,以确保不会错过任何有趣的内容。

而且您知道演习。

我很容易忘记事情。 有时候,当我离开电脑时,也会想起提醒。 有时候,我懒得去找东西,因为我最终无新意,有75-80%的时间。 这么多借口...

此外,当您可以设置一个机器人,坐下来放松一下时,谁会在他们正确的开发人员心中想做那么无聊的事情呢?

我从AWS Lambda开始, AWS Lambda是免费的无服务器计算的明显选择。 它的非到期免费层使我每月获得320 (是, 百万 )秒的运行时间,这真是令人难以置信–我实际上可以使一个lambda永远运行,甚至更多! –调用次数超过1M (又是百万次!)。 以前,在App Script或App Engine上,我每天只有90分钟的时间,每月只有16万秒,这意味着我不得不非常谨慎地使用配额。 但是现在我可以放开恐惧,充分享受发展的自由。 与Apps Script或App Engine的框架限制相比,更不用说成熟的容器环境了。

聊够了。 让我们编码吧!

我没有采取标准的方法 ,而是从SLAppForge中选择了Sigma作为开发框架。 主要是因为它在支持外部依赖项方面享有盛誉,并代表我负责打包和部署工作-包括所有外部服务(API,表,cron和诸如此类)。

首先,我必须注册Sigma 。 尽管我可以继续使用其演示功能(黄色的大按钮),但我已经拥有一个AWS帐户和一个GitHub帐户(更不用说电子邮件地址了); 那为什么不试一试呢?

无服务器

完成注册并登录后,我看到了一个项目选择窗格,在这里我选择了一个名为site-monitor的新项目:

该应用程序运行非常快,当我点击Create Project时 ,编辑器立即弹出:

事不宜迟,我抓住了以前的Apps脚本功能的内容,并将其放入了Sigma!

let AWS = require('aws-sdk');exports.handler = function(event, context, callback) {// Here Goes NothingPROPS = PropertiesService.getScriptProperties();page = UrlFetchApp.fetch("http://www.my-favorite-site.com").getResponseText();url = page.match(/(lp|\?r=specialTopic)\/[^"]*/)[0];if (url != PROPS.getProperty("latest")) {GmailApp.sendEmail("janakaud@gmail.com", "MyFavSite Update!", url);PROPS.setProperty("latest", url);}// end of Here Goes Nothingcallback(null,'Successfully executed');
}

(我知道,我知道那是行不通的。忍受我:))

接下来的几分钟,我花了我的Apps脚本代码转换为NodeJS。 一旦将request模块添加到项目中,就不那么困难了(毕竟都是JS!):

但是我必须说我确实错过了UrlFetchApp模块熟悉的同步语法。

在App Engine下,我使用了非常简单的PropertiesService作为我的机器人的“内存”。 在Sigma(AWS)下,事情并不是那么简单。 经过一番环顾之后,我决定使用DynamoDB (尽管我仍然觉得这太过头了)。

从页面中提取URL后,我需要检查是否已将其通知给自己。 等同于在我的表(以前称为PropertiesService )中查询现有条目。 在DynamoDB-land中,这显然是一个Get Document操作,因此我尝试将DynamoDB拖入我的代码中:

删除后,DynamoDB条目将转换为一个弹出窗口,我可以在其中定义表并提供代码级参数。 希望Sigma会记住表配置,这样我就不必在我的代码中一遍又一遍地输入它。

由于DynamoDB并不是简单的键值对象,因此我花了几分钟的时间来研究如何在其中存储“值”。 最终我决定使用表格的“文档”结构

{"domain": "my-favorite-site.com","url": "{the stored URL value}"
}

在这里我可以使用每个机器人的特定domain值查询表,因此可以将表重用于不同的机器人。

在我的旧代码中,我使用GmailApp.sendEmail()调用在收到新内容时向自己发送通知。 在Sigma中,我尝试通过拖放简单电子邮件服务( SES )条目来做到这一点:

这里似乎有点打small,因为看来我需要先验证电子邮件地址,然后才能发送一些东西。 我不确定自己的骑行有多坎,,无论如何,我都输入了电子邮件地址,然后点击发送验证电子邮件

果然,我通过电子邮件收到了一个验证链接,单击该链接可以将我重定向到“验证成功”页面 。

猜猜是什么:当我切换回Sigma时,弹出窗口已更新自身,说明电子邮件已通过验证,并指导我进行下一步!

我立即填写了详细信息( 我自己而言,没有CC或BCC的主题 MyFavSite Update!Text Body @{url} (它们自己的可变语法;但我希望它是${} )):

在SES电子邮件发件人的回调中,我必须更新DynamoDB表以反映已通过电子邮件发送的新条目(因此,我不会再通过电子邮件发送它)。 就像我原来的漫游器中的PROPS.setProperty("latest", url)调用一样。

这很容易,而且拖放操作也很简单:在“ 现有表”下选择先前创建的表,然后选择domain设置为my-favorite-site.com (我的“搜索查询”;等效于"latest" ”)的"latest" 放置文档”操作 "latest"在旧BOT)和url条目集的电子邮件地址:

最终,我得到了相当不错的代码(尽管它比我亲爱的旧版Apps脚本机器人要长得多):

let AWS = require('aws-sdk');
const ses = new AWS.SES();
const ddb = new AWS.DynamoDB.DocumentClient();
const request = require("request");exports.handler = function (event, context, callback) {request.get("http://www.my-favorite-site.com",(error, response, body) => {if (!body) {throw new Error("Failed to fetch homepage!");}let urls = page.match(/(lp|\?r=specialTopic)\/[^"]*/);if (!urls) { // nothing found; no point in proceedingreturn;}let url = urls[0];ddb.get({TableName: 'site-data',Key: { 'domain': 'my-favorite-site.com' }}, function (err, data) {if (err) {throw err;} else {if (!data.Item || data.Item.url != url) {ses.sendEmail({Destination: {ToAddresses: ['janakaud@gmail.com'],CcAddresses: [],BccAddresses: []},Message: {Body: {Text: {Data: url}},Subject: {Data: 'MyFavSite Update!'}},Source: 'janakaud@gmail.com',}, function (err, data) {if (err) {throw err;}ddb.put({TableName: 'site-data',Item: { 'domain': 'my-favorite-site.com', 'url': url }}, function (err, data) {if (err) {throw err;} else {console.log("New URL saved successfully!");}});});} else {console.log("URL already sent out; ignoring");}}});});callback(null, 'Successfully executed');
}

Sigma一直试图通过提供方便的编辑帮助(代码完成,语法着色,变量建议等)来帮助我,甚至突出显示DynamoDB和SES操作并在前面显示小图标。 单击后,将显示(重新)配置弹出窗口,类似于我第一次将其拖放时得到的弹出窗口。

由于异步,基于回调的语法,我不得不在代码的“ n”位代码中多次移动。 Sigma处理得很好,在我将代码粘贴到新位置后,再过一两秒钟重新进行了突出显示。

只是为了好玩,我尝试手动编辑代码(不使用弹出窗口),很公平的是,弹出窗口理解了更改并在下次检查时进行了更新。 对于一个新手来说很整洁,他们希望无需完成文档即可完成工作。

现在,我该如何定期运行我的机器人?

Sigma在函数标题附近显示一个红色的闪电符号,并在其中突出显示event参数。 可能表明这是lambda的调用或触发点。

对。 他们的文档说的也是一样。

AWS文档和Sigma自己的 文档向我介绍了CloudWatch计划的事件触发器 ,该事件触发器可以按预定义的时间表触发lambda,例如Apps Script触发器,但功能强大得多。 更像App Engine cron表达式 。

如他们的文档所述 ,我将CloudWatch条目拖到了event变量上,并进行了如下配置:

整个event从红色变为绿色,可能表明我的触发器已成功设置。

对。 是时候测试一下了。

工具栏上有一个“ 测试 (播放)”按钮,带有一个下拉菜单以选择您的测试用例。 与Apps Script一样 ,但从某种意义上讲,它可以更好地定义调用的输入有效负载(而Apps Script只是运行没有任何输入参数的函数):

配置好测试用例并点击运行按钮后,状态栏即开始显示运行进度:

几秒钟后,一个SigmaTrail日志输出窗口自动弹出,并开始显示一些日志:

errorMessage:"RequestId: 87c59aba-8822-11e8-b912-0f46b6510aa8 Process exited before completing request"
[7/15/2018][5:00:52 PM] Updating dependencies. This might make runtime longer than usual.
[7/15/2018][5:00:55 PM] Dependencies updated.
[7/15/2018][5:00:57 PM] ReferenceError: page is not defined
at Request.request.get [as _callback] (/tmp/site-monitor/lambda.js:13:24)
at Request.self.callback (/tmp/site-monitor/node_modules/request/request.js:185:22)

糟糕,看来我弄错了变量名。

一个简单的编辑和另一个测试。

[7/15/2018][5:04:50 PM] ResourceNotFoundException: Requested resource not found
at Request.extractError (/tmp/site-monitor/node_modules/aws-sdk/lib/protocol/json.js:48:27)
at Request.callListeners (/tmp/site-monitor/node_modules/aws-sdk/lib/sequential_executor.js:105:20)

嗯,那是什么意思?

看起来这是来自AWS开发工具包本身的。

也许我拖放到应用程序中的AWS“资源”在AWS端尚不可用; 此外,许多Sigma教程在进行测试之前都提到了“部署”步骤。

哦,好,让我们尝试部署这个东西。

我希望能够进行无缝的“一键式部署”,但是当我单击“ 部署”按钮时,出现一个弹出窗口,提示我需要向GitHub进行身份验证。 Sigma可能会将我的东西保存在GitHub存储库中,然后将其用于其余的部署。

看到没有恶意,我单击了登录,并在随后的弹出窗口中授权了他们的应用。 几秒钟后,我又弹出一个窗口,要求我选择一个回购名称和一个提交消息。

我的帐户中没有回购site-monitor ,因此我很想知道Sigma会做什么。 正如我怀疑的那样,单击“ 提交”几秒钟后,另一个对话框弹出,询问我是否希望它代表我创建一个新的仓库。

Sigma非常友好,以至于它甚至提供创建私有存储库的机会。 但是可惜,我没有奢侈的东西,所以我只单击了Create Repo and Commit

从那时起,一切都变得相当自动化:在“成功完成”通知之后,有一个非常快的“构建”步骤(伴随着底部状态窗格中的进度条)。

接下来,我又弹出另一个窗口,这次是“ 变更摘要” ; 再过几秒钟后,将其填充为一种“部署摘要”:

我对底层细节不怎么感兴趣(尽管我确实cweOneAM识别为cron触发器,将siteMonitorLambda为我的机器人),所以我只是点击Execute ; 这次等待了很长的时间(伴随着另一个进度条,这次是在弹出窗口中)。

一旦达到100%,Sigma表示我的部署以CREATE_COMPLETE状态完成(听起来不错!)。

现在,让我们再次尝试测试。

"Successfully executed"
[7/15/2018][5:39:34 PM] New URL saved successfully!

好极了!

等等,如果我再次运行它,它会重新发送吗?

"Successfully executed"
[7/15/2018][5:39:41 PM] URL already sent out; ignoring

都好; 没有重复!

现在检查我的收件箱,看看Sigma是否在说真话。

最初,我有点困惑,因为我实际上没有收到电子邮件。 但是最终我发现它位于我的Spam文件夹中(可能是因为它是由第三方(AWS)发送的?),并取消了标记,因为它起到了垃圾邮件的作用。

希望我的CloudWatch触发器明天明天凌晨1点触发,如果有的话,给我带来了好消息!

总而言之,图形化IDE非常漂亮,值得同事们推荐。 除了部署时间(我认为这是无服务器应用程序,Lambda或也许是AWS的特性)之外,我几乎感觉到了家–甚至还拥有所有出色的功能-自动补全,拖放,GUI配置,测试,日志等。

是时候喝杯咖啡了,然后开始将我的其他机器人迁移到Sigma…嗯…AWS。

翻译自: https://www.javacodegeeks.com/2018/07/bots-placeless-homeless-serverless.html

无处不再的广告

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333482.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java service实例,javaweb后端实例 service

service的作用1.将前端需要的业务代码封装成接口2.将do数据封装为vo3.水平有限只知道这些下面展示的代码为将do封装为vopublic class StationService { private StationDao stationDao new StationDao(); public List listSLByYear(int year) { //创建vo链表 List list new L…

前端 JS 如何在一个页面中局部加载其它页面的数据

一个页面很大&#xff0c;可以分成多个部分&#xff0c;先把小部分的 jsp 写好之后&#xff0c;再在主页面中通过 Struts 2 标签或 ajax 请求来引入其它的 jsp 显示信息。 通过 jQuery 函数来加载其它页面的数据 <script> $(function () {$("#new").load(&qu…

switch字符串jdk_应用新的JDK 11字符串方法

switch字符串jdk在“ 使用JDK 11的Java字符串上的新方法 ”和“ String&#xff03;repeat即将加入Java&#xff1f; ”&#xff0c;我讨论了JDK 11引入Java String的六种新方法。 可用的早期访问JDK 11构建已经包含了这些新方法&#xff0c;在这篇文章中&#xff0c;我将使用…

aws lambda使用_使用AWS Lambda的CloudWatch事件通知

aws lambda使用CloudWatchEvents的主要用例是跟踪整个AWS基础架构中的更改。 当前&#xff0c;它支持跨Auto Scaling组&#xff0c;EC2&#xff0c;EBS和其他各种事件发出的事件。 为了对这些事件进行有意义的处理&#xff0c;我们需要一种消耗它们的方法。 AWS使用术语“ targ…

Struts2中的OGNL表达式和ValueStack

文章目录OGNL 是干什么用的示例代码一示例代码二使用OGNL获取JavaBean对象的属性值获取集合属性中元素的属性的值XWork 中对 OGNL 的扩展示例代码Struts2 对 OGNL 的封装OGNL 可以用在哪些地方OGNL 的结构示意图XWork 对 OGNL 改造后的结构示意图Struts 2 对 OGNL 改造后的结构…

matlab画图五角星标记,Matlab---画图线型、符号及颜色

Matlab 画图线形、颜色、数据点形状的选择1&#xff0c;线形- Solid line (default)-- Dashed line: Dotted line-. Dash-dot line2&#xff0c;颜色r Redg Greenb Bluec Cyanm Magentay Yellowk Blackw White3&#xff0c;数据点的形状 Plus signo Circle* Asterisk. Pointx C…

php 淘宝客接口开发,如何使用PHP的curl函数调用维易淘客接口

《如何使用PHP的curl函数调用维易淘客接口》要点&#xff1a;使用curl调用维易淘客接口高佣转链维易淘客接口是用GET方式调用的&#xff0c;直接用GET调用即可&#xff0c;以下用PHP为例&#xff1a;使用curl调用维易淘客接口高佣转链&#xff1a;$apihttp://api.vephp.com/hca…

querydsl 转字符串_QueryDSL中包含通配符的字符串的精确匹配

querydsl 转字符串在我们最近的一个项目中&#xff0c;我们的客户要求一个搜索字段&#xff0c;该字段可以搜索名字&#xff0c;姓氏和电子邮件地址&#xff0c;唯一的通配符是星号“ *”&#xff0c;表示部分匹配。 听起来很简单&#xff0c;但这使我们陷入了混乱。 在我们的项…

Java中,我自己定义的某个类,去实现某个接口,是否必须实现该接口的全部抽象方法呢?

不一定&#xff0c;关键要看子类是否是抽象类。 如果子类是非抽象类&#xff0c;则必须实现接口中的所有方法&#xff1b;如果子类是抽象类&#xff0c;则可以不实现接口中的所有方法&#xff0c;因为抽象类中允许有抽象方法的存在&#xff01; 一、抽象类定义 抽象类往往用…

堆栈溢出 java_堆栈溢出回答了我们所不知道的Java首要问题

堆栈溢出 java您不应该错过的堆栈溢出问题集合&#xff1a; 这不是秘密&#xff1b; 我们都使用堆栈溢出。 它拥有生命&#xff0c;宇宙和几乎所有与代码相关的答案。 该平台为开发人员&#xff0c;工程师和其他人员提供了一个找到他们所面临问题的答案的地方&#xff0c;或者…

Java 的面向接口编程

假设有这样的代码&#xff1a; F f new G(); f.do(); f.cook(); ...F 是一个接口&#xff0c;G 是 F 的一个实现类&#xff08;也叫具体类/派生类&#xff09;。 如果现在需要另外一个实现类 H 采用其他技术实现接口 F 的所有抽象方法&#xff0c;那么只要修改一条代码&…

mysql 表数据diff,mysqldiff使用笔记

背景手上有个项目&#xff0c;有三个环境:本地开发,测试环境,线上环境&#xff0c;历史原因怀疑数据库表字段可能出现不匹配&#xff0c;所以寻找合适的工具比较数据库表结构。找到了mysqldiff。准备工具正好手上有台windows机器&#xff0c;使用windows版本测试安装mysqldiff是…

java超出gc开销_通过这5个简单的技巧减少GC开销

java超出gc开销编写代码的五种简单方法&#xff0c;可以提高内存效率&#xff0c;而无需花费更多时间或降低代码可读性 垃圾回收会为您的应用程序增加多少开销&#xff1f; 您可能不知道确切的数字&#xff0c;但您确实知道总有改进的余地。 尽管自动GC是最有效的过程&#x…

JSTL(Java 标准标签库)

文章目录JSTL 简介JSTL 可以使用在哪里JSTL 使用步骤使用标签if 语句选择语句迭代遍历语句URL重写设置属性值删除属性值异常捕获导入其它 JSP 页面重定向输出指定的值JSTL 简介 Java Standard Taglib(Java 标准标签库)。 JSTL 是一种代替 JSP 中的 Java 代码的技术。sun 公司…

php hash代码下载,PHP中的哈希表 hash_insert

[php]代码库int hash_insert(HashTable *ht, char *key, void *value){// check if we need to resize the hashtableresize_hash_table_if_needed(ht); // 哈希表不固定大小&#xff0c;当插入的内容快占满哈表的存储空间// 将对哈希表进行扩容&#xff0c; 以便容纳所有的元素…

跟踪React流–将Spring Cloud Sleuth与Boot 2结合使用

Spring Cloud Sleuth在OpenZipkin Brave的基础上增加了对Spring工具的支持&#xff0c; 从而使Spring Boot应用程序的分布式跟踪变得异常简单。 这是关于使用此出色的库添加对分布式跟踪的支持所需内容的简要介绍。 考虑两个应用程序–一个使用上游服务应用程序的客户端应用程…

JDK命令之java -- 用来执行字节码文件,即用来执行Java程序

文章目录一、命令介绍二、用法格式三、常用选项四、常用选项详解-client&#xff0c;-server-hotspot-classpath,-cp-classpath-Dvalue-verbose[:class|gc|jni]-verbose:gc-verbose:jni-version-showversion-ea[:...|:] 和 -enableassertions[:...|:]-da[:...|:] 和 -disableas…

php中双引号的区别,PHP中单引号和双引号的区别

好久没有写博客了&#xff0c;都忘了积累知识啦……现在开始全新的生活&#xff0c;重拾记录的习惯。今天要写的就是PHP中单引号和双引号的区别。在PHP中&#xff0c;我们可以使用单引号或者双引号来表示字符串。不过我们作为开发者&#xff0c;应该了解其中的区别。一、字符串…

sbe 详解_内部简单二进制编码(SBE)

sbe 详解SBE是用于金融行业的非常快速的序列化库&#xff0c;在本博客中&#xff0c;我将介绍一些使其快速发展的设计选择。 序列化的全部目的是对消息进行编码和解码&#xff0c;并且有很多可用的选项&#xff0c;例如XML&#xff0c;JSON&#xff0c;Protobufer&#xff0c;…

php调用swf文件上传,swfupload-jquery-plugin AJAX+PHP 文件上传

var listitem>file.name (Math.round(file.size/1024) KB)>>>Pending;$(#log).append(listitem);$(this).swfupload(startUpload);})//绑定开始上传文件事件.bind(uploadStart, function(event, file){$(#log li#file.id).find(p.status).text(Uploading...);$(#lo…