N카페 이메일 추출

N카페의 멤버들 이메일 추출

// ==UserScript==
// @name         N카페 이메일 추출
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  N카페의 멤버들 이메일 추출
// @author       ChatGPT
// @match        *://cafe.naver.com/*
// @grant        GM_setClipboard
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let extractBtn; // 추출 버튼을 전역 변수로 저장
    let nicknameToIdMap = new Map(); // 닉네임 → writer.id 저장하는 맵 (API 요청 최소화)

    // 1️⃣ "추출 시작" 버튼을 적절한 위치에 추가
    function addExtractButton() {
        let sortBox = document.querySelector("#searchOptionSortByDiv .select_box"); // "최신순" 버튼 확인
        let noticeBox = document.querySelector("label[for='notice_hidden']"); // "공지 숨기기" 버튼 확인

        let targetElement = sortBox || noticeBox; // 최신순이 있으면 그 옆, 없으면 공지 숨기기 옆에 추가
        if (!targetElement) return console.error("❌ 버튼 추가 위치를 찾을 수 없음");

        extractBtn = document.createElement("button");
        extractBtn.innerText = "추출 시작";
        extractBtn.style = "margin-left:10px; padding:5px 10px; background:#ff5722; color:white; border:none; cursor:pointer; font-size:14px; border-radius:5px;";
        extractBtn.onclick = selectDuplicateOption;
        targetElement.parentNode.insertBefore(extractBtn, targetElement.nextSibling);
    }

    // 2️⃣ 중복 제거 선택 창 표시
    function selectDuplicateOption() {
        let removeDuplicates = confirm("중복을 제거하시겠습니까?\n\n확인 = 중복 제거, 취소 = 모든 데이터 포함");
        extractData(removeDuplicates);
    }

    // 3️⃣ 게시글 작성자 정보 추출 함수
    async function extractData(removeDuplicates) {
        if (extractBtn) {
            extractBtn.disabled = true; // ✅ 버튼 비활성화
            extractBtn.innerText = "추출 중...";
        }

        var g_sClubId = typeof window.g_sClubId !== "undefined" ? window.g_sClubId : (document.scripts[0].textContent.match(/g_sClubId\s*=\s*"(\d+)"/) || [,""])[1];
        if (!g_sClubId) {
            console.error("❌ g_sClubId 없음");
            if (extractBtn) {
                extractBtn.disabled = false;
                extractBtn.innerText = "추출 시작";
            }
            return;
        }

        let articleElements = document.querySelectorAll('.article');
        let writers = [];

        for (let articleEl of articleElements) {
            let articleHref = articleEl.getAttribute('href');
            let articleIdMatch = articleHref.match(/articleid=(\d+)/);
            let articleId = articleIdMatch ? articleIdMatch[1] : null;
            if (!articleId) continue;

            // 닉네임 추출 (게시글 목록에서 가져옴)
            let nicknameEl = articleEl.closest("tr")?.querySelector(".m-tcol-c");
            let nickname = nicknameEl ? nicknameEl.textContent.trim() : null;

            if (nickname && nicknameToIdMap.has(nickname)) {
                // ✅ 닉네임이 이미 저장된 경우 → API 호출 없이 사용
                let writerId = nicknameToIdMap.get(nickname);
                let email = `${writerId}@naver.com`; // 📌 이메일 추가
                writers.push(`${writerId}\t${nickname}\t${email}`);
                continue;
            }

            // ✅ 닉네임이 없거나 저장되지 않은 경우 → API 호출 필요
            let retryCount = 0, success = false;
            while (retryCount < 2 && !success) { // 최대 1회 재시도
                try {
                    let response = await fetch(`https://apis.naver.com/cafe-web/cafe-articleapi/v2/cafes/${g_sClubId}/articles/${articleId}/comments/pages/1?requestFrom=A&orderBy=asc`, {
                        "headers": {
                            "accept": "application/json, text/plain, */*",
                            "accept-language": "ko",
                            "sec-fetch-dest": "empty",
                            "sec-fetch-mode": "cors",
                            "sec-fetch-site": "same-site",
                            "x-cafe-product": "pc"
                        },
                        "referrer": `https://cafe.naver.com/ca-fe/cafes/${g_sClubId}/articles/${articleId}?where=search&tc=naver_search&oldPath=%2FArticleRead.nhn%3Farticleid%3D${articleId}%26where%3Dsearch%26clubid%3D${g_sClubId}%26tc%3Dnaver_search`,
                        "referrerPolicy": "unsafe-url",
                        "body": null,
                        "method": "GET",
                        "mode": "cors",
                        "credentials": "include"
                    });

                    if (!response.ok) throw new Error(`HTTP 오류: ${response.status}`);

                    let data = await response.json();
                    let writerId = data?.result?.article?.writer?.id;
                    let writerNick = data?.result?.article?.writer?.nick;

                    if (writerId && writerNick) {
                        // ✅ 닉네임 → ID 저장 (중복 API 호출 방지)
                        nicknameToIdMap.set(writerNick, writerId);
                        let email = `${writerId}@naver.com`; // 📌 이메일 추가
                        writers.push(`${writerId}\t${writerNick}\t${email}`);
                    } else {
                        console.error(`❌ writer 정보 찾을 수 없음: articleid=${articleId}`);
                    }

                    success = true;

                } catch (error) {
                    console.error(`🚨 오류 발생 (${retryCount + 1}번째 시도): ${error.message}`);
                    retryCount++;
                }

                // ✅ 요청 간 랜덤 딜레이 (500~1200ms)
                let randomDelay = Math.floor(Math.random() * 700) + 500;
                await new Promise(resolve => setTimeout(resolve, randomDelay));
            }
        }

        // 4️⃣ 중복 제거 여부에 따라 데이터 처리
        if (removeDuplicates) {
            writers = [...new Set(writers)]; // 중복 제거
        }

        // 5️⃣ 결과를 엑셀 형식으로 변환 & 클립보드 복사
        let resultText = "ID\t닉네임\t이메일\n" + writers.join("\n");
        GM_setClipboard(resultText);

        alert(`📋 결과가 클립보드에 복사되었습니다!\n엑셀에서 Ctrl+V로 붙여넣기하세요.\n\n중복 제거: ${removeDuplicates ? "✅ 예" : "❌ 아니오"}`);

        if (extractBtn) {
            extractBtn.disabled = false; // ✅ 버튼 활성화
            extractBtn.innerText = "추출 시작";
        }
    }

    // Tampermonkey가 실행될 때 버튼 추가
    addExtractButton();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址