Created
February 9, 2026 04:00
-
-
Save ActiveTK/a9e9852a3249860bcfbfcf975366f7c8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Twitterの「データエクスポート」から取得したtweets.jsファイルを解析して、 | |
| 1ツイート1行のテキストファイルとして出力するスクリプトです。 | |
| 使い方の例 | |
| python export_tweets.py tweets.js | |
| python export_tweets.py tweets.js -o output.txt | |
| ※tweets.jsは、エクスポートしたZIPファイルの中の data/tweets.js にあります。 | |
| """ | |
| import argparse | |
| import json | |
| import re | |
| import sys | |
| from datetime import datetime | |
| from pathlib import Path | |
| def parse_tweets_js(file_path: str) -> list[dict]: | |
| with open(file_path, "r", encoding="utf-8") as f: | |
| content = f.read() | |
| match = re.match(r"window\.YTD\.tweets\.part\d+\s*=\s*", content) | |
| if match: | |
| json_str = content[match.end():] | |
| else: | |
| json_str = content | |
| return json.loads(json_str) | |
| def parse_twitter_date(date_str: str) -> datetime: | |
| return datetime.strptime(date_str, "%a %b %d %H:%M:%S %z %Y") | |
| def format_tweet_line(tweet_data: dict) -> str: | |
| tweet = tweet_data.get("tweet", tweet_data) | |
| created_at = tweet.get("created_at", "") | |
| full_text = tweet.get("full_text", "") | |
| tweet_id = tweet.get("id_str", "") | |
| try: | |
| dt = parse_twitter_date(created_at) | |
| timestamp = dt.strftime("%Y-%m-%d %H:%M:%S") | |
| except (ValueError, TypeError): | |
| timestamp = created_at | |
| text_oneline = full_text.replace("\n", " ").replace("\r", "") | |
| return f"{timestamp}\t{tweet_id}\t{text_oneline}" | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description="tweets.jsからツイートを抽出してテキストファイルに出力" | |
| ) | |
| parser.add_argument("input", help="入力ファイル (tweets.js)") | |
| parser.add_argument( | |
| "-o", "--output", | |
| help="出力ファイル (既定ではtweets_export.txtです)", | |
| default="tweets_export.txt" | |
| ) | |
| parser.add_argument( | |
| "--sort", | |
| choices=["asc", "desc"], | |
| default="desc", | |
| help="日時でソート: asc=古い順, desc=新しい順 (既定ではdesc)" | |
| ) | |
| args = parser.parse_args() | |
| input_path = Path(args.input) | |
| if not input_path.exists(): | |
| print(f"エラー: ファイルが見つかりません: {args.input}", file=sys.stderr) | |
| sys.exit(1) | |
| print(f"読み込み中: {args.input}") | |
| tweets = parse_tweets_js(args.input) | |
| print(f"ツイート数: {len(tweets)}") | |
| def get_timestamp(tweet_data): | |
| tweet = tweet_data.get("tweet", tweet_data) | |
| try: | |
| return parse_twitter_date(tweet.get("created_at", "")) | |
| except (ValueError, TypeError): | |
| return datetime.min.replace(tzinfo=None) | |
| tweets.sort(key=get_timestamp, reverse=(args.sort == "desc")) | |
| with open(args.output, "w", encoding="utf-8") as f: | |
| for tweet_data in tweets: | |
| line = format_tweet_line(tweet_data) | |
| f.write(line + "\n") | |
| print(f"完了しました!: {args.output}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment