---
# System prepended metadata

title: threads 抓圖
tags: [tampermonkey, javascript, chrome extension]

---

# threads 抓圖
###### tags: `chrome`, `tampermonkey`, `javascript`

``` javascript
// ==UserScript==
// @name         [ Threads ] 圖片與完整描述自動收集
// @description  [ Threads ] 圖片與完整描述自動收集
// @namespace    http://tampermonkey.net/
// @version      1.20240604
// @author       icps
// @match        https://www.threads.com/@*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    window.allImageData = [];

    const btn = document.createElement('button');
    btn.textContent = '開始收集';
    btn.style.position = 'fixed';
    btn.style.top = '20px';
    btn.style.right = '20px';
    btn.style.zIndex = 9999;
    btn.style.padding = '10px 15px';
    btn.style.backgroundColor = '#ff5722';
    btn.style.color = '#fff';
    btn.style.border = 'none';
    btn.style.borderRadius = '5px';
    btn.style.cursor = 'pointer';
    btn.style.fontSize = '14px';
    btn.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';
    document.body.appendChild(btn);

    btn.addEventListener('click', async () => {
        btn.disabled = true;
        btn.textContent = '收集中...';

        await autoScrollAndCollect();

        console.log(`共收集 ${window.allImageData.length} 筆描述與圖片`);
        downloadData(window.allImageData);

        btn.disabled = false;
        btn.textContent = '開始收集';
    });

    async function autoScrollAndCollect() {
        const maxScrollTimes = 100;
        const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

        for (let scrollTimes = 0; scrollTimes < maxScrollTimes; scrollTimes++) {

            document.querySelectorAll('div.x1xdureb.xkbb5z.x13vxnyz').forEach(post => {

                const descEl = post.querySelector('div.x1a6qonq span');
                const desc = descEl ? descEl.innerText.trim() : "";

                const imgUrls = Array.from(post.querySelectorAll('img'))
                    .map(img => img.src)
                    .filter(src => src); // 避免空值

                if (imgUrls.length === 0) return;

                // 檢查是否已存在相同描述
                const exists = window.allImageData.find(d => d.text === desc);

                if (exists) {
                    // 已存在，補上新圖片（避免重複）
                    imgUrls.forEach(url => {
                        if (!exists.urls.includes(url)) {
                            exists.urls.push(url);
                        }
                    });
                } else {
                    // 新增資料
                    window.allImageData.push({
                        text: desc,
                        urls: imgUrls
                    });
                }
            });

            window.scrollBy(0, 1500);
            await sleep(2000);
        }
    }

    function downloadData(data) {
        const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);

        // 取出使用者名稱
        const matches = window.location.pathname.match(/^\/@([^\/]+)/);
        const username = matches ? matches[1] : 'threads_data';

        link.download = `${username}.json`;
        link.click();
    }

})();


```