130
124

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Firebaseから相席ラウンジのデータをスクレイピングしFlutterアプリで表示する

Last updated at Posted at 2019-11-10

出会いがない!相席屋にいってみたい!でもどこの店舗に行ったらいいかわからない!そんな人のために簡単なアプリをFirebaseとFlutterで作ってみました。

動画でもかなりわかりやすく説明したつもりなので、5分時間がある方はチェックしてみてください。

【相席屋必勝法】プログラミングで相席ラウンジの女子率を計測ww【スクレイピング】

目的

ブルーオーシャン.jpg

出会いがない!相席屋にいってみたい!でもどこの店舗に行ったらいいかわからない!そんな人のために、ブルーオーシャン順に並べたアプリを作ろう!というのが目的です。

また、最速で作るために、FirebaseのCloud FunctionとFirestoreだけで作っていきます。

全体構成

firebase cloud functionに毎5分ごとに実行するfunctionを作り、5分ごとに相席ラウンジのサイトをスクレイピングし、相席ラウンジの各店舗の現在の男女の人数を取得します。このデータをfirebaseのfirestoreと呼ばれるデーターベースに記録していきます。

全体構成.jpg

データーベースに保存された情報を可視化するために今回はFlutterでスマホアプリを作ります。スマホアプリで現在のブルーオーシャン店舗ランキングを簡易的に表示し、今行くべき店舗がすぐに分かるようにするアプリを作って行きましょう。

定期実行

Firebaseのドキュメントに関数のスケジュール設定にあるように、最近Firebase Cloud Functionsに定期実行の機能が追加されたため、容易に定期実行をできるようになりました。

(以前はAppEngineを組み合わせて定期実行していた - FirebaseとAppEngineだけでRSSを使った動画アプリやニュースアプリを作る方法

例えば、15分ごとに実行したい場合は、以下のように書きます。

exports.scrapeAiseki = functions.pubsub
    .schedule('every 15 minutes')
    .timeZone('Asia/Tokyo')
    .onRun(async (context) => {

    });

スクレイピング

スクレイピングとは、あるWEBサイトのHTMLの要素から必要な情報を抽出することを言います。今回は相席ラウンジのHPのHTMLを抽出して、店舗ごとの人数比などを取得していきましょう。というのも、相席ラウンジのトップページからは各店舗ごとの男女比が一目瞭然なのです。

相席男女比.jpg

今回スクレイピングにはpuppeteerというライブラリを使います。

puppteer.jpg

簡単に説明すると、puppeteerはヘッドレスブラウザと呼ばれるChromeやSafariみたいなGUIはないブラウザです。つまり目には見えないブラウザで、puppeteerが指定したwebページのサイトを見た目には表示せずに見に行くことができます。

こちらをfirebaseのcloud functionで使いたいので、package.jsonのdependenciesに以下のようにpuppeteerを追加しターミナルでnpm installします。

package.json
  "dependencies": {
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.3.0",
    "puppeteer": "^1.20.0"
  }

これで使えるようになったのでFirebase Cloud Functionsの定期実行のファンクションの中身に以下のように書いてスクレイピングします。

exports.scrapeAiseki = functions.pubsub
    .schedule('every 15 minutes')
    .timeZone('Asia/Tokyo')
    .onRun(async (context) => {
        const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
        const page = await browser.newPage();
        await page.goto('https://oriental-lounge.com');

        // 店舗取得
        const shops: [any] = await page.$$('.shop');

        await Promise.all(shops.map(async shop => await setShopData(shop)));
        await browser.close();
    });

上記コードでは、

await setShopData(shop)

でもろもろ店舗名や男女比を取得しています。その辺のコードは割愛してサンプルコードをみていただきたいと思いますが、何をやっているかだけ説明していきます。

Chromeで右クリックして検証モードを開いた、下図を見てください。

スクレイピング対象1.jpg

各都市の人数を表示しているところはshop_listというclass名のdivタグに囲まれています。そして各店舗の要素はshopというclass名のdivタグに囲まれています。

shopの中を展開していくとshop_name、num、link_detailというclassがあり、その名の通りshop_nameには店舗名が入っており、札幌という日本語名、そしてその中にはenというクラスで囲まれた英語表記があります。

スクレイピング対象.jpg

またnumの中身を展開すると、その中にはmanとwomanがあります。manの中のspanタグの間に人数が入っています。womanも同様です。こちらから人数が抜き出せそうですね。

すなわち今回取るべきところは、shop_nameの中のenのspanタグに挟まれた部分とmanとwomanの中のspanタグに囲まれた数字です。

これらをスクレイピングてfirestoreに都市ごとに保存していきます。詳しくはサンプルコードで。

Firestoreに保存

Firestoreに保存されると、firebaseの管理画面からこのように保存されたデータを確認することができます。しっかり書く都市のデータが保存されていますね

firestoreの状態.jpg

Flutterアプリ

最後にこのデータをアプリから表示していきます!今回のアプリ開発で使ったフレームワークがFlutterです。

flutter.jpg

今回は、Flutterを使って、相席ラウンジの各都市のデータをブルーオーシャンな順にリストで表示していくというシンプルな構成です。

取得したデータは最後に女性に比べて男性が少ない順に並べ替えます。つまりブルーオーシャン。最後にcellに都市名と男女の人数を表示して完成です。

Flutterのサンプルコードは、こちら

まとめ

ってことで、!良い相席ラウンジライフを!

よければ動画も見てください!

リンク

130
124
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
130
124

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?