1 はじめ
何か自分の欲しい情報を定刻に毎日配信してくれるものはないかな~
そうだ作ろう、という感じでスタート
構成
ざっくり
CloudWatch Eventsで定刻にLambdaを実行
Lambdaはどこからか情報を取得/編集、SendGridで結果をメール配信
LambdaでKotlinを使用する方法は過去に書いたこの記事を参照
KotlinでAWS Lambdaを書く!
SendGridはクラウドメール配信サービスです。
登録後審査があるのですぐ使用開始!、とはいかないのですがFreeプランもあり良いサービスです。
※私の場合は1営業日ほどで認可されました。
SendGrid
各言語のSDKもあります。
https://github.com/sendgrid/sendgrid-java#usage
何を配信しよう??
とりあえずQiitaの日間トレンドを取得してみようか。
トレンドを取得するAPIはないようなので自分で取得します。
ライブラリにはjsoupとgsonを使用しています。
div[data-hyperapp-app=Trend]の中のattr("data-hyperapp-props")を取得すればトレンドが取ってこれますね。
以前Rubyで同じことをしてる方の記事を見て同じ方法を使わせていただきました。
※こんなやり方をしてるのは実際のページをF12ツールで解析すればあぁ。。とわかります。
class Qiita : Source {
override val connection = QiitaConnection()
//記事へのURL
//https://qiita.com/{{name}}/items/{{uid}}
override val information_list: MutableList<String> = mutableListOf()
override fun run(): MutableList<String> {
val documents = connection.getDocumentData()
this.information_list.add("------ Qiita Daliyトレンド記事 ------${LINE_SEPARATOR}")
documents?.forEach {
this.information_list.add("タイトル:${it.node?.title}" + LINE_SEPARATOR)
this.information_list.add("URL :https://qiita.com/${it.node?.author?.urlName}/items/${it.node?.uuid}" + LINE_SEPARATOR)
}
this.information_list.add("-----------------------------------$LINE_SEPARATOR")
return this.information_list
}
}
// const val QiitaDailyTrend = "https://qiita.com/"
class QiitaConnection : Connection(SourceList.QiitaDailyTrend) {
override fun getDocumentData(): List<Edge>? {
val element = super.html.select("div[data-hyperapp-app=Trend]")
.attr("data-hyperapp-props")
val data = gson.fromJson(element, DailyTrend::class.java)
return data.trend?.edges
}
}
gsonのPOJOの生成には以下のサイトを使用
私はここで作ったソースをIDEなどでKotlinに変換して使いました。
http://www.jsonschema2pojo.org/
余談なのですが、Gradleはこんな感じです。
今回の使うものだけでなく色々役に立つもの詰めてるのでまた使います。
(Java11向けに改造したいですが。。。。)
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
}
ext {
kotlin_version = "1.3.50"
spek_version = "2.0.8"
}
group 'kotlinDailyMail'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlin_version
compile 'com.sendgrid:sendgrid-java:4.4.1'
compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.0'
//GSON
compile 'com.google.code.gson:gson:2.8.6'
//Fuel
compile 'com.github.kittinunf.fuel:fuel:1.12.0'
//JSoup
compile 'org.jsoup:jsoup:1.12.1'
//JUnit5,Spek2
testImplementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_version
testImplementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlin_version
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.3.1'
testImplementation group: 'org.spekframework.spek2', name: 'spek-dsl-jvm', version: spek_version
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.3.1'
testRuntimeOnly group: 'org.spekframework.spek2', name: 'spek-runner-junit5', version: spek_version
testImplementation "org.jetbrains.kotlin:kotlin-test"
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
//MockK
testImplementation "io.mockk:mockk:1.9.3"
}
test {
useJUnitPlatform {
includeEngines 'spek2'
}
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
task buildZip(type: Zip) {
from compileKotlin
from processResources
into("lib") {
from configurations.runtime
}
}
build.dependsOn buildZip
一通りコーディングが済んだらLambda関数を作成
環境変数はTZをとりあえず修正
CloudWatch Eventsでスケジュール式を設定
Lambdaは基本UTCなので時刻を逆算して起動時間を指定する(下記はAM 8:00 に1回起動)
試しにテスト起動
プログラムで指定したアドレスにメールが届きました。
SendGrid側で証明書の設定とかをしていないと迷惑メールに入ってるかもです。
続き
軽い気持ちでQiitaのトレンドを試しに配信するか。
と思ったら結構大変で最適な方法を見つけるのに時間かかりました。(笑)
次は情報の取得先をより増やしたり、一度に取得する情報量を調整しようと思います。
他にも開発にSpek2とか導入していたのでそちらについても記事を書こうか考え中
ちなみにこの配信機能ですが、1円も開発には使ってないです。
日々の定時実行もLambdaの無料枠に余裕で収まります。
※実装中のおやつ代は別