GoでRSSフィードを取得・解析する方法を解説。標準ライブラリのnet/http・encoding/xmlを使う方法と、gofeedでRSS・Atomをまとめて扱う方法を紹介します。
Goでは、標準ライブラリのnet/httpとencoding/xmlを使ってRSSフィードを取得・解析できます。
RSSだけでなくAtomなど複数形式のフィードを扱いたい場合は、gofeedのようなフィード解析ライブラリを使う方法もあります。
この記事では、GoでRSSを取得する基本的な方法から、記事タイトル・URL・公開日時を取り出すところまで紹介します。
主な方法は次の2つです。
| 方法 | 向いている用途 |
|---|---|
net/http + encoding/xml | RSS 2.0など決まった形式をシンプルに扱う |
gofeed | RSS・Atom・JSON Feedなど複数形式をまとめて扱う |
取得するRSSの形式が決まっているなら標準ライブラリだけでも実装できます。
さまざまなWebサイトのフィードを受け付けるアプリでは、複数形式を吸収してくれるライブラリを使う方が扱いやすくなります。
まずRSS URLへHTTP GETリクエストを送ります。
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
resp, err := http.Get("https://example.com/rss.xml")
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
panic(fmt.Sprintf("HTTP error: %s", resp.Status))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
http.Getで取得したレスポンスのBodyは、処理が終わったらCloseします。
実際のアプリでは、HTTPステータスコードの確認やタイムアウトも設定した方が安全です。
RSS 2.0はXML形式なので、Go標準ライブラリのencoding/xmlで解析できます。
まずRSSに対応する構造体を定義します。
type RSS struct {
Channel Channel `xml:"channel"`
}
type Channel struct {
Title string `xml:"title"`
Description string `xml:"description"`
Link string `xml:"link"`
Items []Item `xml:"item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
PubDate string `xml:"pubDate"`
GUID string `xml:"guid"`
}
取得したXMLをxml.Unmarshalへ渡します。
var rss RSS
if err := xml.Unmarshal(body, &rss); err != nil {
panic(err)
}
fmt.Println(rss.Channel.Title)
for _, item := range rss.Channel.Items {
fmt.Println(item.Title)
fmt.Println(item.Link)
fmt.Println(item.PubDate)
}
これでRSSから、
などを取得できます。
RSS URLから記事一覧を取得するところまでまとめると、次のようになります。
package main
import (
"encoding/xml"
"fmt"
"net/http"
)
type RSS struct {
Channel Channel `xml:"channel"`
}
type Channel struct {
Title string `xml:"title"`
Items []Item `xml:"item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
PubDate string `xml:"pubDate"`
}
func main() {
resp, err := http.Get("https://example.com/rss.xml")
if err != nil {
panic(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
panic(fmt.Sprintf("HTTP error: %s", resp.Status))
}
var rss RSS
if err := xml.NewDecoder(resp.Body).Decode(&rss); err != nil {
panic(err)
}
fmt.Println(rss.Channel.Title)
for _, item := range rss.Channel.Items {
fmt.Printf("%s\n%s\n%s\n\n",
item.Title,
item.Link,
item.PubDate,
)
}
}
xml.NewDecoderを使えば、レスポンス本文を一度すべて文字列へ読み込まず、そのまま解析できます。
実際のアプリでは、外部RSSが応答しない場合に備えてタイムアウトを設定します。
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Get("https://example.com/rss.xml")
RSSは自分のアプリとは別のサーバーから取得するため、
などが発生する前提で実装しておく方が安全です。
サイトによっては、User-Agentなしのアクセスを拒否する場合があります。
その場合はhttp.NewRequestを使います。
req, err := http.NewRequest(
http.MethodGet,
"https://example.com/rss.xml",
nil,
)
if err != nil {
panic(err)
}
req.Header.Set("User-Agent", "MyRSSReader/1.0")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
多数のRSSを取得するサービスでは、サービス名が分かるUser-Agentを設定する方法もあります。
取得するRSSがRSS 2.0で統一されているなら、標準ライブラリだけでも比較的簡単に実装できます。
ただし、実際のWebサイトでは、
などが混在しています。
不特定多数のサイトからフィードを登録できるRSSリーダーを作る場合は、すべてを自分で吸収するのは大変です。
複数形式のフィードを扱いたい場合は、Go向けライブラリgofeedがあります。
インストールします。
go get github.com/mmcdole/gofeed
基本的な使い方はシンプルです。
package main
import (
"fmt"
"github.com/mmcdole/gofeed"
)
func main() {
fp := gofeed.NewParser()
feed, err := fp.ParseURL("https://example.com/rss.xml")
if err != nil {
panic(err)
}
fmt.Println(feed.Title)
for _, item := range feed.Items {
fmt.Println(item.Title)
fmt.Println(item.Link)
fmt.Println(item.Published)
}
}
gofeedはRSS、Atom、JSON Feedなどを解析し、共通のFeedモデルとして扱えます。
RSSかAtomかを利用側で細かく意識したくない場合に便利です。
たとえばサイトAがRSS 2.0、サイトBがAtomだったとしても、gofeedなら同じコードから扱えます。
fp := gofeed.NewParser()
feed, err := fp.ParseURL(feedURL)
if err != nil {
return err
}
for _, item := range feed.Items {
fmt.Println(item.Title)
fmt.Println(item.Link)
}
不特定多数のサイトを登録できるRSSサービスでは、このような統一モデルが扱いやすくなります。
2026年9月12日時点のgofeedは、RSS 0.90〜2.0、Atom、JSON Feedなど複数形式に対応しています。
gofeedではContext付きでURLを解析することもできます。
ctx, cancel := context.WithTimeout(
context.Background(),
10*time.Second,
)
defer cancel()
fp := gofeed.NewParser()
feed, err := fp.ParseURLWithContext(
"https://example.com/rss.xml",
ctx,
)
if err != nil {
panic(err)
}
外部RSSを取得する処理では、無制限にレスポンスを待たないようタイムアウトを設定しておく方が安全です。
RSSの記事にはpubDateが入っていることがあります。
たとえば、
<pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate>
のような形式です。
ただし、すべてのフィードが同じ日時形式を使うとは限りません。
RSSだけでなくAtomなども扱う場合は、日時フォーマットの違いも考慮する必要があります。
gofeedでは解析済み日時をPublishedParsedやUpdatedParsedから取得できる場合があります。
if item.PublishedParsed != nil {
fmt.Println(*item.PublishedParsed)
}
日時をソートやDB保存に利用するなら、文字列ではなく解析済みの時刻を扱う方が便利です。
RSSを定期取得すると、毎回同じ記事がフィードに含まれます。
そのため、新着記事だけ処理するには重複判定が必要です。
候補になるのは、
などです。
一般的にはGUIDが利用できればGUIDを使い、存在しない場合はURLなどを使って判定します。
for _, item := range feed.Items {
if alreadyExists(item.GUID) {
continue
}
save(item)
}
RSSを定期監視するサービスでは重要な処理です。
RSSを取得できるからといって、数秒おきにアクセスする必要はありません。
RSSは更新頻度に合わせて適切な間隔で取得します。
HTTPレスポンスの、
を利用すれば、変更されていないフィードを毎回すべて取得する処理も減らせます。
多数のRSSを扱う場合は、取得間隔やキャッシュも設計に含めます。
最終的には用途で選べます。
| 要件 | 方法 |
|---|---|
| RSS 2.0だけ解析する | encoding/xml |
| 外部ライブラリを増やしたくない | 標準ライブラリ |
| RSS・Atomを両方扱う | gofeed |
| 不特定多数のフィードを扱う | gofeed |
| XML構造を細かく制御したい | encoding/xml |
学習目的なら、まずnet/httpとencoding/xmlで実装するとRSSの構造も理解しやすくなります。
実際のRSSリーダーや収集サービスでは、複数形式への対応を考えてライブラリを使う方法があります。
GoでRSSを取得するには、最初にRSS URLが必要です。
サイトURLしか分からない場合は、HTMLのlink要素からRSSやAtomを検出する方法もあります。
手作業で探す場合は、RSS URLの見つけ方も参考にしてください。
GoでRSS取得処理を実装するときも、まず対象フィードにどんな記事が流れているか確認すると設計しやすくなります。
NagooFeedではRSS URLを登録して、新着記事をブラウザから確認できます。
情報確認日:2026年9月12日