글 작성자: 개발섭

파이썬으로는 많은 개발을 할일이 없었는데, Telegram 봇을 만져보고 작동하다보니 꽤 재밌어서 학교 공지사항 봇을 만들게 되어서 포스팅 하게 되었습니다.

 

일단 왜 만들게 되었는지?

최근 코로나 19 사태로 학교에서 이런저런 공지사항이 올라오는데요. 어떤 공지사항은 꽤 중요하고, 어떤 사항은 저랑은 상관없는 소식이기도 하니, 이런 저런 공지사항을 읽어보거나 읽지 않거나 선택적으로 골라서 봐야했습니다.

그걸 제가 직접적으로 공지사항을 확인하기 위해서 매일매일 학교 공지사항을 확인하기는 너무 귀찮기도하고, 개인적으로 저희에게 메세지가 오는 것도 없어서 차라리 이런 공지가 올라올때마다 봇으로 알람을 울리게 하는 것이 좋다고 생각했습니다.

 

밑에 학부 공지사항이 있다. 혹은 직접적으로 공지사항으로 눌러서 확인해도 가능

크롤링하기에는 저희 학과 홈페이지가 통합되면서 훨씬 크롤링하기에는 훨씬 어떤 자료형을 찾아야할지 명확해서 좋았습니다만. 이 자료가 최신 자료인지 업데이트될때 처리할때문제가 생겼습니다. 

공지를 맨위에 올리기위해서 번호를 notice처리를 하게되면, 

<img src="_oxdir/templates/oxbbs/bbs/responsive/__magicdir__/image/ic_notice.gif" border="0" valign="middle" alt="공지">

번호가 아니라... img로 처리되기 버리기때문에 번호를 통해서 이 게시물이 최근에 생성됬는지 파악하기가 어려웠습니다. 

 

그러면 어떤식으로 최근 게시물인지 파악할까?

사실 학과에서 공지를 할때 공지사항이 정말 많아봐야 하루에 5건이 넘지 않습니다. 거기에 덤으로 하루에 6개의 공지사항을 한번에 올리지도 않기때문에 많은 양을 한번에 비교할 필요가 없습니다.

그래서 가장 최신의 공지사항 게시물을 올려주고 적은량 사진처럼 학과 홈페이지 첫 페이지에 나오는 공지사항 탭입니다. 그러면 그 학과 공지사항의 탭으로 6개의 가장 최신의 공지사항을 매번 확인할 수 있습니다.

 

물론 날짜로 매번 비교해서 해도 되지만. 같은 게시물인지 파악이 어려울 수도 있기 때문에, 저는 이 title명의 변화에 따라서 이 게시물이 최신 게시물이 있는지를 체크했습니다.  

그리고 파이썬에서는 이전 게시물 목록 리스트와 새로 크롤링한 게시물 리스트 두개를 집합으로 비교하여 차집합 처리를 할 수 있어서 차집합을 통해 새로운 게시물이 만들어진다면, 새로 크롤링해 가져온 리스트를 최신리스트로 DeepCopy합니다.

그리고 새로 생긴 공지사항마다 telegram-bot에게 메세지를 전달하는 방식으로 처리했습니다.

또한 git-hub에 올리기 위해서 telegram Token과 오류 발생시 다른 봇에게 전달하기위한 채널번호를 YAML파일에 만들어서 따로 보관중이라서 Security 처리도 따로 해두었습니다.

마지막으로 학교 서버부하를 줄이기위해서, 15분 간격으로 업데이트를 확인하게끔하여 부하를 줄이게 했습니다.

물론 이전의 많은 코드들도 있었으나 Security처리를 안하고 올렸어서 그걸 지워보려고 하다가 git이 완전꼬여서... 그냥 엎고 새로 만들었습니다. ㅠ 그래서 커밋양이 상대적으로 부족합니다. ㅠ

#!/usr/bin/env python
# encoding=utf-8
import requests
import time
from bs4 import BeautifulSoup
import telegram
import copy
import yaml

yamldoc = yaml.load(open('securityToken.yml의 절대경로', 'r'), Loader=yaml.FullLoader)
bot = telegram.Bot(token=yamldoc['telegram']['botToken'])
chatBot_id = bot.getUpdates()[1].channel_post.chat.id

if __name__ == '__main__':
    try:
        print("강대 컴정 공지사항 봇")
        changeList = None
        while True:
            req = requests.get('https://cse.kangwon.ac.kr:60443/')
            html = req.text
            soup = BeautifulSoup(html, 'html.parser')
            checklist = []
            noticesCrop = soup.find("div", {"class": "tab t1 on"})
            noticeList = noticesCrop.find_all("li")
            for i in noticeList:
                title = i.find("a").get("title")
                herf = i.find("a").get("href")
                noticetTime = i.find("span").text
                checklist.append([title, herf, noticetTime])
                print(title)
            if changeList is None:
                changeList = copy.deepcopy(checklist)
            print(checklist)
            # 비교
            setChange = set(tuple(row) for row in changeList)
            setCheck = set(tuple(row) for row in checklist)
            diff = setCheck - setChange
            if len(diff) > 0:
                changeList = copy.deepcopy(checklist)
            for index in diff:
                print(index[0])
                botText = '<strong>[강대 컴퓨터학과 공지사항 업데이트]</strong>'+'\n\n'
                botText = botText+'<strong>'+index[0]+'</strong>\n\n'
                botText = botText+'<i>'+index[2]+'</i>\n'
                botText = botText +"https://cse.kangwon.ac.kr:60443/"+index[1]
                bot.send_message(chat_id=chatBot_id, text=botText, parse_mode=telegram.ParseMode.HTML)
            print('작동중!')
            time.sleep(900) # 15분 간격으로 크롤링 >
    except Exception as es:
        print("오류 발생!!! 오류원인: "+str(es))
        bot.sendMessage(yamldoc['telegram']['channelNum'], u'강대 컴정봇이 맛탱이가 갔습니다 확인해주세요.' + '   ' + str(es))

 

그럼 텔레그램에 새로운 공지사항이 뜰때마다, 다음과 같이 메세지가 발송됩니다.

 

간단한 텔레그램 봇 라이브러리와 아주 심플한 BeautifulSoup4의 기능만 사용해서 컴퓨터공학과의 봇을 만들었습니다. 호옥시 강원대 컴퓨터공학과에 다니시는 분들이 이 게시글을 보게되면, 채널 입장하실수 있게 링크 남겨 두겠습니다.

 

강원대학교 컴퓨터공학과 공지사항 봇채널 텔레그램 링크:  https://t.me/joinchat/AAAAAEjNqvNJKMALKCuDaw

 

강원대학교 컴공 공지사항 알림봇

 

t.me

 

읽어주셔서 감사합니다!

 

참고 링크들

1. 텔레그램 봇 만들기

https://kslee7746.tistory.com/entry/%ED%85%94%EB%A0%88%EA%B7%B8%EB%9E%A8-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B2%8C%EC%8B%9C%EB%AC%BC-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%95%8C%EB%9E%8C-%EB%B4%87-%EB%A7%8C%EB%93%A4%EA%B8%B01