LoginSignup
16
7

More than 3 years have passed since last update.

Fetch API で Shift_JIS の HTML をDOM として読み込む

Last updated at Posted at 2018-09-18

fetch で Shift_JIS を扱おうとしたら文字化けしたので、解決方法を書きます。

1. 流れ

  1. fetch で DOM として直接読み込むことはできない
  2. なので、一回 text として読み込んで DOM に parse する
  3. ところが、response.text() で文字コードが UTF-8 以外で文字化けし、解決方法は (おそらく) ない (Content-Typecharset を指定しても効果なし)
  4. なので、一度バイナリデータとして読み込み、文字コードを指定して文字列に変換し、そこから DOM に parse する

参考「JavaScriptのFetch APIで返ってきたものをDOMとして扱う - ひと夏の技術
参考「fetch APIでUTF8以外のエンコーディングだと辛い – 阿Qさんと一緒

2. ソースコード

2.1. 方法 1: Response -> Blob -> fileReader.readAsText()

(async () => {

    // 
    const readAsText = (blob, encoding = null) => new Promise(resolve => {
        const reader = new FileReader();
        reader.onload = () => { resolve(reader.result) };
        reader.readAsText(blob, encoding);
    });

    const parseHTML = html => new DOMParser().parseFromString(html, 'text/html');

    // 
    const url = '...';

    const response = await fetch(url);
    const blob = await response.blob();
    const html = await readAsText(blob, 'shift-jis');
    const dom = parseHTML(html);

    // 処理
    console.log(dom.head);

})();

2.2. 方法 2: Response -> ArrayBuffer -> textDecoder.decode()

TextDecoder が使用できるブラウザならこちらの方がシンプルに書けます。

※新 Edge は対応していないようです。

参考「TextDecoder - Web API | MDN

(async () => {

    // 
    const decodeAsText = (arrayBuffer, encoding = null) => new TextDecoder(encoding).decode(arrayBuffer);

    const parseHTML = html => new DOMParser().parseFromString(html, 'text/html');

    // 
    const url = '...';

    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    const html = decodeAsText(arrayBuffer, 'shift-jis');
    const dom = parseHTML(html);

    // 処理
    console.log(dom.head);

})();
16
7
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
16
7