반응형

들어가면서~~


네이버 카페 크롤링을 하는 목적은?

 

두가지의 목적이 있을 것으로 보이네요!

1. 하나는 내가 관리하는 카페인데, 좀 더 효율적으로 관리하고자 하는 목적

2. 타카페인데 게시물 목록이나 댓글을 파악하려고?

 

대부분 인터넷을 검색하면 파이썬을 추천하더군요~

그리고 여러가지 코드도 나와 있어서 쉽게 접근할 수 있는 것 같습니다.

 

오늘 주제는 위의 목적 중에서 "내가 관리하는 카페" 입니다.

 

네이버에도 통계가 있다!!

그것을 활용하면 게시물과 고객들이 작성하는 코멘트를 알 수 있습니다.

그러나 특정시기라든지 이벤트를 진행한 것을 알아보려면 쉽지 않습니다 ㅠ.ㅠ

 

1. 6월1일~10일까지의 특정게시판에 게시물을 많이 작성한 유저는?

2. 댓글 이벤트를 진행하여, 댓글을 많이 단 사람을 TOP 10 으로 뽑으려면?

 

카페를 운영하다보면 여러가지 이벤트를 진행하곤 합니다.

카페에 올라오는 게시글과 댓글의 숫자가 작다라면 ... 임의로 통계를 내어도 되지만!!

 

최소 한달에 10만개의 댓글이 달린다면?

엄두가 나지 않겠죠 ㅠ.ㅠ;;

 

이럴 때 순위 통계를 빠르게 낼 수도 있습니다^^

 

 

네이버 카페 크롤링의 정보는 보통 이렇습니다!!

카페아이디 | 글제목 | 내용 | 글쓴이(닉네임) | 글쓴이 아이디 | 댓글수 | 조회수
이정도가 아닐까 싶군요~

정보가 다 필요할 수도 있고, 상황에 따라서 일부만 필요할 수도 있습니다.

그것들을 가지고 와서 엑셀로 저장해서 정리하거나, DB로 저장해서 정리하는 방법이죠!

 


 

Puppeteer 를 소개합니다

 

 

 

Puppeteer | Puppeteer

build

pptr.dev

 

node 기반으로 작동을 하면서 쉽고 빠르게 네이버 카페 크롤링을 진행할 수 있습니다^^

 

 

서버에서 활용하기보다는 저는 개인PC (윈도우11)에 nodejs를 설치하고 프로그램을 구동합니다~

 

 

 

Node.js — Run JavaScript Everywhere

Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.

nodejs.org

 

 

그런후 테스트 페이지를 작성해서, 저장하고 실행하면서 나에게 맞는 형식으로 바꾸어갑니다

아래 코드는 puppeteer을 이용해서 네이버 카페 게시판을 크롤링 하는 소스 입니다

 


 

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false, // true면 창이 안 보이고 백그라운드 실행
    defaultViewport: null,
    args: ['--start-maximized'],
  });

  const page = await browser.newPage();

  // 네이버 카페 로그인
  await page.goto('https://nid.naver.com/nidlogin.login');

  // 네이버 로그인 정보 입력
  await page.type('#id', 'YOUR_NAVER_ID', { delay: 100 });
  await page.type('#pw', 'YOUR_PASSWORD', { delay: 100 });
  await page.click('.btn_login');

  // 로그인 완료 대기
  await page.waitForNavigation({ waitUntil: 'networkidle2' });

  console.log('✅ 로그인 완료');

  // 크롤링할 카페 게시판 주소 (예: 자유게시판)
  const cafeUrl = 'https://cafe.naver.com/ArticleList.nhn?search.clubid=YOUR_CLUB_ID&search.menuid=YOUR_MENU_ID&search.boardtype=L';

  await page.goto(cafeUrl, { waitUntil: 'networkidle2' });

  // 프레임 내부 게시글 목록 접근 (카페는 iframe 구조)
  const frame = await page
    .frames()
    .find(frame => frame.url().includes('ArticleList.nhn'));

  // 게시글 제목과 링크 추출
  const posts = await frame.evaluate(() => {
    const rows = Array.from(document.querySelectorAll('.article-board .td_article'));
    return rows.map(row => {
      const titleEl = row.querySelector('a.article');
      return {
        title: titleEl?.innerText.trim(),
        url: titleEl?.href
      };
    });
  });

  console.log('✅ 게시글 목록:', posts);

  await browser.close();
})();

 


 

위의 소스는 단순히 게시판 한개를 접속하여, 글제목과 URL을 가져와서 콘솔에 표시해 줍니다.

그것을 복사해서 텍스트 에디터나 엑셀 같은 것에 정리해야죠!!

 

그러나 그 목록이 굉장히 많다면?

바로 파일로 만들어서 저장해야 합니다.

왜냐면 콘솔에 표시된 목록은 길어지면 ... 자동으로 윗줄부터 삭제되기 때문이죠!

 

위의 puppeteer의 큰 장점은 실행 후 

어떻게 동작 되는지 살펴볼 수도 있고, 백그라운드로 실행할 수도 있죠!

 

(async () => {
  const browser = await puppeteer.launch({
    headless: false, // true면 창이 안 보이고 백그라운드 실행
    defaultViewport: null,
    args: ['--start-maximized'],
  });

 

 

headless: false ( true) 를 표시함으로 가능합니다.

여러가지 명령어 코드는 매뉴얼을 참조하시면 됩니다.

 


 

위의 코드는 무척 단순하게 특정 한개의 게시판의 첫페이지를 가지고 오는 것이죠!

그러나 우리가 원하는 것은?

페이지로 이동해서 전부를 가져오는 것 입니다.

페이지 만큼 반복해서 실행하는 코드를 삽입해야 하고,

또 어떤 때에는 기간을 설정해서 가져와야 하기도 합니다.

 

2025년6월1일~30일까지의 데이터만 추출해야하는 상황이면, 날짜까지 추출하여 비교하면서 해야겠죠~

 

이렇듯 단순히 가지고 오는 것에서 조금씩 내가 원하는 데이터를 적절하게 가지고 와서 가공하는 것입니다.

 

그러다보니 처음에는 간단했던 코드가 이런 저런 코드들이 붙으면서 조금 더 길어지게 되네요.

 

게시판 목록에서는 "회원의 아이디"를 알 수 없습니다. 그렇기에 또 한 단계 변환을 해야죠~

 


 

위의 상황들은 관리자가 관리하는 개념입니다. 타카페는 권한이 없는 경우도 있고, 회원만 열람할 수 있는 글도 있고~~ 제약이 있죠!

 

그래서 네이버 카페 크롤링하는 접속 아이디는 "게시판 관리자?" 정도의 권한이 있으면 됩니다.

 

결국 만들다 보면~ 최종 형태는 이렇게 되더군요!

 

서버 (크롤링을 어디까지 했지?) 확인 -> puppeteer의 코드에서 새글이 있는가? 있으면 새글을 가지고 오고, 없으면? 잠시 대기!!

그리고 가지고 왔으면 ... 서버로 그 정보를 전송하여 업데이트 하는 것이죠!

 

이것을 계속해서 반복하면 됩니다.

 


 

const axios = require('axios');
const { exec } = require('child_process');

const URL = '서버 데이터 확인 주소';

function getCheckInterval() {
  const now = new Date();
  const hour = now.getHours();

  // 오후 11시 ~ 오전 8시 (23~7시)
  if (hour >= 23 || hour < 8) {
    return 10 * 60 * 1000; // 10분
  }
  return 5 * 60 * 1000; // 5분
}

async function runPuppeteer(data) {
  return new Promise((resolve, reject) => {
    console.log(`📦 데이터 발견 → Puppeteer 실행`);
    const command = `node run-crowling.js`;

    exec(command, (err, stdout, stderr) => {
      if (err) {
        console.error(`❌ 실행 실패: ${err.message}`);
        return reject(err);
      }
      console.log(`✅ 실행 완료:\n${stdout}`);
      resolve();
    });
  });
}

async function checkAndRun() {
  while (true) {
    const interval = getCheckInterval();

    try {
      const res = await axios.get(URL, { timeout: 10000 });
      const json = res.data;

      if (json && Array.isArray(json.result) && json.result.length > 0) {
        console.log("-----------------------------------------------------------------");
        console.log(`📥 처리 데이터 ${json.result.length}건 존재`);
        await runPuppeteer(json.result);
      } else {
        console.log(`⏳ [${interval / 60000}분 주기] 처리 데이터 없음 → 대기 중...`);
      }
    } catch (e) {
      console.error('🚨 요청/파싱 오류:', e.message);
    }

    await new Promise(res => setTimeout(res, interval));
  }
}

checkAndRun();


 

네이버 카페 크롤링 할 때 puppeteer을 사용하는 것은 간편하면서도 빠르게 작동하고,

서버에서 동작을 하지 않아도~ 내 개인PC에서 얼마든지 가능하며~ 

서버까지 빠르게 업데이트 할 수 있는 장점이 있습니다.

 

위와 같은 것을 확대하면 "일부게시판"이 아니라 "전체게시판","전체댓글"도 가능하다라고 봐야겠죠~

 

그러나 아주 간단하게 제작되는 것은 아니랍니다.

 

하나 하나 실행해서 테스트하는 번거로움이 있기도 하죠!

 

제목에 이모니콘이 들어간다든지, 동일시간에 작성한 글 처리는 어떻게 해야하는지 ...

 

다양한 변수를 만나게 됩니다 ㅎㅎ

반응형
블로그 이미지

제주그리다

제주도 여행&사진 그리다

,
반응형

 

2018년 제2회 고졸 검정고시 기출문제 및 정답

 

2018년 제2회 고졸 검정고시 기출문제.pdf
1.38MB

반응형
블로그 이미지

제주그리다

제주도 여행&사진 그리다

,
반응형

 

2018년 제1회 고졸 검정고시 기출문제 및 정답

 

2018년 제1회 고졸 검정고시 기출문제.pdf
8.30MB

반응형
블로그 이미지

제주그리다

제주도 여행&사진 그리다

,