htmlから本文を取得してみる。

package main

import (
	"bufio"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
)

func main() {
	url := "https://saitodev.co/article/%E3%83%A4%E3%83%96%E3%82%AC%E3%83%A9%E3%82%B7%E3%81%AE%E5%9F%B7%E5%BF%B5"
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Fatal(err)
	}

	readMode := false
	var content string
	reader := bufio.NewReader(resp.Body)
	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		} else if err != nil {
			log.Fatal(err)
		}

		n := strings.Index(line, "post-content")
		if n >= 0 {
			if readMode == false {
				readMode = true
				continue
			} else {
				break
			}
		}

		if readMode == true {
			content = content + line
		}

	}
	file, err := os.Create("test.html")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	file.Write([]byte(content))
}

植物のミカタの任意のページのurlを取得する。Getでurlのソースコードを取得する。この中から本文のみ切り出したいので、本文の始まりと終わりの目印を探す。植物のミカタの記事詳細ページのHTMLは、


/** ヘッダやページのタイトルのHTML **/

<div class="post-content image-caption-format-1 entry">
	/** 本文が記述されている箇所 **/
</div><!-- .post-content -->

/** サイドバーやフッタのHTMLが続く **/

このような構成になっており、

<div class="post-content">で始まりコメントのpost-contentの記述で終わるので、post-contentがあるところを本文の切りだしの目印にする。次にreadMode := falseで、post-contentを見つけたらtrue、見つけなかったらfalseにするスイッチを作成しておく。最初はfalseにしておく。本文の中身を入れる変数をvar content stringで作成する。

NewReaderでresp.BodyのBodyの部分だけをReader型の構造体で取り出す。 reader.ReadStringで構造体の中の一文ずつを切りだす(一文の区切りは\nで認識)。

n := strings.Index(line, "post-content")でlineの中にpost-contentが含まれるか検索する。post-contentが開始されるインデックスがint型で返るのでn > 0であれば、post-contentがlineに含まれていることになる。

if n >= 0 で、post-contentがあれば、readModeがfalseであれば、readMode = trueにして、continueによりforから始まる一番上の行に返り、lineを一行づつ読み込む。post-contentがないので、次は、if readMode == true に続き、content = content + lineでhtmlの本文を記録す、これをpost-contentが見つかるまで繰り返す。

本文の最後に記載されたpost-contentが見つかったら、if n >= 0 に戻るが、その際はreadModeがtrueのままになっているので、 if readMode == falseの条件を満たさないので、else に移り breakして、本文の読み込みを停止する。

os.Createでファイルを作成し、file.Writeでcontentの中身を書き込む。

これで本文だけのhtmlが取得できた。