Google Apps Script를 활용해 무료로 서울사랑상품권 발행 알림 봇 운영하기

개발, 팁과 정보 | 2024/09/09 09:00

Google Apps Script란?

Google Apps Script는 JavaScript를 기반으로 Google의 여러 서비스(Gmail, Google Sheets, Google Drive 등)를 자동화할 수 있는 클라우드 기반 스크립팅 도구입니다. 문서나 스프레드시트 작업을 자동화하는 데도 사용할 수 있지만, 단독으로도 사용할 수 있습니다.

충분한 서비스 할당량을 무료로 제공하고 있기 때문에, 개인이나 소규모 프로젝트 수준에서 대부분의 작업을 비용 없이 처리할 수 있습니다.

Google Apps Script를 사용해서 서울사랑상품권 발행 공지 사항을 크롤링하고 메시지로 전송하는 방법을 알아보겠습니다. 제공하는 코드를 응용해서 어렵지 않게 다른 용도로도 활용할 수 있을 것으로 생각합니다.

서울사랑상품권 발행 공지 사항 크롤링

먼저, 서울사랑상품권 발행 공지 사항의 제목과 링크를 수집해 보겠습니다.

Google Apps Script는 기본적으로 HTML Parser를 제공하지 않습니다. XML Parser를 제공하지만, HTML 문서는 구조가 엄격하지 않고 문법 오류에도 관대하기 때문에 XML Parser를 활용하는 데는 한계가 있습니다.

외부 JavaScript 라이브러리를 사용하면 되겠지만, 일반적인 방식은 아니고 Google Apps Script 라이브러리를 사용해야 합니다. 다행히 Cheerio 라이브러리Google Apps Script에서 사용할 수 있도록 작업해 준 선구자가 있습니다. Cheerio는 HTML 문서를 파싱하는 데 자주 사용되는 라이브러리입니다.

라이브러리 추가 팝업 캡쳐 이미지

Google Apps Script 편집기 화면 왼쪽에서 라이브러리 추가(+) 버튼을 누릅니다. 스크립트 ID에 1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0 를 입력하고, 조회 버튼과 추가 버튼을 누르면 Cheerio 라이브러리가 추가됩니다.

UrlFetchApp.fetch 메소드를 호출해 웹페이지를 가져오고, Cheerio 라이브러리로 원하는 데이터를 파싱합니다.

서울특별시 사이트의 검색 페이지를 크롤링하는 코드입니다:

function run() {
  // 서울특별시 사이트의 검색 페이지를 크롤링합니다
  const URL =
    "https://news.seoul.go.kr/economy/news-all?category&category_1=0&category_2=0&keyword=%EB%B0%9C%ED%96%89";
  const PROPERTY_KEY = "lastLink";

  // '프로젝트 설정 > 스크립트 속성'에 접근합니다
  const props = PropertiesService.getScriptProperties();

  const response = UrlFetchApp.fetch(URL);
  const html = response.getContentText();
  const $ = Cheerio.load(html);
  const elements = $("h3 > a");

  // 스크립트 속성에서 마지막 링크를 가져옵니다
  const lastLink = props.getProperty(PROPERTY_KEY);
  let currentLink = null;

  for (const el of elements) {
    const title = el.attribs["title"];
    const link = el.attribs["href"];
    if (!title.includes("상품권")) {
      // 제목에 '상품권' 단어가 없으면 무시합니다
      continue;
    }

    if (link === lastLink) {
      // 지난번 실행 시 저장한 최신 링크와 동일한 링크부터는 체크하지 않습니다
      break;
    }

    if (!currentLink) {
      currentLink = link;
    }

    // Telegram으로 알림 메시지를 전송합니다
    const message = `${title}\n${link}`;
    sendMessage(message);
  }

  if (currentLink) {
    // 현재 가장 최신 링크를 스크립트 속성에 저장해둡니다
    props.setProperty(PROPERTY_KEY, currentLink);
  }
}

각 스크립트(프로젝트)는 스크립트 속성으로 간단한 데이터를 저장할 수 있습니다. 이를 활용해서, 동일한 글을 여러 번 전송하지 않도록 가장 최신 링크를 저장합니다. PropertiesService.getScriptProperties 메소드를 호출해 불러와서 읽고 쓸 수 있습니다.

이제, 서울사랑상품권 발행 공지 사항의 제목과 링크를 Telegram 메시지로 전송해 보겠습니다.

Telegram 메시지로 알림 받기

Telegram은 Bot API를 무료로 제공하기 때문에 알림 메시지를 받기에 적합합니다. Discord나 Slack 등 다른 플랫폼에서도 유사한 기능을 활용할 수 있습니다.

저는 Telegram Bot API를 사용하여 알림 메시지를 전송해 보겠습니다. 우선, Telegram Bot Token과 Chat ID가 필요합니다. 자세한 방법은 다른 분이 쓰신 Telegram Bot Token 및 Chat Id 얻기를 참고하세요.

Telegram을 통해 메시지를 전송하는 코드입니다:

function sendMessage(message) {
  const TOKEN = "123456789:XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX"; // Telegram Bot Token
  const CHAT_ID = "-1002426873759"; // Telegram Chat ID

  const url = `https://api.telegram.org/bot${TOKEN}/sendMessage`;
  const options = {
    method: "POST",
    payload: {
      chat_id: CHAT_ID,
      text: message,
    },
  };

  UrlFetchApp.fetch(url, options);
}

실행 트리거 설정

작성한 코드를 매일 자동 실행하도록 트리거를 설정할 수 있습니다. Google Apps Script에서는 무료로 하루 90분 동안 실행할 수 있고, 1회 실행하는데 10초 정도 걸린다고 가정하면 하루에 최대 540번 실행할 수 있습니다.

단, 트리거를 설정할 때 정확한 시각 설정은 할 수 없고, 설정한 시각에서 최대 ±15분의 오차가 발생할 수 있습니다. 실시간 알림이 필요하다면 적합하지 않을 수 있지만, 하루 한 번 또는 한 시간에 한 번 정도 실행하면 되는 경우에는 유용하게 사용할 수 있습니다.

트리거 메뉴에서 UI로 설정할 수도 있지만, 분 단위로 세밀하게 설정하기 위해서 코드를 사용해 등록하길 추천합니다. 코드를 작성하고, 저장 후에 함수를 선택해 1회 실행해 줍니다.

setTrigger 함수를 선택하고 실행하는 모습

1일 1회 원하는 시각에 동작하도록 트리거를 설정하는 코드입니다:

function setTrigger() {
  // 권한 획득을 위해 1회 호출합니다
  UrlFetchApp.fetch("http://www.example.com");

  const triggers = ScriptApp.getProjectTriggers();
  if (triggers.length > 0) {
    // 이미 등록된 트리거 있으면 등록하지 않습니다
    return;
  }

  ScriptApp.newTrigger("run")
    .timeBased()
    .everyDays(1) // 1일마다
    .atHour(14) // 14시
    .nearMinute(0) // 0분경에 실행됩니다
    .inTimezone("Asia/Seoul") // 시간대 설정
    .create();
}

ClockTriggerBuilder 문서를 참고해 시각 기반 트리거 설정 옵션을 확인할 수 있습니다.

'승인 필요' 팝업 캡쳐 이미지
"이 프로젝트에서 내 데이터에 액세스하려면 내 승인이 필요합니다"

코드를 최초 실행하면 데이터 액세스 승인을 요구하는 팝업이 뜹니다. ‘권한 검토’를 눌러 승인하면 됩니다.

'Google에서 확인하지 않은 앱' 팝업 캡쳐 이미지
"앱에서 Google 계정의 민감한 정보에 대한 액세스를 요청합니다."

“Google에서 확인하지 않은 앱”이라고 출력되면, 고급 설정을 누르고 ‘제목 없는 프로젝트(으)로 이동(안전하지 않음)’을 누르면 됩니다.

‘서울사랑상품권 알림’ Telegram 채널

위의 코드를 사용해서 ‘서울사랑상품권 알림’ Telegram 채널을 운영하고 있습니다. Telegram 앱에서 구독해 공지 사항 알림을 받으실 수 있습니다.

또한, 제공된 코드를 사용해 직접 채널을 만들어 운영하실 수도 있습니다. 코드를 응용해서 자신만의 채널을 만들어 보시기 바랍니다.

태그 : , ,

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다