自動擷取、清理、管理與匯出 Threads 貼文中的可嵌入程式碼與中繼資料
基於 Google Chrome Manifest V3 標準設計的瀏覽器擴充功能。
純前端、零依賴 — 所有資料安全儲存於瀏覽器本機的 chrome.storage.local,
無需任何後端服務、外部資料庫或 API 金鑰,確保您的隱私與資料安全。
- 快速開始
- 核心功能特性
- 技術規格與技術棧
- 專案目錄結構
- 系統架構與流程圖
- 核心技術邏輯與演算法
- 資料儲存 Schema
- 配置與權限宣告
- 備份與匯出格式規範
- 疑難排解 FAQ
- 開發與貢獻指南
- Changelog
- AI 友善文件說明
- 免責聲明
- 支持 Manifest V3 的 Chromium 核心瀏覽器(如 Google Chrome, Microsoft Edge, Brave, Opera 等)。
- 執行與開發不需安裝任何額外的編譯套件。
- 若需要安裝輔助指令或管理本地測試環境,推薦使用 Bun 作為套件管理器。
- 複製或下載本專案原始碼到本機:
git clone https://github.com/Scorpio-meow/threads-embedded-code.git cd threads-embedded-code - 開啟 Chromium 核心瀏覽器,導覽至擴充功能管理頁面:
- Chrome 請輸入:
chrome://extensions/ - Edge 請輸入:
edge://extensions/
- Chrome 請輸入:
- 開啟頁面右上角的 開發人員模式 (Developer mode)。
- 點擊左上角的 載入未封裝項目 (Load unpacked) 按鈕。
- 選擇本專案的根目錄(即包含 manifest.json 的資料夾)。
- 建議在瀏覽器工具列中釘選「Threads 程式碼儲存器」圖示以利快速操作。
- 瀏覽至任意 Threads 貼文的單篇詳細頁面或動態牆。
- 點擊貼文右上角的選單按鈕(三個點),並選擇「取得內嵌程式碼 (Get embed code)」。
- 擴充功能會自動攔截產生的對話框並擷取資料。當頁面出現綠色的「內嵌程式碼已儲存」通知時,代表儲存成功。
- 點擊瀏覽器工具列的擴充功能圖示可開啟 Popup 快速面板,或在選項中開啟 Dashboard 完整儀表板進行深入管理。
- DOM 變更監聽:使用
MutationObserver持續監控網頁結構,搭配 5 秒一次的週期性掃描,精確捕獲「取得內嵌程式碼」對話框。 - 主動式偵測:當使用者在非擴充功能觸發的情況下開啟嵌入對話框時,
processOpenEmbedDialogs會主動識別並將該貼文儲存至資料庫。 - 安全儲存封裝:內建
safeStorageGet與safeStorageSet,能自動偵測擴充功能上下文是否失效 (isExtensionAlive),避免拋出未捕獲例外(Context Invalidated 錯誤)。
- UI 雜訊過濾:自動識別並清除作者簡介、追蹤人數、串文數量以及平台引導文案(例如「查看 @... 參與的最新對話」、「尚無回覆」等)。支援多達 20 種以上的繁中與英文模式。
- 回覆邊界隔離:在首頁動態牆或個人檔案頁面擷取貼文時,若偵測到「回覆...」等邊界元素,會自動切斷並排除回覆區域,僅保留原始貼文內容。
- 純圖片貼文偵測:透過
isLikelyImageOnlyDescription智慧識別僅含圖片說明(如Photo by ... on ...)的貼文,避免誤擷取無意義描述。
擴充功能會將每篇貼文拆解為結構化的欄位,以利後續的檢索與程式碼重複利用:
| 欄位名稱 | 說明 |
|---|---|
| 貼文內文 | 經過去除中繼資料與 UI 雜訊後的純文字貼文內容 |
| 作者帳號 | 提取發文者的帳號(@username) |
| 作者主頁連結 | 連結至發文者的 Threads 個人主頁 |
| 精確發布時間 | 包含 ISO 8601 格式時間與人類可讀的格式化時間 |
| 自動標籤群組 | 整合官方 Hashtag、程式語言關鍵字,並移除重複標籤 |
| 程式碼區塊 | 解析貼文中的行內程式碼、Markdown 程式碼圍欄及等寬字型 CSS 區塊 |
| 嵌入程式碼 | 儲存 Threads 官方原生的 blockquote HTML 內嵌碼 |
- 背景任務佇列:使用
chrome.tabs與chrome.scripting以最多 3 個併發任務開啟隱藏分頁,自動重新讀取貼文以同步最新內容。 - 智慧失效標記:當背景更新發現以下狀況時,會自動將貼文標記為失效 (
expired):redirected:URL 中的貼文 ID 發生改變(表示原貼文已被轉導或刪除)。post-not-found:在頁面載入 4 秒後仍找不到貼文主容器[data-pressable-container]。fallback-summary:頁面僅剩下預設的引導摘要文字。
- 失效自動恢復:下次更新時若偵測到貼文恢復可存取狀態,將會自動清除失效標記。
- Popup 彈出面板:提供快速檢索、全文搜尋、多維度排序、類型篩選、三種匯出格式、本機資料匯入與單筆更新/刪除。
- Dashboard 完整儀表板:全螢幕響應式排版,內建全選/反選批次操作(支援 Indeterminate 半選狀態)、批次刪除、批次複製 Embed 代碼、標籤統計雲與作者統計雲。
- 自訂互動 Modal:所有具破壞性的敏感操作(如清除全部、批次刪除、覆寫匯入)均使用自訂 Modal 進行二次確認,完全替換原生的
confirm()與alert(),外觀與擴充功能設計語言高度統一。
- 核心架構:原生 HTML5, CSS3, Vanilla JavaScript (ES6+)。
- 核心規範:Chrome Extension Manifest V3。
- 資料儲存:
chrome.storage.local(儲存上限預設為 10MB)。 - 權限控制:完全無第三方依賴,不使用任何外部 CDN 或 NPM 包,符合安全性嚴格的內容安全政策 (Content Security Policy, CSP)。
threads-embedded-code/
├── manifest.json # 擴充功能設定檔 (定義權限、指令注入規則與入口)
├── content.js # Content Script (負責 DOM 監聽、對話框攔截與初次資料提取)
├── styles.css # 注入到 Threads 網頁的樣式檔 (用於提示通知元件)
├── popup.html # 瀏覽器工具列彈出視窗 UI
├── popup.css # 彈出視窗樣式表
├── popup.js # 彈出視窗控制邏輯 (搜尋、篩選、基本備份、背景更新)
├── dashboard.html # 完整管理儀表板 UI (側邊欄、統計雲、貼文列表、確認 Modal)
├── dashboard.css # 儀表板樣式表
├── dashboard.js # 儀表板控制邏輯 (統計分析、標籤雲、自訂對話框、批次管理)
├── favicon.png # 擴充功能圖示
└── README.md # 專案說明文件
下列 Mermaid 流程圖展示了從前端 Threads 頁面點擊按鈕,到背景更新,再到資料呈現於 UI 的完整運作路徑:
flowchart TD
subgraph ThreadsPage["Threads 網頁前端"]
A["貼文 DOM 結構"] -->|"使用者點擊取得內嵌程式碼"| B["嵌入對話框 (Embed Dialog)"]
C["content.js (MutationObserver)"] -->|"自動偵測對話框開啟"| B
B -->|"提取 HTML / 貼文中繼資料"| D["資料清理與智慧過濾鏈"]
end
subgraph Storage["擴充功能本機儲存"]
D -->|"safeStorageSet (寫入 / 更新)"| E[("chrome.storage.local (savedArticles)")]
end
subgraph UserInterface["擴充功能使用者介面"]
E -->|"safeStorageGet (讀取)"| F["Popup 面板 (popup.js)"]
E -->|"safeStorageGet (讀取)"| G["全頁儀表板 (dashboard.js)"]
G -->|"計算分析"| G1["標籤雲 / 作者雲 / 統計指標"]
end
subgraph BackgroundProcess["背景更新程序"]
F -->|"手動/批次更新觸發"| H["chrome.tabs.create (靜默分頁)"]
G -->|"手動/批次更新觸發"| H
H -->|"背景載入貼文 URL"| I["貼文分頁"]
I -->|"等待載入 (最長 8 秒)"| J["chrome.scripting.executeScript"]
J -->|"注入 extractPostInfoFromPage"| K["檢查重新導向 / 輪詢 DOM 提取資訊"]
K -->|"判斷狀態 (Active / Expired)"| L["更新本機資料結構"]
L -->|"回寫儲存"| E
K -->|"關閉分頁"| M["chrome.tabs.remove"]
end
當 Threads 彈出嵌入對話框時,會包含多個唯讀的 input 或 textarea 元素。為了準確拿到包含 blockquote 的完整嵌入碼,擴充功能對所有 readonly 的輸入框內容進行權重計分:
let score = value.length;
if (/data-text-post-permalink=/i.test(value)) score += 1000;
if (/<blockquote/i.test(value)) score += 500;
if (/threads\.com/i.test(value)) score += 100;最後挑選分數最高的輸入框內容作為最佳的 embedCode。
擴充功能會透過四個不同的管道來識別並提取貼文中的程式碼片段:
- Markdown 圍欄程式碼區塊:
使用正規表達式
/```(\w*)\n([\s\S]*?)```/g匹配。若有指定語言標記(例如javascript ...),則自動解析為對應語言。 - Monospace 字型樣式區塊:
尋找 DOM 中包含
style*="monospace"屬性的元素,將其文字內容去重後加入。 - HTML 程式碼標籤:
選取
pre或code元素,並過濾長度大於 5 個字元的內容。 - 行內程式碼:
使用
/`([^`\n]{2,})`/g正規表達式提取所有行內代碼,並將其合併為inline類型。
當用戶點擊「更新時間和內文」時,擴充功能限制最大併發分頁數量為 3,以防止過多靜默分頁同時開啟造成系統效能低落或觸發 Threads 流量限制。 更新模組會以非同步 Worker 迴圈消耗任務佇列:
const maxConcurrency = 3;
const runWorker = async () => {
while (tasks.length > 0) {
const article = tasks.shift();
// 執行分頁建立、載入等待、腳本注入與資料比對
}
};所有儲存的貼文皆以 SavedArticle 物件陣列形式儲存在本機。
interface SavedArticle {
/** 唯一識別碼 (格式為 embed_[時間戳]_[隨機字串] 或 code_[時間戳]_[隨機字串]) */
id: string;
/** 貼文唯一 URL,作為本機去重與更新的主鍵 */
postLink: string;
/** Threads 官方完整 blockquote HTML 內嵌碼 */
embedCode: string;
/** 原始發布時間 (ISO 8601 格式) */
timestamp: string;
/** 原始發布時間的格式化標題 (如「2026年5月29日 上午10:00」) */
timestampTitle: string;
/** 儲存至本機的時間 (ISO 8601 格式) */
savedAt: string;
/** 貼文純文字 (已過濾 UI 雜訊) */
content: string;
/** 發文者帳號 */
author: string;
/** 發文者 Threads 個人檔案網址 */
authorUrl: string;
/** 自動推導的標籤陣列 */
tags: string[];
/** 解析出的程式碼區塊列表 */
codeBlocks: CodeBlock[];
/** 程式碼區塊總數 */
codeCount: number;
/** 貼文存活狀態 */
status: 'active' | 'expired';
/** 最後被背景更新的時間 (ISO 8601) */
lastUpdated?: string;
/** 標記失效的時間 (ISO 8601) */
expiredAt?: string;
/** 失效原因 */
expiredReason?: 'redirected' | 'post-not-found' | 'fallback-summary';
/** 最後一次檢查失效狀態的時間 (ISO 8601) */
expiredCheckedAt?: string;
/** 最後更新時間戳記的系統時間 */
timestampUpdatedAt?: string;
/** 匯入來源標記 */
importedFrom?: 'full-data-file' | 'js-embed-file';
}interface CodeBlock {
/** 來源類型:markdown圍欄、HTML標籤、Monospace樣式或行內程式碼 */
type: 'markdown_block' | 'html_tag' | 'monospace' | 'inline';
/** 程式碼文字內容 */
code: string;
/** 推測的程式語言 (無法識別時為 unknown) */
language: string;
/** 在貼文中的順序索引 (由 1 開始) */
index: number;
/** 行內代碼總數 (僅 inline 類型有效) */
count?: number;
}本擴充功能在 manifest.json 中聲明了最低限度的必要權限,無多餘的後門或敏感權限需求:
| 權限名稱 | 類型 | 說明與用途 |
|---|---|---|
storage |
API 權限 | 用於將貼文資料與設定讀寫至本機瀏覽器的 chrome.storage.local 空間。 |
tabs |
API 權限 | 用於在背景安靜地開啟 Threads 網頁分頁,以執行資料更新與失效驗證。 |
scripting |
API 權限 | 用於向背景載入的 Threads 貼文分頁注入內容提取腳本。 |
https://www.threads.com/* |
主機權限 | 僅允許擴充功能在標準 Threads 網域中注入 content.js 並讀取貼文內容。 |
https://threads.com/* |
主機權限 | 允許擴充功能在非 www 前綴的 Threads 網域中進行相同操作。 |
本工具提供三種不同用途的 JavaScript 陣列格式匯出,檔案會以 const posts = [...] 的結構輸出,以便外部系統直接引用。
- 檔名格式:
threads-embed-codes-[YYYY-MM-DD].js - 說明:專為需要在靜態網頁快速嵌入內容設計。自動去除了重複的
<script src=".../embed.js"></script>標籤,並轉義單引號與斜線。 - 範例格式:
const posts = [ '<blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@user/post/x">...</blockquote>', '<blockquote class="text-post-media" data-text-post-permalink="https://www.threads.com/@user/post/y">...</blockquote>' ];
- 檔名格式:
threads-featured-data-[YYYY-MM-DD].js - 說明:為外部客製化展示網頁設計,
author欄位會自動移除@前綴。 - 範例格式:
const posts = [ { "embedCode": "<blockquote class=\"text-post-media\" data-text-post-permalink=\"https://www.threads.com/@user/post/x\">...</blockquote>", "postLink": "https://www.threads.com/@user/post/x", "author": "user", "content": "貼文純文字內容...", "tags": ["JavaScript", "CSS"] } ];
- 檔名格式:
threads-full-data-[YYYY-MM-DD].js - 說明:包含本機資料庫的所有 Schema 欄位,適用於跨裝置備份或轉移資料。
- 範例格式:
const posts = [ { "id": "embed_1716960000000_abc123xyz", "postLink": "https://www.threads.com/@user/post/x", "embedCode": "<blockquote class=\"text-post-media\" ...>...</blockquote>", "timestamp": "2026-05-29T02:00:00.000Z", "timestampTitle": "2026年5月29日 上午10:00", "savedAt": "2026-05-29T02:10:00.000Z", "content": "貼文純文字內容", "author": "@user", "authorUrl": "https://www.threads.com/@user", "tags": ["JavaScript"], "codeBlocks": [], "codeCount": 0, "status": "active" } ];
當您匯入備份檔案時,系統會開啟自訂 Modal 讓您選擇以下兩種模式之一:
Important
- 合併資料 (Merge):比對
postLink。如果該貼文已存在於本機,則略過匯入,僅將新貼文追加到列表最前方,防止重複。 - 覆寫資料 (Overwrite):直接清空現有的本機資料,完全以匯入檔案中的內容取代。
- 格式容錯:匯入解析器會依序嘗試
JSON.parse->new Function()動態求值 -> 正規表達式提取,可完美相容標準 JSON 與帶有const posts =前綴的 JS 腳本檔案。
Warning
Q:點擊取得內嵌程式碼後,網頁上沒有出現「儲存成功」的提示?
- 請確認您的瀏覽器是否已登入 Threads 帳號(未登入時,Threads 的嵌入框可能無法正常產生代碼)。
- 確認當前頁面網址是否為標準的
threads.com或www.threads.com。 - 若瀏覽器主控台 (Console) 出現
Extension context invalidated警告,此為 Chrome 更新擴充功能後的正常現象,只需重新整理該 Threads 網頁即可恢復運作。
Note
Q:為什麼很多貼文在背景更新後被標記為「失效貼文」?
- 這代表該貼文可能已被原作者刪除、帳號設為私密,或是原作者封鎖了匿名存取。
- 背景分頁的網路載入逾時(預設為 8 秒)也可能導致暫時性無法讀取,因而判定為失效。
- 若貼文隨後恢復正常,在下一次更新時,系統偵測到內容即會自動將其恢復為
active狀態。
Caution
Q:Threads 官方改版後,擴充功能無法正常擷取?
- 本工具高度依賴 Threads 前端網頁的 DOM 選擇器特徵(例如
span[class*="xo1l8bm"])。 - 若 Threads 官方進行了重大的樣式類別 (class) 或 DOM 結構修改,將會導致擷取演算法失效。此時需要更新 content.js 中對應的 CSS 選擇器,歡迎提交 Issue 回報。
Important
Q:本機儲存空間是否有限制?
chrome.storage.local在多數 Chromium 瀏覽器中預設有 10MB 的配額限制。- 當儲存空間接近上限並拋出
QUOTA_BYTES_EXCEEDED錯誤時,擴充功能會提示您清理。建議定期將完整版資料匯出備份,並清除不需要的舊貼文。
歡迎所有開發者協助改進本專案!如果您有任何建議或發現 Bug,請隨時提交 Issue 或 Pull Request。
- 零依賴原則:專案保持原生輕量化設計,請勿引入任何 npm 依賴套件或外部 CDN 框架。
- 嚴格 CSP 相容:所有 HTML 頁面及注入的指令皆禁止使用行內樣式 (inline style) 與行內事件監聽器(例如
onclick="..."),必須使用addEventListener。 - 欄位擴展:若在 content.js 中新增或修改了儲存欄位,請務必同步更新本 README 的 資料儲存 Schema 區段。
- 套件管理:若您在開發過程中需要執行自訂腳本或建立輔助工具,請優先使用
bun套件管理器而非npm:bun install
本專案遵循 Keep a Changelog 格式規範。
- 實作
safeStorageGet/safeStorageSet封裝,防止 context invalidated 後未捕獲的例外中斷腳本執行。 - 支援
processOpenEmbedDialogs主動偵測機制,即使用戶未透過擴充功能按鈕開啟嵌入對話框也能成功擷取。
- 擴充過濾規則至 20 種以上的 UI 雜訊模式,並新增英文語系介面的過濾規則。
- 優化背景併發更新佇列的超時處理與重試邏輯。
- 修正
isSameThreadsPostLink在特定自訂貼文 URL 格式下的誤判問題。 - 修正批次刪除完成後,全選核取方塊的半選 (indeterminate) 狀態未正確重置的異常。
- 上線全網頁版儀表板 (Dashboard UI)。
- 支援三種匯出格式:簡易嵌入碼、精選貼文資料、完整版資料。
- 支援最多 3 個併發任務的背景分頁自動更新與失效智慧標記。
- 新增 Top 15 標籤統計雲與作者統計雲。
- 實作自訂確認 Modal,全面替換原生
confirm()。
- 嵌入碼對話框掃描改用分數權重演算法,大幅降低誤選率。
- 全面移除行內樣式,相容瀏覽器嚴格 CSP。
Note
本區段提供給 AI 代理、LLM 網頁爬蟲與 RAG 索引工具快速讀取本專案結構。
# Threads 程式碼儲存器
> Chromium 核心瀏覽器擴充功能,用於從 Threads 貼文自動擷取並本機儲存可嵌入的程式碼與貼文中繼資料。
## 核心檔案路徑
- [manifest.json](./manifest.json): 擴充功能配置檔,定義權限與 content script 規則
- [content.js](./content.js): Content Script,負責監聽 DOM 變更與擷取嵌入對話框
- [styles.css](./styles.css): 注入至 Threads 頁面的通知樣式
- [popup.js](./popup.js): Popup 視窗邏輯,處理基本的搜尋、排序、更新與資料備份
- [dashboard.js](./dashboard.js): 儀表板頁面邏輯,包含標籤/作者統計雲與批次維護工具
## 核心資料定義
- savedArticles: chrome.storage.local 中的鍵名,儲存 SavedArticle 的物件陣列
- postLink: 去重與更新的主鍵
- embedCode: Threads 官方 <blockquote> HTML 嵌入程式碼
- status: active | expired,標記貼文的可存取狀態本擴充功能為第三方獨立開發之開源工具,與 Meta 或 Threads 官方無任何關聯、授權或隸屬關係。Threads 平台的網頁結構、API 與使用規範可能隨時變更,若因官方平台改版導致擷取功能暫時失效,需等待維護者更新選擇器規則。使用者須自行承擔使用本工具之相關風險。
Threads 程式碼儲存器 — 由 Scorpio-meow 開發與維護