Amazon Linux 2022 (AL2022) と Node.js

そろそろ Node も 18かなという感じ。この時点、2022/9/下、 https://nodejs.org/ja/ にて、バージョンは「16.17.0 LTS 推奨版」「18.9.0 最新版」です。
前回記事(2022/2/) AmazonLinux2 に Node.js - hs9587’s diary より少し進んでいるけど、LTS推奨版のメジャーバージョン 16 は変わっていません。それはいいとして、AmazonLinux2 では、glibc とかバージョンが合わなくて、18系は入りません。
そして「りあクト!」の第4版が出て、それが「v18.7.0 って」なので 18系が良いのですが、どうしましょう。りあクト! TypeScriptで始めるつらくないReact開発 第4版【① 言語・環境編】 - くるみ割り書房 ft. React - BOOTH第4版【② React基礎編】第4版【③ React応用編】

Amazon Linux 2022 (AL2022)

前回記事(2022/2/) AmazonLinux2 に Node.js - hs9587’s diary では、Amazon Linux 2 (AL2) を見ていました、その AL2 の次は AL2022 という事です。
Amazon Linux 2022 のプレビューの発表
Comparing Amazon Linux 2 and Amazon Linux 2022 - Amazon Linux 2022
EC2コンソールからの「インスタンスの起動」では、「アプリケーションおよび OS イメージ (Amazon マシンイメージ)」 の選択で、「クイックスタート」には出て来ないの注意、「その他の AMI を閲覧する」で「コミュニティ AMI」になります、検索ワードは「al2022」にしましょう、「Amazon Linux 2022」「Amazon Linux」ではすぐ出てきません。そして日付のついたのが複数出て来るの、新しい日付のをえらべばいいでしょう、minimal じゃなくて良いよね。今カーネルはみんな 5.15 みたい。

glibc のバージョンは上がっています、Node.js 18 (2.27, 2.28以上)には全然余裕です。

Package name Amazon Linux 2 Amazon Linux 2022
glibc 2.26 2.34
gcc 7.3 11.2
binutils 2.29 2.35

https://docs.aws.amazon.com/linux/al2022/ug/compare-al2-to-AL2022.html#glibc-gcc-and-binutils

パッケージコマンド「dnf」

パッケージコマンドは「dnf」です。
Package management tool - Amazon Linux 2022

まだ「yum」も使える(dnf のポインターになってる)けど、これからはこちらを使いましょう。

dnf check-release-update

そして時々「dnf check-release-update 」しましょう。たまに

WARNING:
  A newer release of "Amazon Linux" is available.

とか言われます、適宜「dnf update --releasever=2022.0.<何か>」どうぞ。

パッケージ、nodejs, npm あります

nodejs.x86_64 1:18.4.0-1.amzn2022 amazonlinux
npm.x86_64 1:8.12.1-1.18.4.0.1.amzn2022 amazonlinux

パッケージのバージョンは 18.4 です、最新にはなってませんが 18系です。
npm があれば yarn とかも来ます

sudo dnf install nodejs npm -y 
sudo npm install -g yarn typescript ts-node typesync npm-check-updates
node --version                   
v18.4.0
npm --version                     
8.12.1
npx --version                     
8.12.1
yarn --version                    
1.22.19
ts-node -v                        
v10.9.1

とか。

他のパッケージ

nkf , w3m もはいってるのはいいですね。nkf があるので guess はエイリアスにしておきます

alias guess='nkf --guess'

locate (mlocate) は無いようです、findutilsパッケージは入ってるので「find / -name <ファイル名>」しましょう、sudo 必要かな。

asdf で nodejs

「りあクト!」第4版のリードに従って、バージョンマネージャ asdf でのインストールもやってみます。
Getting Started | asdf
GitHUB からホームにもってきて、.bashrc .zshrc を調整、asdfコマンド動きます

(0)ec2-user@ip-<何か>[18] asdf --version 
v0.10.2-7e7a1fa

そして
.default-npm-packages

yarn
typescript
ts-node
typesync
npm-check-updates

として

asdf plugin add nodejs
asdf install nodejs latest
asdf global nodejs latest

すると

node --version
v18.9.1
npm --version
8.19.1
npx --version
8.19.1
yarn --version
1.22.19
ts-node -v
v10.9.1

とか。いい感じ。

fs.inotify.max_user_watches=65536

あと、手元機の VSCodessh拡張から nodejs機をみていると、max_user_watches の制限に引っかかるようなので、調整しておきます
Running Visual Studio Code on Linux

(0)ec2-user@ip-<何か>[30] cat /proc/sys/fs/inotify/max_user_watches
15275
(0)ec2-user@ip-<何か>[33] sudo sed -i.old -e '$afs.inotify.max_user_watches=65536' /etc/sysctl.conf
[~] <pts/1>
(0)ec2-user@ip-<何か>[34] tail -1 /etc/sysctl.conf         
fs.inotify.max_user_watches=65536
(0)ec2-user@ip-<何か>[35] sudo sysctl -p                   
fs.inotify.max_user_watches = 65536
[~] <pts/1>
(0)ec2-user@ip-<何か>
[36] cat /proc/sys/fs/inotify/max_user_watches
65536

unzip -l、zipinfo、rubyzip、と標準入力

zip ファイルの格納ファイルの一覧、というか、それっぽいの一覧やら思ってるファイルが入ってるかどうか見たい。それで、zipファイル標準入力から取れないかな。

ファイル一覧ならまずは

unzip -l file[.zip] [list]

[list] にファイル名とか、ワイルドカード適宜。
いいんだけど、zipファイルの情報とか該当ファイル数とかのヘッダフッダが付き、各行にもサイズや日時が入ってるの、参考になるけど、ちょっと余計に思うこともある。

ファイル名だけなら

zipinfo -1 file[.zip] [list]

とか、「-1」なしだと前項同様の各行のサイズ日時とかもうちょっと詳しく。
いずれも他のオプションもいりいろあるので参考に。

そしてどちらにしても、このへんのコマンド系では、zipファイルは引数に指定する、標準入力からは読めない。

zipinfo -1 /dev/stdin [list] < file[.zip]

とすれば、リダイレクトから取ってくることはできるが、標準入力からは取れたなかった。それは僕のシェルの扱いが分かってないのかな。

というわけで、「rubyzip」を使います、手元環境で「gem list rubyzip」すると入ってたんだけど、標準添付のジェムだっけ、そうじゃなければジェムインストールしましょう。そして

cat file[.zip] | ruby -r zip -e 'Zip::File.open_buffer(ARGF.read).glob("**/*<何か>.txt").map{_1.name.+("\n")}.join.display'

ジェム名 rubyzip だけど、「-r zip」なの注意、あとは #glob のワイルドカードRuby の Dir
class Dir (Ruby 3.1 リファレンスマニュアル) のを参考に。

AmazonLinux2 に Node.js

AmazonLinux2 に Node.js を入れるのはどうしましょう。
いや、今さらそこに入れなくても、ラムダでもドッカーでも呼べばいいんだけど、やっぱり手元環境も欲しくて(手元?)。

この時点、2022/2/半ばで、https://nodejs.org/ja/ にて、バージョンは「16.14.0 LTS 推奨版」「17.5.0 最新版 最新の機能」

(2022/10/1 追記)
その後、nodejs 1.8系をいれようとしたら、AmazonLinux2 では難しくて、AmazonLinux2022 (AL2022) にしました、次の記事 Amazon Linux 2022 (AL2022) と Node.js - hs9587’s diary

バイナリからのインストール

Installing Node.js via binary archive Installation · nodejs/help Wiki · GitHub をみながら

  1. 前項メインサイトより Linux Binaries (x64) node-v16.14.0-linux-x64.tar.xz をダウンロード
    1. 最新 node-v17.5.0-linux-x64.tar.xz でもいいけどここは堅実に推奨版で
  2. how-to-install-nodejs-via-binary-archive-on-linux を参考に /usr/local/lib/nodejs に展開
[ec2-user@ip- ~]$ sudo mkdir -p /usr/local/lib/nodejs
[ec2-user@ip- ~]$ sudo tar -xJvf node-v16.14.0-linux-x64.tar.xz -C /usr/local/lib/nodejs
  1. using-sudo-to-symlink-node-npm-and-npx-into-usrbin を参考に /usr/bin/ に Sリンク
[ec2-user@ip- ~]$ sudo ln -s /usr/local/lib/nodejs/node-v16.14.0-linux-x64/bin/node /usr/bin/node
[ec2-user@ip- ~]$ sudo ln -s /usr/local/lib/nodejs/node-v16.14.0-linux-x64/bin/npm /usr/bin/npm
[ec2-user@ip- ~]$ sudo ln -s /usr/local/lib/nodejs/node-v16.14.0-linux-x64/bin/npx /usr/bin/npx
  1. という事で、バージョン等確認

node

[ec2-user@ip- ~]$ node -v
v16.14.0

npm

[ec2-user@ip- ~]$ npm version
{
  npm: '8.3.1',
  node: '16.14.0',
  v8: '9.4.146.24-node.20',
  uv: '1.43.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '93',
  nghttp2: '1.45.1',
  napi: '8',
  llhttp: '6.0.4',
  openssl: '1.1.1m+quic',
  cldr: '40.0',
  icu: '70.1',
  tz: '2021a3',
  unicode: '14.0',
  ngtcp2: '0.1.0-DEV',
  nghttp3: '0.1.0-DEV'
}

npx

[ec2-user@ip- ~]$ npx -v
8.3.1

これで良かったのだけど、それは下記が難しかったから。

パッケージからのインストール、難

AmazonLinux2 の yumパッケージだと、amazon-linux-extras から epel を入れてそのパッケージ「yum list nodejs」

nodejs.x86_64                        1:16.13.2-7.el7                        epel

まあ、16 です。
そして「sudo yum install nodejs」

Error: Package: 1:nodejs-16.13.2-7.el7.x86_64 (epel)
           Requires: libuv >= 1:1.42.0
           Available: 1:libuv-1.23.2-1.amzn2.0.2.i686 (amzn2-core)
               libuv = 1:1.23.2-1.amzn2.0.2
           Available: 1:libuv-1.39.0-1.amzn2.i686 (amzn2-core)
               libuv = 1:1.39.0-1.amzn2
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

とのこと。なので「 sudo yum install nodejs --skip-broken」
まあ、進むような、Skipするような、そして失敗

--> Processing Dependency: libuv >= 1:1.42.0 for package: 1:nodejs-16.13.2-7.el7.x86_64

だけど

Packages skipped because of dependency problems:
    brotli-1.0.7-5.el7.x86_64 from epel
    1:libuv-1.39.0-1.amzn2.x86_64 from amzn2-core
    1:nodejs-16.13.2-7.el7.x86_64 from epel
    1:nodejs-libs-16.13.2-7.el7.x86_64 from epel
    1:openssl11-1.1.1g-12.amzn2.0.4.x86_64 from amzn2-core

libuv のバージョンが足りないわけです。
ということで、yumからのインストールは出来なかったです。

(追記) NodeSource パッケージ、これが良いかな

コメントいただきました、あり難うございます。

いけむらさん@fd0
既に確認済みかもしれませんが、ここの手順でやると自分は楽にできました
午前0:14 ・ 2022年2月14日

distributions/README.md at master · nodesource/distributions · GitHub

NodeSource Node.js Binary Distributions
https://github.com/nodesource/distributions/blob/master/README.md#nodesource-nodejs-binary-distributions

NodeSourceさん、Node.js本体とは違うところでディストリビューション別のパッケージインストールの案内がありました。

Enterprise Linux based distributions にて、Amazon Linux 2 (64-bit) の項あり、
Installation instructions との事です

Node.js LTS (16.x)

curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -

こちら、setup_lts.x 文書はシェルスクリプト、環境というかディストリビューションをチェックして、良さそうな rpmパッケージをダウンロードしてくる、或いはパッケージのリポジトリをセットします。

そして、

## Run `sudo yum install -y nodejs` to install Node.js 16.x and npm.
## You may run dnf if yum is not available:
     sudo dnf install -y nodejs
## You may also need development tools to build native addons:
     sudo yum install gcc-c++ make
## To install the Yarn package manager, run:
     curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
     sudo yum install yarn

と言ってきます。なのでそうする。

sudo yum install -y nodejs

いろいろあって

Running transaction
Warning: RPMDB altered outside of yum.
  Installing : 2:nodejs-16.14.0-1nodesource.x86_64                          1/1
  Verifying  : 2:nodejs-16.14.0-1nodesource.x86_64                          1/1

Installed:
  nodejs.x86_64 2:16.14.0-1nodesource

Complete!
[ec2-user@ip- ~]$ 

という事で、入りました。
バージョン確認。

[ec2-user@ip- ~]$ node -v
v16.14.0
[ec2-user@ip- ~]$ npm version
{
  npm: '8.3.1',
  node: '16.14.0',
  v8: '9.4.146.24-node.20',
  uv: '1.43.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '93',
  nghttp2: '1.45.1',
  napi: '8',
  llhttp: '6.0.4',
  openssl: '1.1.1m+quic',
  cldr: '40.0',
  icu: '70.1',
  tz: '2021a3',
  unicode: '14.0',
  ngtcp2: '0.1.0-DEV',
  nghttp3: '0.1.0-DEV'
}
[ec2-user@ip- ~]$ npx -v
8.3.1
[ec2-user@ip- ~]$

一応 reboot。

(1)ec2-user@ip-[6] ll /etc/yum.repos.d                14:28 0216 Wed
total 16
-rw-r--r-- 1 root root 1003 Oct 27 02:55 amzn2-core.repo
-rw-r--r-- 1 root root 4168 Feb 16 14:12 amzn2-extras.repo
-rw-r--r-- 1 root root  474 Apr 20  2021 nodesource-el7.repo
[~] <pts/2>

nodesource のレポジトリが追加されてるわけです。
yarn もインストールしましょう。

[~] <pts/2>
(1)ec2-user@ip-[7] curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
[yarn]
name=Yarn Repository
baseurl=https://dl.yarnpkg.com/rpm/
enabled=1
gpgcheck=1
gpgkey=https://dl.yarnpkg.com/rpm/pubkey.gpg
[~] <pts/2>

そして「sudo yum install yarn」します

(1)ec2-user@ip-[9] yarn -v                            15:28 0216 Wed
1.22.17
[~] <pts/2>

そして「sudo npm install -g typescript ts-node typesync」この辺もインストールしました

(0)ec2-user@ip-[14] ts-node -v                        15:53 0216 Wed
v10.5.0
[~] <pts/1>
(0)ec2-user@ip-[23] tsc -v                            15:57 0216 Wed
Version 4.5.5
[~] <pts/1>

良いですね。
コメントのようなエイリアス書かなくても、実行できてます。このインストールが良いです。

ソースからのビルド v16.14.0、難

Building Node.js from source on supported platforms node/BUILDING.md at main · nodejs/node · GitHub より

Source Code node-v16.14.0.tar.gz をダウンロードしたうえで

sudo yum install python3 gcc-c++ make python3-pip
tar xvzf node-v16.14.0.tar.gz
cd node-v16.14.0/
./configure
[ec2-user@ip- node-v16.14.0]$ ./configure
Node.js configure: Found Python 3.7.10...
WARNING: C++ compiler (CXX=g++, 7.3.1) too old, need g++ 8.3.0 or clang++ 8.0.0
WARNING: warnings were emitted in the configure phase
INFO: configure completed successfully
[ec2-user@ip- node-v16.14.0]$

ふむ、「yum list gcc

Installed Packages
gcc.x86_64                      7.3.1-13.amzn2    

ちょっとバージョンが足りない模様。

ちょっとカーネル「 sudo amazon-linux-extras install kernel-5.10」してみるけど、「./configure」メッセージ変わらない。
一応 completed successfully というので作りましょう

[ec2-user@ip- node-v16.14.0]$ make -j4

ちょっと時間かかる、10分とかそれ以上、t3.microインスタンスです。
それで

g++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[1]: *** [/home/ec2-user/node-v16.14.0/out/Release/obj.target/torque_base/deps/v8/src/torque/cc-generator.o] Error 4
make[1]: *** Waiting for unfinished jobs....
rm 5761517c9fac3ccdca772ce0e817a3e42baba5f2.intermediate
make[1]: Leaving directory `/home/ec2-user/node-v16.14.0/out'
make: *** [node] Error 2

出来なかったです。

node-v15.14.0.tar.gz、難

https://nodejs.org/download/release/v15.14.0/ より、node-v15.14.0.tar.gz、「tar xvzf」して「./configure」

[ec2-user@ip- node-v15.14.0]$ ./configure
Node.js configure: Found Python 3.7.10...
INFO: configure completed successfully
[ec2-user@ip- node-v15.14.0]$

いいんでしょうか「make -j4」

[ec2-user@ip- node-v15.14.0]$ make -j4

20分とかかな、t3.microインスタンス

g++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[1]: *** [/home/ec2-user/node-v15.14.0/out/Release/obj.target/torque_base/deps/v8/src/torque/cfg.o] Error 4
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory `/home/ec2-user/node-v15.14.0/out'
make: *** [node] Error 2

失敗

node-v14.19.0.tar.gz、難

https://nodejs.org/download/release/v14.19.0/ より、node-v14.19.0.tar.gz
「./configure」

Node.js configure: Found Python 3.7.10...
INFO: configure completed successfully

「make -j4」
20分とかかな、t3.microインスタンス

g++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[1]: *** [/home/ec2-user/node-v14.19.0/out/Release/obj.target/torque_base/deps/v8/src/torque/cfg.o] Error 4
make[1]: *** Waiting for unfinished jobs....
rm 671b9b97581075a7d3d68486280cfbd3d862ba1e.intermediate
make[1]: Leaving directory `/home/ec2-user/node-v14.19.0/out'
make: *** [node] Error 2

失敗

それぞれ、エラー詳細までは検討せず。

テキストの引き算

テキストの差分が欲しかったんだけど、diff とはちょっと違くて。
名前のリストがある、テキストファイルが二つ、まあファイル名とかディレクトリ名のリストなんだけど。こちらに在ってあちらに無いもの、或いは、こちらに無くてあちらに在るもの、そういうのが欲しかった。単にそういうリストが欲しいのであって、diff ではどちらのものとか何行目とか詳しいことがいろいろ出てきてそこまで必要ないです。

それは

grep -F -f <ファイルA>.txt -v <ファイルB>.txt 

でいいのでした。
fgrep は deprecated(非推奨) なので「-F」オプションにする、それで正規表現ではなくて単なる文字列として改行区切りで「-f <ファイルA>.txt」を受け付ける。「-v」なのでそれに入ってないものを「<ファイルB>.txt」から抜き出すことになる。

あと

cat <ファイルA>.txt <ファイルB>.txt S U -1

で対称差。
ここで「S」は「'| sort'」、「U」は「'| uniq'」その「-1」で 一回だけ出て来るもの。ということで、A に入ってて B に入ってないのと、 A に入ってなくて B に入ってるのと、合わせたものになります。
そしてファイルを繰り返すと先と同様の単なる差に

cat <ファイルA>.txt <ファイルB>.txt <ファイルB>.txt S U -1

で、A に入ってて B に入ってないのだけになります。B だけが欲しければ A の方繰り返す。

集計、ファイルサイズの足し算

ちょっといくつかのファイルのサイズの足し算が欲しかった、du ではなんか難しかった

ll */*.zip | sed -e 's/  */\t/g' C -f5 | paste -s -d+ B | numfmt --to=iec

ここで「ll」は「ls -l」、「C」は「'| cut'」、「B」は「'| bc'」。
sed のパターン「 's/ */\t/g'」は「 <空白文字> <空白文字>*<アステリスク>」にしています、正規表現の量指定子は零回以上の「*<アステリスク>」を使ったので「 <空白文字>」はふたつ続けています。1回以上の「+<プラス>」の方がいいかとも思ったのですが、シェルでは「\<円マーク>+<プラス>」と書かないと通らなくて返って分かり難くなるかと思った。そうして、cut の区切り文字「 <空白文字>」一つ、に合わせています。
ちなみに「S, P, N」はそれぞれ。sort, perl, nkf にしてるのでエイリアスは使いません。
あと、numfmt のオプション

--to=si
--to=iec
--to=iec-i

或いは、「none」「auto」、一方「--from=」。
du だと

du */*.zip C -f1 | paste -s -d+ B | numfmt --to=iec

このときサイズ数値は行の最初なので、そのあと空白文字で桁調整してても cut の区切り文字「 <空白文字>」一つにする調整は気にしなくてよい。
まあ、ll でも du でも、その出力を適宜「G='| grep'」とかで拾い直して足し算しましょうという話しです。

バランサーのヘルスチェックのリクエストヘッダー

AWS EC2のエラスティックロードバランサーをクラシックから付け替えているのだけど、アプリケーションロードバランサーにしたら、ヘルスチェックのリクエストが変わったみたいで、Webアプリ側のチェックで応答が悪くヘルスチェックに苦労した。
というわけで、ヘルスチェックのリクエストのヘッダーを見ましょう。
そのために、小さな Webサーバーをセットします、まあ、WEBrick でいいよね。小さな Webサーバは前にもいくつか話題にしています、時間の掛る Webサーバ - hs9587’s diary TLS1.2 サーバ - hs9587’s diary "小さい"Rackアプリケーション - hs9587’s diary

というわけで、このくらいかな

ruby -r webrick -e "WEBrick::HTTPServer.new(DocumentRoot: %q[./], Port: 8080, RequestCallback: Proc.new{|req,| req.raw_header.join.+(%Q[\n]).display }).start"

実行して、同じマシンで「lynx localhost:8080」とかすると、こうい風にリクエストのヘッダーが見えます。

(0)ec2-user@ip-172-31-<何か>[34] ruby -r webrick -e "WEBrick::HTTPServer.new(DocumentRoot: %q[./], Port: 8080, RequestCallback: Proc.new{|req,| req.raw_header.join.+(%Q[\n]).display }).start"
[2021-08-14 11:39:58] INFO  WEBrick 1.7.0
[2021-08-14 11:39:58] INFO  ruby 3.0.1 (2021-04-05) [x86_64-linux]
[2021-08-14 11:39:58] INFO  WEBrick::HTTPServer#start: pid=29917 port=8080
Host: localhost:8080
Accept: text/html, text/plain, text/css, text/sgml, */*;q=0.01
Accept-Encoding: gzip, bzip2
Accept-Language: en
User-Agent: Lynx/2.8.8dev.15 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/1.0.2k-fips

127.0.0.1 - - [14/Aug/2021:11:40:04 JST] "GET / HTTP/1.0" 200 77
- -> /

起動ディレクトリには「Hello world!」とあるだけの index.html を置いときます。

というわけで、ロードバランサーやターゲットグループにこの機を配置します。

Classic Load Balancer より

host: 172.31.<何か>:8080
User-Agent: ELB-HealthChecker/1.0
Accept: */*
Connection: keep-alive

172.31.<何か> - - [14/Aug/2021:14:14:53 JST] "GET /index.html HTTP/1.1" 200 77
- -> /index.html

Application Load Balancer の Target groups より

Host: 172.31.<何か>:8080
Connection: close
User-Agent: ELB-HealthChecker/2.0
Accept-Encoding: gzip, compressed

172.31.<何か> - - [14/Aug/2021:14:13:53 JST] "GET /index.html HTTP/1.1" 200 77
- -> /index.html

ということで、User-Agent: が 1.0、2.0 とか兎も角、Connection: の値や、Accept: か Accept-Encoding: など、微妙に違っています。
所要のWebアプリでは「[msg "Request Missing an Accept Header"]」と出ていたので、まさにそういう事でした。

Facebook や Instagram のデータのダウンロードで JSON の日本語

FacebookInstagram の投稿など、(個人)データをまとめてダウンロードすることが出来る、データ形式JSON もあるのだけど、その日本語が読めない。
日本語というか非ASCIIというかそういう文字。

  • Facebook - アカウント - 設定とプライバシー - 設定
    • あなたのFacebook情報 - 個人データをダウンロード - コピーをリクエスト - フォーマット - JSON
  • Instagram - 設定
    • プライバシーとセキュリティ - データのダウンロード - ダウンロードをリクエスト - 情報フォーマット - JSON

ダウンロードはこの辺から。

猫廼舎。2019年09月28日(土) 15:00:59

それで、この辺の投稿

フェイスブック
https://www.facebook.com/hi.shimura.9/posts/2627556467311596

インスタグラム
https://www.instagram.com/p/B28a5ANHUI6/?igshid=1qe54csg90kch

ちなみにツイッターの投稿はこちら
https://twitter.com/hs9587/status/1177825511520788485

それはこういう文字です

irb(main):009:0> "猫廼舎。".force_encoding('ASCII')
=> "\xE7\x8C\xAB\xE5\xBB\xBC\xE8\x88\x8E\xE3\x80\x82"

それが上記でダウンロードしたなかで、

フェイスブック

  {
    "timestamp": 1569650461,
    "attachments": [
      {
        "data": [
          {
            "media": {
              "uri": "photos_and_videos/InstagramPhotos_DG0b8PZadQ/71746085_2627556473978262_1018468751701442560_n_2627556467311596.jpg",
              "creation_timestamp": 1569650461,
              "title": "Instagram Photos",
              "description": "\u00e7\u008c\u00ab\u00e5\u00bb\u00bc\u00e8\u0088\u008e\u00e3\u0080\u0082"
            }
          }
        ]
      }
    ]
  },


インスタグラム

  {
    "media": [
      {
        "uri": "media/posts/201909/70725295_131712588184345_6958651618331221860_n_18004788103249812.jpg",
        "creation_timestamp": 1569650456,
        "media_metadata": {
 …… (写真のメタデータ少々)
        },
        "title": "\u00e7\u008c\u00ab\u00e5\u00bb\u00bc\u00e8\u0088\u008e\u00e3\u0080\u0082"
      }
    ]
  },

こんな感じ。
(それそれ一部切り出し、なかの uri の記述はそれぞれの同梱データでの画像ファイル名)

日本語文字列

というわけで

"\u00e7\u008c\u00ab\u00e5\u00bb\u00bc\u00e8\u0088\u008e\u00e3\u0080\u0082"

「猫廼舎。」

JSON なら UTF-8 のはずなんだけどそうじゃない、手近の JSONパーサはそう思って変換して読めなくなってしまう。(Rubyjsonライブラリです)

この辺参考に文字を読みます

UTF-8 の16進表記を2桁ずつにして「\u00」に繋げてるみたい、どういう形式(名前)のエンコーディングなんだろう。

というわけで、encoding: 'ascii' で読み、そのように変換します、Ruby です。

irb(main):026:0> neko
=> "              \"description\": \"\\u00e7\\u008c\\u00ab\\u00e5\\u00bb\\u00bc\\u00e8\\u0088\\u008e\\u00e3\\u0080\\u0082\"\n"
irb(main):027:0> neko.encoding
=> #<Encoding:US-ASCII>
irb(main):028:0> neko.gsub(/\\u00([a-f0-9]{2})/m){ "#{$1.to_i(16).chr}"}.force_encoding('UTF-8')
=> "              \"description\": \"猫廼舎。\"\n"