「OK,Google. いいニュースを聞かせてくれ」
この記事はWebスクレイピング Advent Calendar 2017の2日目の記事です。
どうも、duenoです。先日転職をしまして、 前職ではそれはもうたーーーーーっくさんWebスクレイピングあれこれをやるような職場だったんですが、 現職ではそういった事、一切やらないです。 まぁでもなんか書こうと思ったので書きます。よろしくお願いします。
OK, Google. ニュース
こう言うと、GoogleHomeは最新のニュースを読み上げてくれるんですが、 今やってみたら某相撲暴行問題の話。 ぼくはそんなネガティブなニュースばかり聞きたくない。いいニュースを読み上げてくれ。
そんなわけで、タイトルの通り、「OK,Google. いいニュースを聞かせてくれ」と言うとポジティブなニュースを読み上げてくれる機能を実装したいと思います。
仕組み
「OK,Google. いいニュースを聞かせてくれ」 ↓ IFTTTが反応して、cloud functions をHTTPでたたく ↓ ニュースサイトから最近のニュースを何件かスクレイピングする。 ↓ GoogleのナチュラルらんげぇじAPIで感情分析。 ↓ 最もポジティブなニュースを読み上げる。
そんなかんじです。
読み上げるのに
anoninoni.hateblo.jp みたいな仕組みを使ってます。
あと1分で今日が終わるのでこれで詳細は後でかきます。
ありがとうございました。
退職したよー
この記事は退職者 Advent Calendar 2017の1日目の記事です。
いまさらになっちゃうんですが今年の10月頃に株式会社Speeeを退職しました。2年と9か月ぐらい在籍していたと思います。 現在は新宿の某社で働いています。
在職中のこと
在職中はずっとデジタルコンサルティング事業部という所にいました。 主に社内システムや、Webコンサル・広告配信に関するWebアプリケーションの運用・開発を行っていました。
自分とディレクターが1名ずつの小さいプロジェクトもあれば、 エンジニアが10名弱のプロジェクトのリードエンジニアを任されたりもしました。 詳細はあんまり話せないやつですが色々経験できて楽しかったです。
Speee社の良かった事
変化のスピードが半端ない
入社当初と比べて、社内の変化がもの凄かったです。
オンプレサーバにPHPでWebシステムが動いていたのが、 ある日を境に基本的にはRubyでやっていくぞ!という方針になり、 AWSをはじめとするクラウドサービスもばりばり使っていくようになり、 ReactもAngularもプロダクションで動くようになっていたり、 なかなかモダンなWeb開発ができるようになったように感じます。
全社でみても、わかりやすい所だとChatwork→Slackの移行だったり、CI・VIの刷新であったり、 変化させる、新しくする労力を惜しまない所はとてもよかったなぁと思います。
代表の個性や哲学が社風に表れていて面白い
話すと長くなるので割愛しますが、 Speee社は「知の共有」について一人ひとりがめちゃめちゃ哲学されていて、個人的に好きなところの一つです。 Slackや、Google Apps、Kibelaなどのツールを使う事についても非エンジニアの方も含め、どんどんハックしていき改善していく様子が面白かったです。
転職の動機
シンプルに環境を変えたかったというのが大きいです。
ありきたりなフラストレーションを感じ、これはもう環境を変えるしかないなと思ったというだけです。 転職のエモい話とかそういうのは他の方が書いてくれると思います。
ただ、転職の意思を固めるにあたって、「半年後、自分 or 会社がこういう状態になっていたら退職しよう」 というような設定は自分で継続的にするようにしていて、今回その条件を満たしたので転職するに至りました。
あとは、自分自身の人格が会社の環境に強く依存してしまったことがしんどかったです。
普通、職場環境に応じて自己人格をある程度最適化する(演じる)って事は少なからずあると思うんですが、 私はこのオン/オフがなんだかよくわからなくなってしまって、 自分は何者で、何がしたいのか、今一度落ち着いて考えて方針を定めるという事がしたくなりました。
だいたいそんな感じです。
どうやって転職先を決めたか
業種のこだわりはなかったので、基本的には転職ドラフトで活動していました。 ありがたいことに20社弱からの指名をいただき、とにかく色々な会社と面談をさせていただきました。
最終的には
- 自分が活躍できる環境か
- 自分が素でいられる環境か
という点を重視して転職先を決めました。 単純にスキルと人格の適合度ともいえると思います。
逆に、
- エンジニアとして成長できる環境か
- 責任領域が広く、裁量のある立場か
というところは優先度を低く考えていました。
エンジニアとしての成長というのは、会社に求めるよりは 個人の活動によるものが大きいなと思ったのと、 そんなに常に自由や裁量があっても考える事が増えてしんどいだけだよなぁと 働いているうちに思うようになったからです。 勉強会、Slack、GitHub、Twitter等で色々な方と関われるので、 「この会社にいるから全然学びを得られない。」なんてことはほぼないんじゃないかと思ってます。
ちなみに、転職ドラフトのレジュメはかなり時間と熱意をかけて準備したと思います。
最終的に文章を書いたのは5時間程度で、 業務で携わったプロジェクトの話をするのも限界があるので、 今持っている技術をちゃんと入れた個人プロジェクトを用意したりしました。
なので「転職ドラフト参加したいけど話せるプロジェクトないよ~~」って人は個人プロジェクトを公開してそれについて書くとよいと思います。
この後
今年の抱負として「技術を使って自己表現する」的なものを立てたんですが、大失敗しておりまして、というか転職することを第一目標に変えたのでそこまで進捗していない。というのが現状なのですが、そちらのほうやっていきたいと思います。
あと、収入や待遇の話していないのですがもちろん転職理由としてあり、 無事転職も済み、収入にも余裕ができたので来年こそは結婚しようと思います。
そんなわけで、
退職者 Advent Calendar 2017の1日目は@anoChickによる 僕と結婚を前提としたお付き合いをしてくださる方募集の記事でした。
ありがとうございました。
引き続きよろしくお願いいたします。
Google Home でツイッターをする
新しい職場で開かれたとあるコンテストで入賞し、GoogleHomeを頂いたので遊んでみました。
今回作った機能は下記の3つです
- 「OK,Google ツイート {ツイート内容}」と言うと{ツイート内容}がツイートされる。
- 「OK,Google リプライ {ツイート内容}」と言うと{ツイート内容}が一番最後に自分に対してリプライをしたユーザのツイートに対してリプライされる。
- 自分へのリプライが行われると、GoogleHomeがリプライ内容を喋る。
1.ツイートする
上の記事を参考に、基本的にはIFTTTで実装しています。
「おっけーぐーぐる ツイート 外に出る気力がない」
と言うと以下のようにツイートされるようになりました。
ただ、これだとツイート内容の単語間にスペースがはいってしまっています。
そのため、Firebase Functionsを経由し、そこで整形を行った後にツイートするというようにしました。
exports.tweet = functions.https.onRequest((request, response) => { var postParams = { status: request.body.text.replace(/ /g, '') + " - Google Home から" } client.post('statuses/update', postParams); response.status(200).end(); });
出来ました。
2.リプライする
リプライについても同様に、IFTTTからFIrebase FunctionsのエンドポイントURLを叩き、内部でツイッターAPIを使って最後のリプライを指定、ツイート。と言うような感じです。
つまづきポイントとしては、IFTTTの音声認識の設定を「リプライ $」とすると認識されづらく、「reply $」でも認識されるようにしたぐらいです。
3.自分へのリプライを喋る
↑を参考にしました。 GoogleHomeを喋らせるようのサーバを建て、発話APIを作ります、 IFTTTをつかってリプライが来たらwebhookによって発話APIを叩くようにします。
@EnsekiTT pic.twitter.com/0ZN3CrLDfy
— あのちっくしなちく (@anoChick) 2017年10月14日
こんな感じで、リプライが来ると喋りだすようになりました。 上のデモでは、「@anoChick おk」というツイート内容を発話しており、「@anoChick」の部分を抜きたかったので、この場合に関しても、Ficebase Functionsを経由して整形しています。
結果、下記のような構成に落ち着きました。
やっぱりIFTTTだけだと痒いところに手が届かないので、Cloud Functionsや AWS Lambda等、を使うといい感じになりそうです。
こういう独特な言い回しは間違えやすい
MRデバイスが家に届いたと思ったらインターネットに繋がらなくなった
悲しすぎるのと、なんか色々と混乱したので整理もかねて書いていく。
26日
午前10時 windows機にMRデバイスを接続し、初期設定中に突然PCがクラッシュ。以降設定ウィザードが進まなくなる。
午前10時30分 公式のトラブルシューティングに従い、インストール途中のファイルの削除及びレジストリをいじる。MRデバイスを接続していると、グラボのドライバーが異常停止するようになる。
午前11時 グラボのドライバーを最新のものにあげる。windowsじたい画面が常時真っ暗になる。古いドライバーを探してきて事なきを得る。
午前12時 同じ現象が起こる人はいないか調べる。microsoft insider previewというものを見つけたのでインストールを試みるも、ダウンロード中に回線が切れる。異常な通信扱いされている様子。ルータをいじり、何度も再接続してアップデートファイルをダウンロードしきる。
ここで力尽きて一度寝る。
午後5時 リネージュ2をはじめる。楽しい。
午後8時 windowsのアップデートをしたら、グラボのドライバーも更新されてしまい、画面が常時真っ暗に。仕方なく強制終了したら、アップデート中だったため、windowsが破損する。回復プログラムを実行する。
午後10時 再度microsoft insider previewのアップデートファイルのダウンロードを試みたところ、ルータがクラッシュ。電源後と落ちる。コンセントを指し直したら動いたけど接続情報が飛ぶ。契約時にもらった書類に接続情報が書いてなくて色々調べる。
午前12時 諦めてリネージュ2をやる。
もうこのまま引っ越したい。
PowerPointの資料生成をRubyで書きたい
資料作成自動化業務ってありますよね。 Googleスライドとか使えばいいのに、ビジネスサイドの理由とかでPowerPointじゃなきゃ嫌だって言われたり、 Railsアプリとして操作したいのにいい感じにPowerPointファイルを扱うgemがなかったりします。
今回はApache POIを使ったをさっと書く。
Apache POI
Apache POI(アパッチ・ポイまたはピーオーアイ)はApacheソフトウェア財団のプロジェクトで、WordやExcelといったMicrosoft Office形式のファイルを読み書きできる100% Javaライブラリとして提供されている。
そういうことなので、これを使えば詰むことはなさそう。
Apache POI - the Java API for Microsoft Documents サンプルコードとかたくさんある。
あとはJNIでrubyとJavaをブリッジしてしまえばよい。
JNI
Java Native Interface JVM上で動くコードでネイティブコードで連携するためのインタフェース仕様
このブリッジを実装したgemがあるので使う。
require 'rjb' out = Rjb::import('java.lang.System').out out.println('jarh')
こんな感じでかける。 これでRailsアプリのモデルや何かの資産を活用しつつ、Officeファイルを操作できる。
注意すべき点
RJBはメインスレッド以外のスレッドでの動作はサポートしていない。 うっかりSidekiqのworkerとかで処理しようとするとうまく動かなかったりする。 ジョブキューを使う場合はシングルスレッドで動かすとか、マルチプロセスモデルのものを使うとかしよう。
Firebase Functionsをゲームサーバーにしてみよう。
Firebase DatabaseとUnityでオンラインゲームを作るとして、 サーバーというか、GlobalManagerロールをどうしようってなったので Firebase Functionsでやってみようと思います。
今回やることは
1分ごとに、 - マップ上にランダムに木を生成する。 - ゲーム内時間を進める。
データ構造
{ "world": { "time": 1, "resources": { "wood": 0 }, "objects": [ { "type": "wood", "position": { "x":0, "y":0, "x":0, } }, { "type": "wood", "position": { "x":2, "y":0, "x":0, } } ] } }
こんな感じかな。 Functionsでobjectsにwoodを入れていく。
プレイヤーは木を切るとresources.woodを+1する。
やっていく
https://console.firebase.google.com まず適当にFirebaseプロジェクトを作る
npm install -g firebase-tools
firebaseのCLIをインストールして、 適当な空のディレクトリに移動してから
$ firebase init functions
生成されたindex.js
の中は
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(functions.config().firebase); exports.tick = functions.https.onRequest((request, response) => { admin.database().ref('/world/time').once("value") .then(snapshot => { admin.database().ref('/world/time').set(1 + snapshot.val()); }) admin.database().ref("/world/objects").push({ type: 'tree', position: { x: Math.floor(Math.random() * 51), y: 1, z: Math.floor(Math.random() * 51) } }); response.status(200).end(); });
こんな感じ。
コードの記述が終わったらデプロイをする。
$ firebase deploy --only functions
これでHTTPSのエンドポイントURLが発行される。
定期的に実行する
cron-job.org - Free cronjobs - from minutely to once a year.
これとか使ってみます。 定期的にHTTPリクエストを送ってくれるサービス。 1分毎に叩くように設定してみた。
これで 「1分毎に新たに木が生え、ゲーム内時間が進む」 が実装されました。
時系列データを集めてシェアするサービスを作っている。
Statis αですが公開はしています。
こういう感じのサービスを作っています。
どういうサービス?
現段階で出来るのは以下のようなことです。
- APIを用いて時系列データをポストする
- 対象データのURL・HTMLのパスを指定し、定期的にスクレイピングをさせ、データを収集する
- シリーズ(時系列データの単位)に対するイベントトリガー(しきい値を超えたらメッセージ)
- シリーズをまとめて観る事ができる"ボード"
- ボードへコメントをつける
例えばツイッターの自分のページのフォロワー数を1時間に1度スクレイピングしていくような事ができます。 こんな感じに指定すると勝手にデータが入っていく。
あとは しきい値を超えると発火するようなイベントトリガー。 モニタリングツールとかによくあるやつ。
なんで作ってるの
ビジネスシーンでは、GoogleDataStudio,Redash,Supsersetなどなど、プロジェクトの状況を視覚化する為のBIツールと呼ばれるアプリケーションが増えてきてます。 システム面では、DatadogやStackdriver等のモニタリングツールというものもあり、これも最近増えてきているような気がします。
ただこういったサービスって基本的にプライベートで使う想定ではなく、閉じられた範囲でしか情報を共有しないものです。
一般公開されているデータや個人のデータを1箇所に集約し、横断的に観ることが出来たら、 面白い発見や新しい体験が得られるのではないかと思って作っています。
今後の方針
とりあえずはいろいろなデータを入れて行くことに専念して、 ある程度パターンが増えたらデータの表現方法を考えて、 インフォグラフィックっぽいものが生成される機能とかを作りたいです。