【Go言語】TwitterAPIを使ってVtuberの画像を収集して保存する

#はじめに

好きな人の絵を保存したい......。

現在、Twitter上で、絵描きの人が様々な画像を投稿しています。

私は、Vtuberの方の絵をよく見るですが、上手いなあ、どっかに保存しておきたいなあ...と思いました。

私がよく見るVtuberの絵は、Twitterではハッシュタグによって投稿されていることが多いと気付き、どうにかできないのかと思い、調べながら、「収集ツール」を作りました。


#TwitterAPIを用いて画像をまとめて取得する

>ちなみにここでは私の好きな「兎田ぺこら」さんを取り上げたいと思います。

##必要な工程

・TwitterAPIの取得と認証
・収集する情報を設定(「#ぺこらーと」という文字列を含むツイート、100件取得など)
・保存した画像を入れておくためのファイルの作成など
・画像URLの取得
・jpgファイルとして保存


それでは一つずつ見ていきましょう。

#TwitterAPIの取得と認証

以下のサイトに飛び、TwitterAPIを取得するようにしてください。

[>>>TwitterAPIの取得](https://developer.twitter.com/en)

詳しいやり方などについては省略します。

ソースのはじめの方で定義しておいたら良いと思います。

```go

const (
	consumerKey       = ""
	consumerSecret    = ""
	accessToken       = ""
	accessTokenSecret = ""
)
```

#収集する情報を設定

ここでは、
>ツイートを何件取得するのか
リツイートも含むのか
画像がないツイートを含まないようにするか

などのクエリを設定します。

```go

    v := url.Values{}
    v.Set("count", "100")
	query := "ぺこらーと OR #ぺこらーと exclude:retweets filter:images"
	searchResult, _ := api.GetSearch(query, v)
```

ここでは、ツイート数を意味する"count"を使い、100件取得する。
次に、検索した文字列は　"ぺこらーと"　もしくは　"#ぺこらーと"　であるとし、
リツイートは含まない、画像が添付されているツイートのみに絞る。

####失敗ポイント
私は、この部分で設定できるのを知らず、ツイート内容を取得し、その中から画像内容が存在するかを判定していました。

#保存した画像を入れておくためのファイルの作成

普通に保存してしまうと、ごちゃごちゃしてしまうので、画像を保存するためのフォルダを作成します。
jsonファイルを作ったりする時も、他にフォルダを作った方が良いです。

>以下のソースコードでMkdirする時、0777という数字を使っていますが、これはファイルの権限についてを記述したものになります。
0:読込・書込・実行はできない
1:実行のみ可能
2:書き込みのみ可能
3:書き込み、実行が可能
4:読み込みのみ可能
5:読み込み、実行可能
6:読み込み、書き込みが可能
7:読み込み、実行、書き込みが可能
では、3桁あるのはなぜ？と思ったのではないでしょうか？
これは、上から順に
・ファイルやディレクトリの所有者(作成者）の権限
・作成したユーザーと同じグループの他ユーザーの権限
・それ以外のユーザーの権限
[参考にした記事はこちら](https://www.sejuku.net/blog/tutorial/115549)


```go
//カレントディレクトリを絶対パスで設定
currentDir, err := filepath.Abs(".")
//Chdirは、イメージとしてはコマンドで $cd している感じ
    err = os.Chdir(currentDir)
	if err != nil {
		panic(err)
	}
//ファイルの確認
	_, err = os.Stat("pekorato")
	if err != nil {
//ここでMkdirによりフォルダを作成する
		err = os.Mkdir("pekorato", 0777)//0777については上で詳しく解説
		if err != nil {
			panic(err)
		}
	}
//ディレクトリを移動し、画像をここにまとめて保存する
	err = os.Chdir(currentDir + "/pekorato")
	if err != nil {
		panic(err)
	}
```
#画像URLの取得

画像のURLを取得するのは以外にも簡単なんです。
細かい部分を省くと、以下のコード1行で収集できます。

逆に言えば、tweet.の後を書き換えることによって、違う情報を得ることができます。
例えば、tweet.User.ProfileImageURLを用いると、そのユーザのプロフィールの画像のURLを得ることができます。

```go

mediaRawURL := tweet.ExtendedEntities.Media[0].Media_url_https
```

#jpgファイルとして保存

保存というより、コピーに近いのではないかと思います。
はじめにhttp.Getをしていますが、ここは少しhttpの知識が必要になります。
getメソッドを送れば、何が返されるのか？など、知らない人は軽く調べてみると良いでしょう。

```go

        response, err := http.Get(mediaRawURL)
			if err != nil {
			panic(err)
		}
		defer response.Body.Close()

		//jpgファイルを生成
		pekoPic, err := os.Create(fmt.Sprintf("pekora%d.jpg", i))
		if err != nil {
			panic(err)
		}
		defer pekoPic.Close()

		//ダウンロードしたpekoPicにコピー
		io.Copy(pekoPic, response.Body)
```


#全体のソースコード

```go

package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"

	"github.com/ChimeraCoder/anaconda"
)

//ここは各自で入れるようにしてください。
const (
	consumerKey       = ""
	consumerSecret    = ""
	accessToken       = ""
	accessTokenSecret = ""
)

func main() {
	//Twitterの認証
	anaconda.SetConsumerKey(consumerKey)
	anaconda.SetConsumerSecret(consumerSecret)

	//個人の認証
	api := anaconda.NewTwitterApi(accessToken, accessTokenSecret)

	/*************
	検索クエリの設定
	**************/
	v := url.Values{}
	v.Set("count", "100")
	query := "ぺこらーと OR #ぺこらーと exclude:retweets filter:images"
	searchResult, _ := api.GetSearch(query, v)

	/**********************************************
	画像を保存するためのフォルダの作成と、ディレクトリの移動
	**********************************************/

	currentDir, err := filepath.Abs(".")
	if err != nil {
		panic(err)
	}

	_, err = os.Stat("pekorato")
	if err != nil {
		err = os.Mkdir("pekorato", 0777)
		if err != nil {
			panic(err)
		}
	}

	err = os.Chdir(currentDir + "/pekorato")
	if err != nil {
		panic(err)
	}

	/********************************
	ツイートを解析し、画像を生成
	********************************/

	for i, tweet := range searchResult.Statuses {
		mediaRawURL := tweet.ExtendedEntities.Media[0].Media_url_https

		response, err := http.Get(mediaRawURL)
		if err != nil {
			panic(err)
		}
		defer response.Body.Close()

		pekoPic, err := os.Create(fmt.Sprintf("pekora%d.jpg", i))
		if err != nil {
			panic(err)
		}
		defer pekoPic.Close()

		io.Copy(pekoPic, response.Body)
	}
}

```



#まとめ
今回は、画像を取得するためにTwitterAPIを用いました。
次は、ある特定の人のツイートした画像を取得するようなものでも作ってみようかと思いました。
ご覧になられた方、ありぺこでした。