X(Twitter)で複数のツイートをつなげた「スレッド(連投)」を、引用やメモに使いたいときがある。ところがXには連投をまとめて取り出す機能がなく、1ツイートずつコピーして貼り付けるしかない。長い解説スレッドだと10件以上を手作業でつなぐことになり、かなり面倒だ。このブックマークレットを使えば、スレッド主のツイート本文だけを上から順に連結し、1つのテキストとしてまとめてコピーできる。ログインも外部サービスも不要で、いま開いているページ上だけで完結する。
ブックマークレット
次のコードをブックマークのURL欄に設定する。
javascript:(function(){if(!/(twitter|x)\.com/.test(location.host)||!location.pathname.includes('/status/')){alert('X(Twitter)のスレッド(ツイートの詳細)ページで実行してください');return;}function handleOf(a){var n=a.querySelector('[data-testid=\"User-Name\"]');if(!n)return null;var m=n.innerText.match(/@\w+/);return m?m[0]:null;}var arts=document.querySelectorAll('article[data-testid=\"tweet\"]');if(!arts.length){alert('ツイートが見つかりません。ページを開き直してから実行してください。');return;}var author=handleOf(arts[0]),seen={},texts=[];arts.forEach(function(a){if(handleOf(a)!==author)return;var b=a.querySelector('[data-testid=\"tweetText\"]');if(!b)return;var t=b.innerText.trim();if(!t||seen[t])return;seen[t]=1;texts.push(t);});if(!texts.length){alert('本文が取得できませんでした。スレッドを下にスクロールしてから試してください。');return;}var result=texts.join('\n\n');var o=document.getElementById('x-thread-panel');if(o){o.remove();return;}var p=document.createElement('div');p.id='x-thread-panel';p.style.cssText='position:fixed;top:60px;right:16px;width:380px;max-height:80vh;overflow-y:auto;background:#fff;border:1px solid #ddd;border-top:3px solid #1d9bf0;border-radius:4px;z-index:99999;padding:12px 16px;font-size:13px;font-family:sans-serif;box-shadow:0 4px 16px rgba(0,0,0,.2)';var hdr=document.createElement('div');hdr.style.cssText='display:flex;justify-content:space-between;align-items:center;margin-bottom:10px';var ttl=document.createElement('span');ttl.style.cssText='color:#1d9bf0;font-weight:bold';ttl.textContent='スレッド ('+texts.length+'件 / '+author+')';var btns=document.createElement('div');var cp=document.createElement('button');cp.style.cssText='padding:3px 10px;background:#1d9bf0;color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:12px;margin-right:6px';cp.textContent='コピー';var cl=document.createElement('button');cl.style.cssText='background:none;border:none;font-size:16px;cursor:pointer';cl.textContent='×';btns.appendChild(cp);btns.appendChild(cl);hdr.appendChild(ttl);hdr.appendChild(btns);p.appendChild(hdr);var ta=document.createElement('textarea');ta.value=result;ta.style.cssText='width:100%;height:60vh;box-sizing:border-box;border:1px solid #eee;border-radius:4px;padding:8px;font-size:12px;line-height:1.6;resize:vertical;white-space:pre-wrap';p.appendChild(ta);document.body.appendChild(p);cl.onclick=function(){p.remove();};cp.onclick=function(){navigator.clipboard.writeText(result).then(function(){cp.textContent='コピーしました';setTimeout(function(){cp.textContent='コピー';},2000);}).catch(function(){ta.select();cp.textContent='手動でコピーを';setTimeout(function(){cp.textContent='コピー';},2000);});};})(); 登録手順
- ブックマークバーを右クリックして、新しいブックマークを作る
- 名前を「スレまとめ」など分かりやすいものにする
- URL欄に上のコードを貼り付けて保存する
使い方
- まとめたいスレッドの先頭ツイート(詳細表示)を開く
- 連投の最後までゆっくりスクロールして、ツイートをすべて読み込む
- ブックマークレットをクリックする
- 右側に連結結果のパネルが表示される(件数とスレッド主のハンドルが上部に出る)
- コピーボタンでクリップボードに取得できる
- もう一度クリックするとパネルが閉じる
スクロールが足りないとツイートが読み込まれず、途中までしか取得できない。先に最後まで表示させてから実行するのがコツだ。
どう動いているか
Xのスレッドは、同じ投稿者が自分のツイートに連続して返信する形で作られている。途中に他人のリプライが挟まることもあるため、まずは各ツイート要素から投稿者のハンドル(@xxxx)を取り出す関数を用意する。
// ツイート要素から投稿者のハンドル(@xxxx)を取り出す
function handleOf(article) {
const name = article.querySelector('[data-testid="User-Name"]');
if (!name) return null;
const m = name.innerText.match(/@\w+/);
return m ? m[0] : null;
}
次に、ページ内のツイート要素(article[data-testid="tweet"])を上から順に走査する。先頭ツイートの投稿者をスレッド主とみなし、同じハンドルのツイートだけを集める。本文は [data-testid="tweetText"] から取り出し、空のものや同一文面の重複を除いて配列にためていく。最後に空行区切りで連結すれば、1つのテキストになる。
const articles = document.querySelectorAll('article[data-testid="tweet"]');
const author = handleOf(articles[0]); // 先頭ツイートの投稿者をスレッド主とみなす
const seen = new Set();
const texts = [];
articles.forEach((art) => {
if (handleOf(art) !== author) return; // 他人のリプライは除外
const body = art.querySelector('[data-testid="tweetText"]');
if (!body) return;
const text = body.innerText.trim();
if (!text || seen.has(text)) return; // 空・重複を除外
seen.add(text);
texts.push(text);
});
const result = texts.join('\n\n'); 取得したテキストはテキストエリアに入れて表示しているので、コピー前に中身を確認・微修正することもできる。Xのクリップボード書き込みがブロックされた環境でも、テキストエリアを選択して手動でコピーできるようにしてある。
注意
- 画面に読み込まれたツイートだけが対象。仮想スクロールのため、表示していない範囲は拾えない。
- 画像・動画・引用ツイートは本文に含まれない。あくまでテキスト部分だけを連結する。
- XのDOM構造(
data-testidなど)が変わると動作しなくなる可能性がある。 - スレッド主が同じハンドルで連投している前提。別アカウントをまたぐ会話には対応していない。
関連記事
- X(Twitter)のメディア欄から画像URLを一括取得する方法
- X(Twitter)の検索演算子まとめ(from: / since: / until: / filter:)
- X(Twitter)の画像をオリジナル画質で保存する方法
- ページのメタ情報を見やすく表示&コピーするブックマークレット
- Chromeのブックマークレットにアイコン(ファビコン)を追加する
よくある質問
- Xのスレッド(連投)をまとめてコピーするには?
- ブックマークレットを使うと、スレッド表示ページで同じ投稿者のツイート本文を上から順に連結し、1つのテキストとしてコピーできる。スレッドを下までスクロールして読み込んでからクリックする。
- スレッドの一部しか取得できないのはなぜ?
- Xのタイムラインは画面に表示された分だけを読み込む仮想スクロール方式のため、表示されていないツイートは取得できない。スレッドを下までスクロールしてから実行すると全件を拾える。
- 引用やリプライも一緒にコピーされる?
- 最初のツイートと同じ投稿者のツイートだけを対象にしているため、他人のリプライは除外される。投稿者本人による連投だけがまとめてコピーされる。