ツイート→絵日記 を作るツール

# 日記生成ツールの紹介と実装解説

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411120/b200b5b6-6a63-444d-921e-802f6d65b29c.png)

## 概要

本記事では、X（旧Twitter）から取得したツイートと天気データを組み合わせて日記を生成し、さらにその日記から画像生成に必要な要素を抽出するツールの実装について解説します。このツールは、Pythonを使用して構築されており、外部APIを活用してデータ取得や生成を行います。

## ソース
https://github.com/Syogo-Suganoya/inkpost

## サンプル
### Input

```json
[
  {
    "created_at": "2023-05-01 00:10:00",
    "text": "今日カフェで勉強してたんだけど、隣の席の人がイケメンすぎて全然集中できなかった…‍♀️"
  },
  {
    "created_at": "2023-05-01 00:10:00",
    "text": "課題多すぎ…終わる気がしない…誰か助けて…"
  },
  {
    "created_at": "2023-05-03 00:10:00",
    "text": "新しいスニーカー買った！めっちゃ可愛い✨ 明日どこ履いて行こうかな？"
  },
  {
    "created_at": "2023-05-03 00:10:00",
    "text": "バイト疲れたー。でも、給料日近いから頑張るしかない"
  },
  {
    "created_at": "2023-05-03 00:10:00",
    "text": "今日のランチは友達と話題のラーメン屋さんへ めちゃくちゃ美味しかった！"
  }
]
```

### Output

<img width=25%><img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411120/3c6627f5-540c-451d-b631-70ea6544db0f.png">


今日は、カフェで勉強しようと意気込んで出かけたんだけど、まさかの展開に見舞われてしまった…。隣の席に座った人が、とんでもなくかっこいい人でね、もう全然集中できなかったんだよね…！教科書を開いてはみたものの、気づけば彼の横顔をちらちらと見てしまっていて、肝心の課題は全然進まず…。
課題は山積みだし、全然終わる気がしないしで、もう八方塞がりって感じ。本当、誰か助けてほしいよ…。せめて、集中力を高める魔法とかあればいいのに！
明日は、今日の分も頑張って課題を終わらせないと、もう本当にやばいことになりそう。あのイケメンさん、明日もカフェにいるかな…？…いやいや、今は集中！集中！課題に集中して、少しでも進められるように頑張ろう。とりあえず、今日は早く寝て、明日に備えよう。

---

2023-05-02: 快晴
何もありませんでした。

---

<img width=25%><img width=50% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411120/3d57f245-8a33-41ca-824e-e50b1e4010d3.png">


2023-05-03: 晴時々薄曇
今日は、なんだか嬉しいことと少し疲れたことと、美味しいことで盛りだくさんの一日だったな！
まず、一番嬉しかったのは、新しいスニーカーを買ったこと！お店で見た瞬間、もう「可愛い！」って目がハートになっちゃって、即決だった。家に帰って改めて眺めていたら、ますます気に入っちゃって、ニヤニヤが止まらないの。明日はどこに履いて行こうかな？ おしゃれして、どこかにお出かけしたいな！
午後からはバイトだったんだけど、今日はなんだかいつも以上に疲れてしまって…。でも、もうすぐ給料日！それを楽しみに、頑張って乗り切ったよ！頑張った自分を褒めてあげたいな。
そして、今日のランチは、友達と話題のラーメン屋さんに行ってきたんだ！ 噂通り、めちゃくちゃ美味しくて、スープも全部飲んでしまった！友達と美味しいものを一緒に食べるって、本当に幸せだよね。
明日は新しいスニーカーを履いて、どこに出かけようかな。バイトも頑張って、楽しい週末を過ごしたいな！





## 主な機能

1. **ツイート取得**
   - 指定されたユーザーのツイートを取得します。
   - モックデータを使用するオプションもあります。
2. **天気データ取得**
   - 指定された期間と場所の天気データを取得します。
3. **日記生成**
   - ツイート内容を日記形式に変換します。
4. **画像生成**
   - 日記の内容からシチュエーションや登場人物を抽出し、画像生成APIを利用して画像を生成します。
5. **ファイル出力**
   - 生成された日記と画像を指定のディレクトリに保存します。

## 処理の流れ

### 1. 引数の解析

プログラムはコマンドライン引数を受け取り、モックデータを使用するか、実際のデータを使用するかを切り替えます。

```python
def parse_args():
    parser = ArgumentParser(description="日記生成ツール")
    parser.add_argument("--mock", action="store_true", help="モックデータを使用する")
    parser.add_argument("--user_name", type=str, help="Xのユーザー名")
    parser.add_argument("--location_name", type=str, help="天気の取得に使う地名")
    parser.add_argument("--start_date", type=str, help="開始日 (YYYY-MM-DD)")
    parser.add_argument("--end_date", type=str, help="終了日 (YYYY-MM-DD)")
    return parser.parse_args()
```

### 2. メタデータの読み込み

ツイートや天気データを取得するためのメタデータを読み込みます。

```python
def _load_metadata(self):
    if args.mock:
        self.user_name = "mock_user"
        self.location_name = "東京"
        self.start_date = datetime.strptime("2023-05-01", "%Y-%m-%d")
        self.end_date = datetime.strptime("2023-05-02", "%Y-%m-%d")
        self.tweets = x_api.get_user_tweets_mock()
    else:
        self.user_name = args.user_name
        self.location_name = args.location_name
        self.start_date = datetime.strptime(args.start_date, "%Y-%m-%d")
        self.end_date = datetime.strptime(args.end_date, "%Y-%m-%d")
        self.tweets = x_api.get_user_tweets(self.user_name)
```

### 3. 天気データの取得

指定された期間の天気データを取得します。

```python
def _load_weather_data(self):
    months = {(self.start_date.year, self.start_date.month), (self.end_date.year, self.end_date.month)}
    for year, month in months:
        if args.mock:
            path = f"mock/weather/{year}{month:02d}.json"
            raw = text.load_json(path)
        else:
            raw = whether.get_past_weather(self.location_name, year, month)
        daily = whether.extract_daily_weather(raw)
        self.weather_data.update(daily)
```

### 4. 日記生成

ツイート内容を日記形式に変換します。

```python
def tweet_to_diary(tweet_text):
    prompt_template = text.read_text_file("prompt/tweet_to_diary.txt")
    prompt = prompt_template.replace("###TWEET_TEXT###", tweet_text)
    result = gemini_api.query(prompt)
    return result
```

### 5. 画像生成

生成された日記から画像生成に必要な要素を抽出し、画像を生成します。

```python
def extract_diary_for_image(diary_text):
    prompt_template = text.read_text_file("prompt/diary_to_situation.txt")
    prompt = prompt_template.replace("###DIARY_TEXT###", diary_text)
    result = gemini_api.query(prompt)
    return result
```

## 実行方法

1. 実際のデータを使用して実行する場合：

    ```bash
    python src/main.py --user_name <ユーザー名> --location_name <地名> --start_date <開始日> --end_date <終了日>
    ```

2. モックデータを使用して実行する場合：

    ```bash
    python src/main.py --mock
    ```

## 使用技術

- **外部API**
  - 天気データ取得: [気象データ Web API](https://www.cultivationdata.net/weather-web-api.html)
  - 画像生成: Gemini
  - ツイート取得: Tweepy

## まとめ

このツールは、ツイートと天気データを組み合わせて日記を生成し、さらに画像生成まで行うユニークなアプローチを採用しています。今後は、天気データ取得を気象庁APIに変更するなど、さらなる改善を予定しています。