占いのキュレーションサービス「Ftune」を作った

こんにちは、突然ですが僕たち日本人にとって空気のように身近にあるものといえば何でしょうか?それはもちろん「占い」です。朝の情報番組にはほぼ確実に占いのコーナーがあり、僕たちはそれを何の疑いもなく享受しています。ニュースと占いは2つが合わさって1つと言っていいでしょう。そして、平均的日本人である僕はもれなく占いが好きです。(偏見ですがこのブログを読む人はあまり占いに興味がないでしょう)

占いが確定的なら問題ないのですが、残念ながら占いとは曖昧なもので各メディアで別々の占いが取り扱われています。僕たちはそれをくまなく確認したいものです。僕は無職なので何ら問題はないのですが、現代人は忙しいのでせいぜい1つか2つの占いに目を通して終わりでしょう。本当にそれでいいのでしょうか?あらゆる物事は比較することで真実が見えてきます。出来るならもっと沢山の占いを確認するべきです。

でも時間がないという方におすすめするサービスがこれ、「Ftune」です。Fortuneからorを取り除いたものです。占いから曖昧性を無くそうという高い目標があります。この記事を書いているときに思いつきました。

ftune-web.com

Androidはアプリもあります。(iOSはありません…詳細は後述)

https://play.google.com/store/apps/details?id=app.bootch.ftune

play.google.com

実際何故作ったか

日々コンテンツが変化するサービスを自分で持っておきたかったというのが大きな理由です。新しかったり自分が試したことなかったりする技術を、実際に導入して挙動を確認できる環境が欲しかったのです。日々コンテンツが変化するサービスとしては、ユーザー投稿型のサービスや自分でコンテンツを投稿することが考えれますが、前者はそもそもユーザーが集まらないとどうにもならないのと、後者は単純にめんどくさいのでやめました。キュレーションの中でも、占いは身近にありふれている割にこれといったサービスが思い浮かばなく、かつ実際に調べても存在しなかったので決定しました。また、最悪誰も使わなくても自分は使えるものが良かったので占いにした、という理由もあります。

全体構成

全体の構成をざっくり説明します。各コンポーネントの詳細は元気があれば別の機会で書きます。

f:id:pompom168:20220209170015p:plain

Crawler

間違いなく一番めんどくさかったのは占いを収集するCrawlerです。現状30程度のドメインを対象とした割と中規模くらいのクローラーを作れたので良い経験でした。

言語はPythonでScrapyというフレームワークを使っています。Scrapyはページの辿り方や内容のパース以外のめんどくさい部分をほとんど設定で制御できるので便利です。ただ、JavaScriptによってクライアント側でゴリゴリHTMLを生成するページには対応できません。そこで一部Splash (scrapy-splash) というクローラーとwebサイトとの通信を中継してJavaScriptを実行した結果を返してくれるライブラリと組み合わせて使用しています。またクローリングの結果をFirebaseのFirestoreとS3に保存しています。Firestoreはクライアント側からの読み込み、S3はクローリングのたびに読み込んで占いのクロール済の判定に使ったり、後述のAnalyzerの入力になったりします。

そして、ひとまず単純なEC2にデプロイして日々運用しています。というのも極力お金をかけたくなく、AWSの1年の無料枠の中で動かしたかったからです。少しでも利益を得られるようになったらFargateなりに移行したいところです。

めんどくさいところは多々あったのですが、長くなってしまうので別にします。

Analyzer

せっかくCrawlerで本文まで収集しているので、何か分析した結果を出そうと思って作りました。現状では、ユーザーごとの占いのキーワードや独自のスコアを出しています。(ユーザーごとと言いつつ現状は星座別です…)唯一独自のコンテンツの部分ではあるのですが、やってることは本当に単純で2時間くらいで作りました。一応何をやっているかは説明しないことにしておきます。

こちらもCrawlerと同じEC2インスタンスにデプロイして動かしています。

Ftune(アプリ)

最初はアプリだけの予定でした。React NativeによりiOSとAndroidのクロスプラットフォームで開発しました(実際世に出ているのはAndroidだけですが…)。アプリを作るのはほぼ初めてで、クロスプラットフォームで開発したかったのでReact Nativeを選択しました。実際今の第一候補としてはFlutterなんじゃないかと思いますが、「react native」で検索したら「react native オワコン」とサジェストされるところに逆張り精神がひっかかり選びました。あと最近Reactを使いだしたので、Reactをベースにできるのも大きいところでした。

Ftune(web)

後述しますがiOSアプリが審査に通る気配が無く、Androidだけでは不安に感じたのでwebバージョンも作ることにしました。こちらはNext.jsで開発しました。単純にReactベースに1個別の技術使いたかったので選択したくらいです。一応SEO的なことも考えました。ただメインのページが現状Client Side Rendering (CSR) になっており正直あんまりNext.jsの恩恵は無いかもしれません。

こちらは、Vercelにデプロイして動かしています。開発元が同じだけあってNext.jsとVercelはほぼセットみたいな雰囲気を感じますね。何も意識しなくても自動デプロイなどCI/CDの恩恵を受けられるのが良いですね。pull request別にプレビューのURLが用意されて確認できるのもめちゃくちゃ良いと思いました。

開発の経緯

11月後半から12月前半にかけてCrawlerの開発を行い、12月後半でアプリを作りました。そして12月24日にiOSアプリをApp StoreにAndroidアプリをGoogle Playに提出しました。Google Playは審査を通過してリリースされたものの、App Storeではリジェクトされました。事前に軽く調べていた感じではキュレーションアプリなので、Guideline 4.2.2 - Design - Minimum Functionalityの理由でリジェクトされることは想定しており、実際ガイドライン違反も指摘されました。こちらは、機能を追加していけばいいと思っていたのですが、想定外のGuideline 4.3 - Design - Spam違反も指摘されました。普通に「占いのアプリは飽和してるからすごい機能がないとリジェクト」と書いてありました。2020年3月ごろに占いの指定が追加されたようです。

少しの望みをかけて、とりあえずGuideline 4.2.2 - Design - Minimum Functionality違反へのよくある対策を調べてオフラインでもコンテンツを表示できるようにしたり、お気に入り機能をつけたりして再度提出しました。年末年始はほぼ毎日1つ機能を追加しては再提出を繰り返していた気がします。5,6回リジェクトされて軽く取れる打ち手がなくなったとこで、App Storeの審査を通すことは諦めました。

1月前半は、App Storeリジェクトのショックでやる気がなくなっていたり、突発性難聴になったりでほとんど作業ができませんでした。そして何となくやる気を取り戻し、1月後半からweb版の開発にとりかかり現在に至るという感じです。

おわりに

ひとまずは、目的であった日々コンテンツが変化するサービスを作ることができて良かったです。ここ数ヶ月フロント周りを触ったこともあって、フロント界隈で話されている内容が何となく何言ってるか分かるくらいにはなったと思います。今後も改良を重ねていければなと思います。