공부한 것 꼭꼭 씹어먹기

최신 공지 10개 자동으로 보여주는 프로그램 본문

코딩으로 문제 해결하기

최신 공지 10개 자동으로 보여주는 프로그램

젤라솜 2022. 8. 1. 16:35
반응형

 

본인의 친구는 국악을 전공하고 있습니다.

국립국악원에서 공모전 공고를 본 친구는 열심히 공모전 준비를 하였습니다. 1차 합격 발표가 나지 않았지만 미리 2차 준비를 시작했지요.

1차에 불합격하면 멈추면 되고, 합격하면 다른 사람보다 더 많은 준비를 하는 셈이기 때문입니다.

 

그리고 열심히 사비 몇십만 원을 들여 밤샘하며 준비를 하던 찰나... 왠지 쎄한 기분이 든 친구는 모처럼 국립국악원 홈페이지에 방문하였고... 아뿔싸! 이미 합격차는 발표된 후였다고 합니다!!!

아쉽게도 불합격한 친구는 제때 공지만 확인했더라면 돈과 시간을 낭비하지 않았을 것이라며 한숨을 내쉬었지요...

이 세상의 많은 사람들은 틈틈이 국립국악원 홈페이지에 들어가 보지 않은 내 친구를 비난할 것입니다. 그러나 본인은 친구가 덜렁거린다고 해서 비난할 수만은 없었습니다. 비난 대신 선물을 하기로 했답니다!

 

 

국립국악원-홈페이지
국립국악원-홈페이지

"국립국악원 공지 자동 플레이"

 

 

국립국악원 홈페이지의 공지사항 메뉴에 들어가서 최신 공지 10개(첫 페이지)만 자동으로 플레이되는 프로그램을 선물하기로 했습니다.

매일 이 프로그램을 습관적으로 실행 시키기만 한다면 중요한 공지를 놓칠 일은 없을 것입니다.

 

특정 웹사이트에 자동으로 들어가서 원하는 데이터를 얻거나 특정 동작을 하게 하는 것을 스크래핑 이라고 하는데요.

보통 스크래핑이나 크롤링은 파이썬으로 많이 하지만 본인은 자바스크립트로 할 것입니다.

자바 스크립트로 스크래핑 할 수 있는 라이브러리로는 puppeteer가 유명하죠. 보통 데이터를 뽑아오기 위해서 headless(브라우저 화면이 안보이는) 모드로 많이 하지만(화면을 볼 필요가 없으므로) 이 프로그램은 친구가 직접 두 눈으로 공지 내용을 확인해야 하기 때문에 Non-headless 모드로 진행을 하겠습니다.

 

또한 이 프로그램은 실행파일로 만들어서 줄 것이기 때문에 데스크탑 앱을 만들 수 있는 electron이라는 라이브러리도 써야 합니다.

따라서 이 두가지를 함께 쓸 때 유용한 puppeteer-in-electron 라이브러리를 활용해 보겠습니다.

 

const { app, BrowserWindow, Menu } = require("electron");
const pie = require("puppeteer-in-electron");
const puppeteer = require("puppeteer-core");

let window;

const startProcess = async () => {
    console.log("in startProcess");
    await pie.initialize(app);
    const browser = await pie.connect(app, puppeteer);

    const window = new BrowserWindow({
        width: 1200,
        height: 900,
    });
    const urlHeader = "https://www.gugak.go.kr/site/program/board/basicboard/";
    const siteUrl = "https://www.gugak.go.kr/site/program/board/basicboard/list?boardtypeid=58&menuid=001005006001&pagesize=10&searchdate=null&currentpage=1";
    await window.loadURL(siteUrl);

    const page = await pie.getPage(browser, window);

    page.once('close', () => console.info('✅ Page is closed'));

    await page.waitForSelector('table tbody');
    const links = await page.$$('table tbody tr td.tl');

    let urls = [];
    for (let link of links) {
        const url = await link.$eval('a', element => element.getAttribute('href'));
        urls.push(url);
    }

    for (let url of urls) {
        console.log(url);
        await page.goto(url.replace('./', urlHeader));
        await page.waitForSelector('p.tit');
        await autoScroll(page);

    }

    async function autoScroll(page) {
        await page.evaluate(async () => {
            await new Promise((resolve, reject) => {
                var totalHeight = 0;
                var distance = 100;
                var timer = setInterval(() => {
                    var scrollHeight = document.body.scrollHeight;
                    window.scrollBy(0, distance);
                    totalHeight += distance;

                    if (totalHeight >= scrollHeight - window.innerHeight) {
                        clearInterval(timer);
                        resolve();
                    }
                }, 700);
            });

        });
    }
   
    window.destroy();
};

startProcess();

냅다 코드부터 던져보았습니다.

 

코드 구성은 매우 간단한데요.

먼저 puppeteer-in-electron의 사용법을 보고 앞부분 세팅을 해주고요.

 await pie.initialize(app);
 const browser = await pie.connect(app, puppeteer);

 const window = new BrowserWindow({
     width: 1200,
     height: 900,
 });

 

그리고 국립국악원 공지사항 페이지로 바로 직진해주세요.

 const siteUrl = "https://www.gugak.go.kr/site/program/board/basicboard/list?boardtypeid=58&menuid=001005006001&pagesize=10&searchdate=null&currentpage=1";
 await window.loadURL(siteUrl);

 const page = await pie.getPage(browser, window);

 

이제 이 페이지에서 보여지는 공지사항들이 가지고 있는 상세페이지 링크를 모아보겠습니다.

   await page.waitForSelector('table tbody');
   const links = await page.$$('table tbody tr td.tl');

 

우선 table 태그 안에 있는 tbody 안에 있는 tr 안에 있는 td들 중에 tl이라는 클래스를 가진 태그를 찾아 links라는 배열에 모아놓습니다.

개발자모드에서-태그를-찾아봅시다
개발자모드에서-태그를-찾아봅시다

 

tl 클래스를 가진 td 태그 안에는 a 태그가 있고 그 링크를 클릭함으로써 공지사항의 상세페이지로 이동할 수 있는데요.

이제 links 배열에서 상세페이지 링크만 뽑아서 urls라는 배열에 모아놓습니다.

let urls = [];
for (let link of links) {
    const url = await link.$eval('a', element => element.getAttribute('href'));
    urls.push(url);
}

 

그리고 urls 배열의 각 요소를 반복하면서 모아 놓은 상세페이지에 차례로 방문합니다. 이 때 자동으로 스크롤을 내리고 다 내려가면 다음 페이지로 이동하게 했습니다.

 for (let url of urls) {
    console.log(url);
    await page.goto(url.replace('./', urlHeader));
    await page.waitForSelector('p.tit');
    await autoScroll(page);
}

async function autoScroll(page) {
    await page.evaluate(async () => {
        await new Promise((resolve, reject) => {
            var totalHeight = 0;
            var distance = 100;
            var timer = setInterval(() => {
                var scrollHeight = document.body.scrollHeight;
                window.scrollBy(0, distance);
                totalHeight += distance;

                if (totalHeight >= scrollHeight - window.innerHeight) {
                    clearInterval(timer);
                    resolve();
                }
            }, 700);
        });
    });
}

 

이제 electron으로 설치파일을 만들어서 실행을 하면!

0
최신 공지 10개를 자동으로 보여주는 프로그램

 

이렇게 최신 공지 10개를 자동으로 보여주는 프로그램을 완성하였습니다!

멍때리면서 화면만 보고 있어도 중요한 공지는 놓치지 않을 수 있어요.

매일 컴퓨터 켜자마자 한번씩 꼭 실행하렴 친구야 😹

 

 

 

 

요약

- 문제 : 공지를 제때 확인하지 않아서 돈과 시간을 날림 -> 공지를 매일 확인하는 것은 귀찮은 일.

- 해결법 : 자동으로 최신 공지를 보여주는 툴을 만듦.

- 활용한 기술 : 자바스크립트, 퍼펫티어, 일렉트론

- 다음 버전에서는 : 최신 10개가 아닌 원하는 날짜에 올라온 공지만 확인하기, 특정 키워드가 제목이나 내용에 포함되었을 경우 메일 받기 

 

 

 

 

반응형
Comments