Intro
블로그 첫 프로젝트가 끝났습니다.
다음에 다른 프로젝트로 찾아뵙겠습니다.
한라대학교 공지 알림 봇 제작기를 읽어주신 모든분들께 감사드립니다.
최종 코드
일반 공지_ver
# -*- coding: utf-8 -*-
########## 서비스 코드
import requests
from bs4 import BeautifulSoup
import os
import telegram
import sys
import time
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
my_token = '봇 토큰'
my_chat_id = "채널 주소 / 서비스 채널은 '@***' / 테스트 채널은 '-***'"
req = requests.get('http://www.halla.ac.kr/mbs/kr/jsp/board/list.jsp?boardId=23401&mcategoryId=&id=kr_060101000000')
client_errors = [400, 401, 403, 404, 408]
server_errors = [500,502, 503, 504]
print(time.strftime("%c", time.localtime(time.time())))
if req.status_code in client_errors:
print(req.status_code + ": 클라이언트 에러")
sys.exit(1)
elif req.status_code in server_errors:
print(req.status_code + ": 서버 에러")
sys.exit(1)
bot = telegram.Bot(token=my_token)
html = req.text
soup = BeautifulSoup(html, 'html.parser')
posts = soup.select('td > a')
num = soup.find_all(title='공지')
for i in range(len(num)): # 공지로 위로 올라간 게시글 제외한 최신 게시글 분류
del posts[0]
if not(os.path.isfile(os.path.join(BASE_DIR, 'latest.txt'))):
new_file = open("latest.txt", 'w+',encoding='utf-8')
new_file.write(posts[0].text)
new_file.close()
with open(os.path.join(BASE_DIR, 'latest.txt'), 'r+',encoding='utf-8') as f_read: # DB 구현후 변경 에정
before = f_read.readline()
for post in posts: # 기존 크롤링 한 부분과 최신 게시글 사이에 게시글이 존재하는지 확인
print("post = " + post.text)
print("before = " + before)
if before == post.text:
print("최신글입니다.")
break
elif before != post.text:
url = "http://www.halla.ac.kr/mbs/kr/jsp/board/" + post.get('href')
print(url)
try:
if post != posts[10]:
bot.sendMessage(chat_id=my_chat_id, text="일반공지 : " + post.text)
bot.sendMessage(chat_id=my_chat_id, text=url)
else:
break
except Exception as ex:
print("timeout") # 짧은 시간에 message를 과도하게 보내면 timeout이 뜨는것같다.
break # message를 많이 보내서 발생한다기 보다는, 한번에 보낼 수 있는 url의 양이 10개로 제한되어 있는듯
with open(os.path.join(BASE_DIR, 'latest.txt'),'w+',encoding='utf-8') as f_write:
f_write.write(posts[0].text)
학사 공지_ver
# -*- coding: utf-8 -*-
########## 서비스 코드
import requests
from bs4 import BeautifulSoup
import os
import telegram
import sys
import time
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
my_token = '봇 토큰'
my_chat_id = "채널 주소 / 서비스 채널은 '@***' / 테스트 채널은 '-***'"
req = requests.get('http://www.halla.ac.kr/mbs/kr/jsp/board/list.jsp?boardId=23409&id=kr_060102000000')
client_errors = [400, 401, 403, 404, 408]
server_errors = [500,502, 503, 504]
print(time.strftime("%c", time.localtime(time.time())))
if req.status_code in client_errors:
print(req.status_code + ": 클라이언트 에러")
sys.exit(1)
elif req.status_code in server_errors:
print(req.status_code + ": 서버 에러")
sys.exit(1)
bot = telegram.Bot(token=my_token)
html = req.text
soup = BeautifulSoup(html, 'html.parser')
posts = soup.select('td > a')
num = soup.find_all(title='공지')
for i in range(len(num)): # 공지로 위로 올라간 게시글 제외한 최신 게시글 분류
del posts[0]
if not(os.path.isfile(os.path.join(BASE_DIR, 'latest_haksa.txt'))):
new_file = open("latest_haksa.txt", 'w+',encoding='utf-8')
new_file.write(posts[0].text)
new_file.close()
with open(os.path.join(BASE_DIR, 'latest_haksa.txt'), 'r+',encoding='utf-8') as f_read: # DB 구현후 변경 에정
before = f_read.readline()
for post in posts: # 기존 크롤링 한 부분과 최신 게시글 사이에 게시글이 존재하는지 확인
print("post = " + post.text)
print("before = " + before)
if before == post.text:
print("최신글입니다.")
break
elif before != post.text:
url = "http://www.halla.ac.kr/mbs/kr/jsp/board/" + post.get('href')
print(url)
try:
if post != posts[10]:
bot.sendMessage(chat_id=my_chat_id, text="학사공지 : " + post.text)
bot.sendMessage(chat_id=my_chat_id, text=url)
else:
break
except Exception as ex:
print("timeout") # 짧은 시간에 message를 과도하게 보내면 timeout이 뜨는것같다.
break # message를 많이 보내서 발생한다기 보다는, 한번에 보낼 수 있는 url의 양이 10개로 제한되어 있는듯
with open(os.path.join(BASE_DIR, 'latest_haksa.txt'),'w+',encoding='utf-8') as f_write:
f_write.write(posts[0].text)
코드를 수정하면서 배운점
- 생각하지도 못한 곳에서 에러가 발생할 수 있다.
- 따라서 에러가 발생 가능한 부분에서 예외처리를 해줘야한다.
- 윈도우의 기본 인코딩 ANSI가 리눅스에 올라가면 한글이 깨진다는 것을 알았다.
- 한글이 깨져서 많이 당황했다. 여러 방법을 써도 해결할 수 없었다.
- 그때 BLEX님이 윈도우에서는 ANSI를 쓴다고 알려줘서 해결했다.
- 코드에 쓸데 없는 반복문을 제거했다.
- 리눅스의 Crontab을 통해 1시간에 한번만 동작하게 해줘도 서버에 부담을 줄여줄 수 있다.
- 반복문을 써서 최신글이 나오자 마자 확인하는 것도 좋지만, 1시간에 한번씩 확인하는 것도 나쁘지 않다.
- 좀 더 응용하면 매주 월-금, 09:00 ~ 18:00, 1시간에 한번씩 확인하는 것이 제일 좋다.
- 블로그를 통해 내가 만든 코드를 설명하는 것이 많이 도움이 된다.
- 이 코드를 처음 작성한 년도가 18년도 아니면 17년도이다. 전역하고 많이 까먹었는데 블로그 포스팅을 위해 Document도 읽어보고 코드를 한줄 한줄 다시 짜보면서, 이제는 조금 알겠다는 느낌이 든다.
참고문헌
notice_alarm, "https://github.com/mildsalmon/notice_alarm", [mildsalmon]
- 따라서 에러가 발생 가능한 부분에서 예외처리를 해줘야한다.
- 한글이 깨져서 많이 당황했다. 여러 방법을 써도 해결할 수 없었다.
- 그때 BLEX님이 윈도우에서는 ANSI를 쓴다고 알려줘서 해결했다.
- 리눅스의 Crontab을 통해 1시간에 한번만 동작하게 해줘도 서버에 부담을 줄여줄 수 있다.
- 반복문을 써서 최신글이 나오자 마자 확인하는 것도 좋지만, 1시간에 한번씩 확인하는 것도 나쁘지 않다.
- 좀 더 응용하면 매주 월-금, 09:00 ~ 18:00, 1시간에 한번씩 확인하는 것이 제일 좋다.
- 이 코드를 처음 작성한 년도가 18년도 아니면 17년도이다. 전역하고 많이 까먹었는데 블로그 포스팅을 위해 Document도 읽어보고 코드를 한줄 한줄 다시 짜보면서, 이제는 조금 알겠다는 느낌이 든다.
notice_alarm, "https://github.com/mildsalmon/notice_alarm", [mildsalmon]
Ghost