0
0

【Go】「http.Get」で取得したhtmlについて文字コードを考慮する

Posted at

概要

http.Getでhtmlを取得する際にGoでGETを使ってHTMLを文字列で取得してみるのような実装を行うと思います。大体のページはこれで大丈夫なのですが、ただこの実装だと文字コードutf-8以外だと文字化けしてしまいます。
というわけで、utf-8以外の文字コードが設定されたhtmlをどう取得するかのメモ書きを残しておきます。

対応方針

今回はstackoverflowのgolang HTML charset decodingの回答にある、charset.DetermineEncodingメソッドを使用する方法で試してみることとします。このstackoverflowの内容だと以下2点課題があったので、別途考慮しました。

一点目はcharset.DetermineEncodingでは、Determining the character encodingのドキュメントに説明がある通り、複数要素で文字コードを推論しているようです。そして、shift-jisのページだと判定時のcertainがfalseになってしまうことがあるようです(いくつかページを試してみたところ)。今回はcertainの結果は使用しない形にしました。

二点目は文字コード判定用で一度Readerでの読み込みが必要になるので、全部のhtmlを読み取る場合はこれを複製する必要があることです。対応は【golang】io.Readerを使いまわしてContentType判定、S3アップロードしたらハマった話の記事にいくつか紹介されていますが、今回はio.TeeReaderを使うこととしました。

実装サンプル

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net/http"

	"golang.org/x/net/html/charset"
	"golang.org/x/text/encoding/htmlindex"
)

func detectContentCharset(body io.Reader) string {
	r := bufio.NewReader(body)
	if data, err := r.Peek(1024); err == nil {
		// certainがfalseの場合もそのまま使う
		_, name, _ := charset.DetermineEncoding(data, "")
		if name != "" {
			return name
		}
	}
	return "utf-8"
}

func main() {
	// htmlページの取得
	// webPage := ("https://mayukasports.blogspot.com/")     // UTF-8のサイト
	webPage := ("http://abehiroshi.la.coocan.jp/top.htm") // Shift_JISのサイト
	resp, err := http.Get(webPage)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

	// 文字コードチェック用のreadのためにbodyをコピーしておく
	body := new(bytes.Buffer)
	bodyForCheck := io.TeeReader(resp.Body, body)
	// 文字コードの判定
	charset := detectContentCharset(bodyForCheck)
	encode, err := htmlindex.Get(charset)
	if err != nil {
		fmt.Println(err)
		return
	}

	// htmlのRead
	var contentBytes []byte
	if name, _ := htmlindex.Name(encode); name != "utf-8" {
		encodeBody := encode.NewDecoder().Reader(body)
		contentBytes, err = io.ReadAll(encodeBody)
	} else {
		contentBytes, err = io.ReadAll(body)
	}

	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(string(contentBytes))
}
0
0
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
0
0