実装ハンズオン

【Dify】X APIでソーシャルリスニング Part4:スプレッドシートにデータを格納

更新:

連載シリーズ

X APIを用いたソーシャルリスニング

全5回・X API × Dify・投稿収集からラベル付与・シート格納まで

  1. 概要:全体像と狙い
  2. X(旧Twitter) APIの基礎
  3. DifyでX APIから直近のポストを取得
  4. LLMで自動データラベル付与
  5. スプレッドシートに格納

目次

1. はじめに

本記事は、Difyのワークフローを使って、X(旧Twitter)のソーシャルリスニングを自動化するシリーズのPart 4です。

Part 3の復習: 前回の記事では、取得したツイートデータに対してLLMで感情ラベル付与、健康関連性の判定、カテゴリ分類、健康トピック • デバイストピックの抽出を行い、元データと統合する処理を解説しました。具体的には、以下のノードを実装しました。

  1.  LLM処理(感情ラベル判定 • 健康関連性判定 • カテゴリ分類 • トピック抽出)
  2.  データ統合(LLM結果と元データのマージ)

Part 4(本記事)では、統合したデータをCSV形式に変換し、Google Apps Script(GAS)に送信してスプレッドシートに保存する処理を詳しく解説します。これにより、ユーザーはスプレッドシートで分析結果を確認できるようになります。

シリーズ構成

  • Part 0: X APIを用いたソーシャルリスニング概要
  • Part 1: X 旧Twitter) APIの基礎
  • Part2: Difyを用いてX APIから直近のポストを取得する
  • Part 3: LLMを用いて自動でデータラベルを付与する
  • Part 4(本記事): スプレッドシートにデータを格納する
  • Part 5: Streamlitを用いたデータの可視化例

2. Part 3からの流れ

Part 3で統合したデータは、以下のような構造になっています。

{
  "data": [
    {
      "tweet_id": "1234567890",
      "search_keyword": "Apple Watch",
      "created_at": "2025-01-14T12:00:00.000Z",
      "author_id": "987654321",
      "text": "Apple Watchの心拍数と睡眠トラッキングが便利...",
      "retweet_count": 10,
      "reply_count": 5,
      "like_count": 20,
      "quote_count": 2,
      "sentiment_label": "positive",
      "sentiment_reasoning":  "健康管理機能への満足度が高い内容",
      "is_health_related": true,
      "category": "health_monitoring",
      "health_topics": ["心拍モニタリング", "睡眠トラッキング"],
      "device_topics": ["バッテリー寿命"],
      "tokens": ["Apple Watch", "心拍数", "睡眠トラッキング"],
      "post_url": "<https://x.com/i/web/status/1234567890>"
    }
  ],
  "meta": {
    "result_count": 20
  }
}

本記事では、この統合データに対して、以下の処理を行います。

  1.   CSV形式への変換(カラム定義、データ整形)
  2.   GASへのHTTPリクエスト(POST, JSON形式)
  3.   スプレッドシートへの自動保存

3. 各ノードの詳細解説

3-1. GAS送信用のCSV作成(Codeノード)

GAS送信用のCSV作成(Codeノード)

統合済みのツイートデータを、Google Apps Script(GAS)に送信するためのCSV形式に変換するノードです。

入力変数

変数名 ソース
rows データ統合ノード array[object]

コード

import csv
import io
from typing import List, Dict, Any

def main(rows: List[Dict[str, Any]]):
  # CSV出力用のStringIOオブジェクトを作成
  output = io.StringIO()
  writer = csv.writer(output)

  # CSVのヘッダー行を定義
  headers = [
    "tweet_id",
    "search_keyword",
    "created_at",
    "author_id",
    "text",
    "retweet_count",
    "reply_count",
    "like_count",
    "quote_count",
    "post_url",
    "sentiment_label",
    "sentiment_reasoning",
    "is_health_related",
    "category",
    "health_topics",
    "device_topics",
    "tokens",
  ]
  writer.writerow(headers)

  # 各ツイートデータをCSV行に変換
  for row in rows:
    # adverse_eventsは配列なので、パイプ区切り文字列に変換
    adverse_events = row.get("adverse_events") or []
    if isinstance(adverse_events, list):
      adverse_events_str = "|".join(adverse_events)
    else:
      adverse_events_str = str(adverse_events)

    # tokensも配列なので、パイプ区切り文字列に変換
    tokens = row.get("tokens") or []
    if isinstance(tokens, list):
      tokens_str = "|".join(tokens)
    else:
      tokens_str = str(tokens)

    #  テキスト内の改行をスペースに置換(CSVの可読性向上)
    text = row.get("text", "")
    text = text.replace("\\n", " ")

    # CSV行を生成
    writer.writerow([
      row.get("tweet_id", ""),
      row.get("search_keyword", ""),
      row.get("created_at", ""),
      row.get("author_id", ""),
      text,
      row.get("retweet_count", 0),
      row.get("reply_count", 0),
      row.get("like_count", 0),
      row.get("quote_count", 0),
      row.get("post_url", ""),
      row.get("sentiment_label", "") or "",
      row.get("sentiment_reasoning", "") or "",
      row.get("is_health_related", "") or "",
      row.get("category", "") or "",
      health_topics_str,
      device_topics_str,
      tokens_str,
    ])

  # CSV文字列を取得
  csv_string = output.getvalue()
  output.close()

  return {
    "csv_output": csv_string
  }

処理の流れ

  1. CSV出力準備: io.StringIO() でメモリ上にCSV出力用のバッファを作成
  2. ヘッダー行の生成: 19個のカラムを定義(tweet_id, search_keyword, created_at等)
  3. データ行の生成: 各ツイートデータに対して:
    • adverse_events 配列をパイプ区切り文字列( \| )に変換(例: “発熱\|倦怠感”
    • tokens 配列もパイプ区切り文字列に変換
    • テキスト内の改行( \\\\n )をスペースに置換(CSVの可読性向上)
    • 各フィールドを取得し、デフォルト値を設定
  4. CSV文字列の取得: getvalue() でCSV文字列を取得する

CSVカラム構成

カラム名 説明 データソース
tweet_id ツイートID Xから取得される元データ
search_keyword 検索キーワード Xから取得される元データ
created_at 作成日時 Xから取得される元データ
author_id 著者ID Xから取得される元データ
text ツイート本文 Xから取得される元データ
retweet_count リツイート数 Xから取得される元データ
reply_count リプライ数 Xから取得される元データ
like_count いいね数 Xから取得される元データ
quote_count 引用ツイート数 Xから取得される元データ
post_url ツイートURL 生成( https://x.com/i/web/status/{tweet\_id}
sentiment_label 感情ラベル LLM抽出結果
sentiment_reasoning 感情判断の理由 LLM抽出結果
is_health_related 健康 • ヘルスケア関連かどうか LLM抽出結果
category ツイートのメインカテゴリ LLM抽出結果
health_topics 健康トピック(パイプ区切り) LLM抽出結果
device_topics デバイストピック(パイプ区切り) LLM抽出結果
tokens 重要な単語(パイプ区切り) LLM抽出結果

データ整形のポイント

  1. 配列の処理: tokens は配列なので、パイプ区切り( \| )で結合(例: “発熱\|倦怠感”
  2. 改行の処理: テキスト内の改行( \\\\n )をスペースに置換(CSVの可読性向上)
  3. デフォルト値: 各フィールドにデフォルト値を設定(空文字列、0等)

出力例

tweet_id,search_keyword,created_at,author_id,text,retweet_count,reply_count,like_count,quote_count,po st_url,sentiment_label,sentiment_reasoning,is_health_related,category,health_topics,device_topics,tok  ens
1234567890,Apple  Watch,2025-01-14T12:00:00.000Z,987654321,Apple  Watchの心拍数と睡眠トラッキングが便利...,10,5,20,2,<https://x.com/i/web/status/1234567890,positive,健康管理機能への満足度が高い内容,true,health_moni toring,心拍モニタリング|睡眠トラッキング,バッテリー寿命,Apple Watch|心拍数|睡眠トラッキング

出力

出力名 説明
csv_output string CSV形式の文字列

3-2. GASにデータ送信(HTTP Requestノード)

生成したCSVデータをGoogle Apps Script(GAS)のWebアプリに送信するノードです。

設定内容

項目 設定値
メソッド POST
URL https://script.google.com/macros/s/…/exec
認証 なし
ヘッダー Content-Type:application/json

リクエストボディ

{
  "output": "#csv_output#",
  "keyword": "Apple Watch"
}
  • output : CSV文字列(前のノードから取得)
  • keyword : 検索キーワード(固定値または環境変数から取得)

Google Apps Scriptとは?

Google Apps Script(GAS)は、Googleが提供するクラウドベースのJavaScript実行環境で、Google Workspace(スプレッドシート、ドライブ、メール、カレンダーなど)を自動化 • 拡張するために設計されたプラットフォームです。ブラウザ上のエディタだけで完結し、インフラ構築やサーバ管理なしでスクリプトを動かせるため、「ちょっとした業務自動化」から「小さな業務システム」までを素早く立ち上げられる点が特徴です。

GAS Webアプリの作成方法(参考)

  1. Google Apps Scriptエディタを開く: https://script.google.com/
  2. 新しいプロジェクトを作成
  3. 以下のようなコードを記述:
function doPost(e) {
  try {
    const data = JSON.parse(e.postData.contents);
    const csvString = data.output;
    const keyword = data.keyword;

    // スプレッドシートを取得または作成
    const spreadsheet = SpreadsheetApp.getActiveSpreadsheet() ||
                        SpreadsheetApp.create('ソーシャルリスニング結果');
    const sheet = spreadsheet.getActiveSheet() ||
                  spreadsheet.insertSheet('データ');

    // CSVをパースしてスプレッドシートに追記
    const rows = Utilities.parseCsv(csvString);
    sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length)
         .setValues(rows);

    return ContentService.createTextOutput(JSON.stringify({
      status: 'success',
      message: 'Data appended successfully',
      spreadsheet_url: spreadsheet.getUrl()
    })).setMimeType(ContentService.MimeType.JSON);
  } catch (error) {
    return ContentService.createTextOutput(JSON.stringify({
      status: 'error',
      message: error.toString()
    })).setMimeType(ContentService.MimeType.JSON);
  }
}

  Webアプリとしてデプロイ:

  • 「デプロイ」→「新しいデプロイ」を選択種類: 「ウェブアプリ」を選択
  • アクセス権限: 「全員」を選択
  • 「デプロイ」をクリック
  • 表示されたURLをコピー(これがHTTP RequestノードのURLになります)

レスポンス例

{
  "status": "success",
  "message": "Data appended successfully",
  "spreadsheet_url": "<https://docs.google.com/spreadsheets/d/>..."
}

エラーハンドリング

GAS側でエラーが発生した場合、以下のようなレスポンスが返されます。

{
  "status": "error",
  "message": "Error message here"
}

Dify側では、このレスポンスを確認し、必要に応じてエラーログを記録する処理を追加できます。

4.  ワークフローの完成

ここまでで、ソーシャルリスニングワークフローの主要な処理が完成しました。

スプレッドシートをデータベース代わりに利用しているため、以下のようにデータが蓄積されます。

データ蓄積

5.  まとめ

本記事(Part 4)では、統合したデータをCSV形式に変換し、Google Apps Script(GAS)に送信してスプレッドシートに保存する処理を詳しく解説しました。

本記事で実現したこと

  • CSV形式への変換処理(カラム定義、データ整形)
  • GASへのHTTPリクエスト(POST, JSON形式)
  • スプレッドシートへの自動保存
  • エラーハンドリングとレスポンス処理

処理の流れの確認

  1.   CSV作成: 統合済みデータをCSV形式に変換(配列の処理、改行の処理等)
  2.   GAS送信: Google Apps ScriptのWebアプリにPOSTリクエストで送信
  3.   スプレッドシート保存: GAS側でCSVをパースしてスプレッドシートに追記

シリーズ全体のまとめ

本シリーズ(Part 2〜4)では、Difyのワークフローを使って、X(旧Twitter)のソーシャルリスニングを自動化するシステムを構築しました。

  • Part 2: DifyのワークフローでX APIからツイートを取得し、構造化データに変換
  • Part 3: LLMによる感情判定 • カテゴリ分析と、データ統合処理
  • Part 4: CSV形式への変換と、Google Apps Scriptへの送信 • スプレッドシート保存

これらの処理により、ツイートを取得 • 分析 • 保存するシステムが完成しました。

次のPart5ではこのStreamlitデータを用いたデータの可視化方法を解説します。企業におけるX投稿データの利用例として使える、現実的なサンプルを用意しています。

シリーズ構成

  • Part 0: X APIを用いたソーシャルリスニング概要
  • Part 1: X(旧Twitter) APIの基礎
  • Part 2: Difyを用いてX APIから直近のポストを取得する
  • Part 3: LLMを用いて自動でデータラベルを付与する
  • Part 4(本記事): スプレッドシートにデータを格納する
  • Part 5: Streamlitを用いたデータの可視化例(次の記事)

連載シリーズ

X APIを用いたソーシャルリスニング

全5回・X API × Dify・投稿収集からラベル付与・シート格納まで

  1. 概要:全体像と狙い
  2. X(旧Twitter) APIの基礎
  3. DifyでX APIから直近のポストを取得
  4. LLMで自動データラベル付与
  5. スプレッドシートに格納