golangの AriticleExtractor "GoOse" を試してみる

# 追記
取得できる要素を詳細にしました(2016/02/02)。

# 目的
golangのArticle Extractorである”GoOse”を試してみる。

# 概要

ArticleExtractorとはWebページのタイトルやメインコンテンツ、メイン画像、その他諸々の要素を判別して抽出するライブラリのことです。

golangでスクレイピングをするときはjQueryライクに処理を書ける”goquery”が有名でよく使われていると思います。
ただ不特定多数のWebサイトから狙い撃った要素をスクレイピングしたいときはArticleExtractorライブラリである"GoOse"があります。

[https://github.com/advancedlogic/GoOse](https://github.com/advancedlogic/GoOse)

別にScala製で"goose"というArticleExtractorがありますが、それとの関係は不明です。
まったく無いということはなさそうですが...

[https://github.com/jiminoc/goose](https://github.com/jiminoc/goose)

また"golang goose" でググると同名のgolang製DBマイグレーションツールばかり引っかかるのでググラビリティは低いです。

# 使い方

## URLまたはHTMLを指定する

urlString, rawHTMLはともにstringです。
（ExtractFromRawHTML(rawHtml)のほうは試したことはありません。）

```go
g := goose.New()
article, err := g.ExtractFromURL(urlString)
// または
article, err := g.ExtractFromRawHTML(rawHtml)
```

## 戻り値 article から必要なプロパティを取得する

戻り値 articleから取得できるプロパティは20個あります。
READMEには書かれていません。


- AdditionalData
[GitHubリポジトリ](https://github.com/advancedlogic/GoOse/search?utf8=%E2%9C%93&q=additionaldata)で検索したところ Article struct で定義されているのみ。

- CanonicalLink
goqueryでlink[rel=canonical]を探して取得しています。

- CleanedText
TopNodeから優先度の低いノードを削除し、段落やstrongなどの装飾タグなどを綺麗に整理したもの。

- Doc
*goquery.Document

- Delta
time.Now().UnixNano()

- Domain
url.Parse(CanonicalLink).Host

- FinalURL
基本的にはWebサイトのURL？

- LinkHash
こんな感じで作ってます。どういう役割なのかはよくわかりません。

```go
h := md5.New()
io.WriteString(h, url)
bytes := h.Sum(nil)
linkHash = fmt.Sprintf("%s.%d", string(bytes), time.Now().UnixNano())
```
- Links
TopNode内のaタグから画像リンク以外のhrefをsliceにしたものです。

- MetaDescription
meta[name="description"]

- MetaFavicon
Webサイトのソース内にfaviconファイルがあった場合はそれを使用。
なかった場合は link[rel="icon"]を探してそのhrefを取得。

- MetaKeywords
meta[name="keywords"]

- MetaLang
html[lang]

- Movies
"iframe", "embed", "object", "video"タグを探して取得？

- PublishDate
[GitHubリポジトリ](https://github.com/advancedlogic/GoOse/search?utf8=%E2%9C%93&q=publishdate)で検索したところ Article struct で定義されているのみ。

- RawHTML
生のHTML文字列

- Tags
a[rel=tag]のテキストを取得

- Title
タイトルっぽい要素（meta[property="og:title"]やtitle,post-title,headlineタグ）を探して取得

- TopImage


- TopNode

# 試してみる
Qiita Blogのエントリで実際に試してみます。

[ユーザページでcontribution数やフォロワー数の推移が見られるようになりました](http://blog.qiita.com/post/136806363764/new-users-page)

```go
package main

import (
    "github.com/advancedlogic/GoOse"
)

func main() {
    g := goose.New()
    article := g.ExtractFromURL("http://blog.qiita.com/post/136806363764/new-users-page")
    println("title", article.Title)
    println("description", article.MetaDescription)
    println("keywords", article.MetaKeywords)
    println("content", article.CleanedText)
    println("url", article.FinalURL)
    println("top image", article.TopImage)
}
```

**Title**
ユーザページでcontribution数やフォロワー数の推移が見られるようになりました

**MetaDescription**
ユーザページでcontribution数やフォロワー数の推移が見られるようになりました こんにちは、yuku_tです。小寒が過ぎてから朝起きるのがつらいです。 さて、このたびユーザページのデザインがリニューアルされました！ 一番大きな変化はなんといっても大きく目を引くグラフが追加されたことでしょう。過去30日間の数値の変化を確認することができます。画面中央の「Followers」の箇所をクリックする...

**MetaKeywords**
qiita

**CleanedText**
ユーザページでcontribution数やフォロワー数の推移が見られるようになりました

**FinalURL**
http://blog.qiita.com/post/136806363764/new-users-page

**TopImage**
http://increments.github.io/blog.qiita.com/images/og_image.png

---
もう一つ、もう少しゴタゴタしたページで試してみます。

[Qiitaが変えるエンジニアの「情報共有の世界」CTO髙橋侑久が語る『仕事の流儀』（前編）](https://codeiq.jp/magazine/2016/01/36482/)

**Title**
Qiitaが変えるエンジニアの「情報共有の世界」CTO髙橋侑久が語る『仕事の流儀』（前編）｜CodeIQ MAGAZINE

**MetaDescription**
なし

**MetaKeywords**
cto,increments,qiita,髙橋侑久

**CleanedText**
Qiitaが変えるエンジニアの「情報共有の世界」CTO髙橋侑久が語る『仕事の流儀』（前編）｜CodeIQ MAGAZINE

**FinalURL**
https://codeiq.jp/magazine/2016/01/36482/

**TopImage**
https://codeiq.jp/magazine/wp-content/uploads/2016/01/46A0242.jpg

# まとめ

なんかぱっとしない感じになってしまいました。
とりあえずもっといいのがあったら教えて下さい。