requestって?
名前の通り、HTTPやHTTPS通信を行うためのnpm公開されているライブラリです。
これですね!
node.jsの生の関数を使用してHTTP/HTTPS通信を実行しようとすると、実装がちょっと複雑になってしまうので重宝しています
そんな便利なライブラリなんですが、sjisのデータをダウンロードしようとするとちょっと困ったちゃんになってしまうので……
その備忘録的に対応策でも。
node.jsでもutf8以外のデータをダウンロードしたい!
const request = require("request");
const jschardet = require('jschardet');;
const requestOption = {
url: 'http://www.nisshin-oillio.com/',
};
request(requestOption, (error, response, body) => {
console.log(body);
console.log(jschardet.detect(body));
});
という訳でsjisのページをダウンロードしてみます。
URLは……偶然見つけたsjisのページであって、特に意図はありません。
$ node index.js
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML lang="ja">
<HEAD>
<TITLE>�A���̃`�J���@�����I�C���I</TITLE>
...
{ encoding: 'windows-1252', confidence: 0.95 }
jschardetを使用してエンコーディングを判定しています。
detectでデータのエンコードを見てみたんですが……encodingがwindows-1252に。
というかタイトルも化けてしまっています。
どうしてこうなった?
結論から言うと、公式に書いてあります!
encoding - encoding to be used on setEncoding of response data. If null, the body is returned as a Buffer. Anything else (including the default value of undefined) will be passed as the > encoding parameter to toString() (meaning this is effectively utf8 by default). (Note: if you expect binary data, you should set encoding: null.)
問答無用でresponseデータをutf8として変換してしまうんですね。
そこの変換処理の問題でTITLEの部分がバケてしまっていたり、encodingの判定結果がおかしいことになってしまっています。
対応策!
iconvでsjisのデータをutf8に変換するところまで入れています。
const request = require("request");
const jschardet = require('jschardet');
const { Iconv } = require('iconv');
const requestOption = {
url: 'http://www.nisshin-oillio.com/',
encoding: null,
};
request(requestOption, (error, response, body) => {
const utf8body = (new Iconv('SHIFT_JIS', 'UTF-8')).convert(body).toString();
console.log(utf8body);
console.log(jschardet.detect(utf8body));
console.log(body);
console.log(jschardet.detect(body));
});
$ node index.js
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML lang="ja">
<HEAD>
<TITLE>植物のチカラ 日清オイリオ</TITLE>
...
{ encoding: 'windows-1252', confidence: 0.95 }
<Buffer 3c 21 44 4f 43 54 59 50 45 20 48 54 4d 4c 20 50 55 42 4c 49 43 20 22 2d 2f 2f 57 33 43 2f 2f 44 54 44 20 48 54 4d 4c 20 34 2e 30 31 20 54 72 61 6e 73 ... >
{ encoding: 'SHIFT_JIS', confidence: 1 }
ちゃんとTITLEが表示されるようになりました!
そしてencoding未指定のため、bodyにはBufferが入ってきています。ので、後はエンコーディング的な処理でこねくり回してあげればOKです!