m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

golangでRSS2のデータを取得して表示

XMLを取得してパースする

RSSを取得して一覧を表示するサンプルを作成する

参考

[Golang] XML Parsing Example (7) - Parse RSS 2.0
Atomや両方対応のパターンもあります

静的ファイルも参照したい

jsとかcssとか使用したいけどどうやって参照するか
web applications - Serving static content with a root URL with the Gorilla toolkit - Stack Overflow

実装

構成
.
├── main.go
├── static
│   ├── css
│   │   ├── bootstrap-theme.css
│   │   ├── bootstrap-theme.css.map
│   │   ├── bootstrap-theme.min.css
│   │   ├── bootstrap-theme.min.css.map
│   │   ├── bootstrap.css
│   │   ├── bootstrap.css.map
│   │   ├── bootstrap.min.css
│   │   └── bootstrap.min.css.map
│   ├── fonts
│   │   ├── glyphicons-halflings-regular.eot
│   │   ├── glyphicons-halflings-regular.svg
│   │   ├── glyphicons-halflings-regular.ttf
│   │   ├── glyphicons-halflings-regular.woff
│   │   └── glyphicons-halflings-regular.woff2
│   └── js
│       ├── bootstrap.js
│       ├── bootstrap.min.js
│       ├── jquery-2.2.0.min.js
│       ├── jquery-2.2.0.min.map
│       └── npm.js
└── templates
    └── index.html
main.go
package main

// インポート
import (
	"log"
	"net/http"
	"html/template"
	"github.com/gorilla/mux"
	"io/ioutil"
	"encoding/xml"
)

// RSS2用の構造体
type Rss2 struct {
	XMLName		xml.Name	`xml:"rss"`
	Version		string		`xml:"version,attr"`
	// Required
	Title		string		`xml:"channel>title"`
	Link		string		`xml:"channel>link"`
	Description	string		`xml:"channel>description"`
	// Optional
	PubDate		string		`xml:"channel>pubDate"`
	ItemList	[]Item		`xml:"channel>item"`
}

// RSS2の各記事の部分(Item)
type Item struct {
	// Required
	Title		string		`xml:"title"`
	Link		string		`xml:"link"`
	Description	template.HTML	`xml:"description"`
	// Optional
	Content		template.HTML	`xml:"encoded"`
	PubDate		string		`xml:"pubDate"`
	Comments	string		`xml:"comments"`
}

// 主処理
func main(){

	// ルーティング初期化
	r := mux.NewRouter()

	// 静的ファイルをサポート
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

	// url別処理
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
		// httpよりRSS取得
		_rssURL := "http://m-shige1979.hatenablog.com/rss"
		res, err := http.Get(_rssURL)
		if err != nil {
			panic(err)
		}

		// text形式で読み込む
		asText, err2 := ioutil.ReadAll(res.Body)
		if err2 != nil {
			panic(err2)
		}

		// rss2構造体を定義
		rssData := Rss2{}

		// パースして格納
		err3 := xml.Unmarshal(asText, &rssData)
		if err3 != nil {
			panic(err3)
		}

		// テンプレート生成
		tmpl := template.Must(template.New("index").ParseFiles("templates/index.html"))
		// 変数を設定
		tmpl.Execute(w, struct{
			RssItemList []Item
		}{
			RssItemList: rssData.ItemList,
		})

		// url
		log.Println(r.URL.Path)
	})

	// ルーティング設定
	http.Handle("/", r)

	// ポート待ち
	log.Println(":9001")
	http.ListenAndServe(":9001", nil)
}
templates/index.html
{{ define "index" }}
<!DOCType html>
<html>
<head>
	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>websample3</title>
	<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
</head>
<body>
	<div class="container-fluid">
		<div class="row">
			<div class="col-xs-12">
				<h3>RSSリスト</h3>
			</div>
		</div>
		<div class="row">
			<div class="col-xs-12">
				{{ range .RssItemList }}
				<div>
					<blockquote>
						<p>{{ .PubDate }}</p>
						<p>{{ .Title }}</p>
						<footer>
							<a href="{{ .Link }}" target="_blank">{{ .Link }}</a>
						</footer>
					</blockquote>
				</div>
				{{ end }}
			</div>
		</div>
	</div>
	<script src="/static/js/jquery-2.2.0.min.js"></script>
	<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
{{ end }}

結果

f:id:m_shige1979:20160211183714p:plain

所感

xmlの解析がなんかいい感じにやってくれたので助かる。
atomなどと一緒にやる場合は多少手間がかかるみたいですけど
構造体の仕組みをちょっと調べないと…