ぽんぽんぺいんでつらたんなので、おしごとおやすみしまーす

🗣: バイクに乗ったり、ものづくりしたり、ひたすら寝たり。

はじめてのスクレイピング アプリでOSの依存性やCORSなどに殴られた話。

早いもので、盛夏の真っ只中です。後5ヶ月もしたら29回目の紅白歌合戦。 ここ数ヶ月に渡って、TypeScript, Angular.js, Node.js, AWS…などなど、前の現場の復習も兼ねて触ったりしていました。

シングルページアプリケーション www.oreilly.co.jp

を読んだ3年前、何がどうなっているかわからないうちに手を動かしている部分もありましたが、 今回はもう少し発展的なことができたかな…テスト書いてないけど…

今回作ったもの

バイクが大好きですが、横断的に車両の情報を表示しているWebページがなかった気がしたので、 バイク情報の表示 + 内容をDBに取り込んで検索 できる物を作ってみました。もう自己満足です。

デモアプリ
デモアプリ
今の仕様では前者だけの要件を満たしていますが、まずはローカルでの開発〜デプロイまでのいろいろをメモしていきます。

今回作る上でやってみたかったこと

バックエンドJSと、フロントエンドはAngularで書きたかった。です。

フロントはVueを使うことも検討しましたが、よりサービスロジックに近いこと + オブジェクトを独自のデータ型で定義し、扱うことが主流になっているAngularにしました。 (Vueでも好きなオブジェクト型は作れるが、構成に頭を使うことと、Component単位の実装をして、再利用について全て一緒にやっていたら頭がおかしくなりそうだった)

バックエンドJSは最近流行っているから…、Nodeを書きたい気持ちになった。JavaScriptができることの可能性をバックエンドまで体験したかった。という理由です。

苦労した点

はじめてのEC2インスタンスで環境構築

AWSを触るのはほぼほぼはじめて。(前職ではSSL証明書の更新をやらせてもらったくらい)

インフラって本当に抽象的というか、実際に触らないと実感としてわかないところが多い。なので前職ではむりくり理由をつけて触らせてもらったw自分で物作るときはホスティングサービスにお世話になってたからね…

マシンタイプの選定も、よくわからずどうせ拡張するからね!って理由でAmazon Linux2のt2.micro(メモリ1GBw)を選択したけど、これが後々の環境構築に大きく響くことになった…ここに関しては調査不足が否めない。 まっさらなOSにいろいろインストールするのは比較的脳死で行ってたけど、後々CentOSに切り替えてからsudo yum whatprovidesコマンドの存在を崇めることになる。平たく言うとrpmライブラリがなにに依存して動いているかがわかる。今足りないものについても教えてくれる。rpmってなに

スクレイピング してくれるライブラリ(puppteener)のlaunch error

ものごっつ便利なスクレイピング アプリがあると聞いて、まず導入してみた。 比較的最近Nodeでの開発事例があることと、READMEがしっかりしてたからまず使ってみた。Dockerの上からでも動く。

github.com

OS別の動かし方も載っている。 が、EC2上で動かすときにUnhandledPromiseRejectionWarning: Error: Failed to launch chrome!と出る。 node/node_modules/puppeteer/.local-chromium/linux-*****/chrome-linux/chromeとか出ているから、chromeが参照できなくて怒ってるんだね。権限周りを散々疑ったり、引数にわざわざ上記のパスを書いてみたりしたけれど、この段階ではうまく解決できなかった。

OSとライブラリの依存性

上でもちょっと触れているけど、最初はAmazon Linux2上でpuppteenerを動かしてた。上に書いてあるようなエラーにぶち当たって、思い切って新しいインスタンスを立ててみることにした。(なけなしの銭を投げ打って。w) これは正解だったみたいで、前のOSでは見つけきれなかったパッケージなどをうまくインストールすることができた。 これによってUnhandledPromiseRejectionWarning: Error: Failed to launch chrome!は見えなくなったし、puppteenerが動いているAPIのエンドポイントで真っ白なページを眺めることもなくなった。w

スクレイピング 結果
スクレイピング 結果

わかりづらいけど、あるバイク販売店のHPのhtmlを丸ごとリクエストして、そこから必要なDOMから文字列を抜き出してる。 フロントエンドで<td>を挿入するように整形しているはずだけど、なぜか数珠つなぎになってるw直さなくては。

最終的にスペックは t2.medium Red Hat Enterprise Linux にした。

必要だったやつ

sudo yum install alsa-lib.x86_64 atk.x86_64 cups-libs.x86_64 gtk3.x86_64 ipa-gothic-fonts 
sudo yum install libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXrandr.x86_64 libXScrnSaver.x86_64 libXtst.x86_64 pango.x86_64 xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-fonts-cyrillic xorg-x11-fonts-misc xorg-x11-fonts-Type1 xorg-x11-utils

lddコマンドで調べてから、また足りないライブラリのためにwhatprovidesで調べたりした。

ldd /node_modules/puppeteer/.local-chromium/linux-756035/chrome-linux/chrome
    linux-vdso.so.1 (0x00007fff041e2000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f1ef9dd3000)
…
    libnspr4.so => /lib64/libnspr4.so (0x00007f1ef70ac000)
    libatk-1.0.so.0 => not found
    libatk-bridge-2.0.so.0 => not found
    libcups.so.2 => not found
    libdbus-1.so.3 => /lib64/libdbus-1.so.3 (0x00007f1ef6e58000)
    libXss.so.1 => /lib64/libXss.so.1 (0x00007f1ef6c54000)
    libgio-2.0.so.0 => /lib64/libgio-2.0.so.0 (0x00007f1ef68ab000)
    libexpat.so.1 => /lib64/libexpat.so.1 (0x00007f1ef6670000)
    libXrandr.so.2 => /lib64/libXrandr.so.2 (0x00007f1ef6465000)
    libdrm.so.2 => not found
    libm.so.6 => /lib64/libm.so.6 (0x00007f1ef60e3000)
    libgbm.so.1 => not found
    libasound.so.2 => not found
    libpangocairo-1.0.so.0 => /lib64/libpangocairo-1.0.so.0 (0x00007f1ef5ed4000)
    libpango-1.0.so.0 => /lib64/libpango-1.0.so.0 (0x00007f1ef5c8d000)
    libcairo.so.2 => /lib64/libcairo.so.2 (0x00007f1ef596c000)
    libatspi.so.0 => not found
    libgtk-3.so.0 => not found
    libgdk-3.so.0 => not found
    libgdk_pixbuf-2.0.so.0 => not found
…

CORSで殴られる

ローカルで開発して喜んでる人だったから、CORSに悩まされたの。(こういうことを生業としていた会社に勤めていながら、恥ずかしい) API側でヘッダーの設定の書き方がちょっと違ったのでしばらく悩んでた。

   res.header('Access-Control-Allow-Origin', '*');
-  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
-  res.header('Access-Control-Allow-Methods', 'OPTIONS, GET, POST, PUT, DELETE');
+  res.header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
+  res.header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');

セキュリティグループの設定をうっかり忘れる

工程的には前の方だけど、インバウンドグループを設定し忘れるなんてこともあった。

次にやること(優先度順)

デザインをマシにする スマホで見れるようにする テストを書く ドメイン取る 機能の拡充

感想

express爆速。超便利。

qiita.com

プロジェクトのベース

medium.com