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が取得できた。