동기

최근에 IT로 시각장애인 도서제작이라는 사이트에서 책의 내용을 문서로 옮기는 봉사활동 시작했다. 기초 교육을 받고 정회원이 되면 도서 제작에 참여할 수 있는데 문제는 공급(제작해야 할 책)보다 수요(제작자)가 많아서 도서 제작을 하고 싶어도 아무때나 할 수 없다는 것이다. 마치 티켓팅같다. 새로운 책이 등록되더라도 대략 10분정도면 페이지 할당이 끝난다. 새로운 책이 등록되면 홈페이지에 내부적으로 알림이 뜨기는 하지만 이는 홈페이지에 접속해 있을 때만 확인이 가능하다. 그래서 나는 새로운 책이 등록되면 내가 바로 확인을 할 수 있으면 좋겠다는 생각이 들었고, 바로 실행에 옮기게 되었다.

과정

[참고한 영상] https://www.youtube.com/watch?v=eJAC596oHSA

Kakao Developers

+) 내 애플리케이션 > 카카오 로그인 > 동의항목 > 접근권한에서 오른쪽 그림과 같이 카카오톡 메시지 전송 항목을 동의해줘야 권한 오류가 나지 않는다.

+) 도구는 'REST API 테스트'에서 메시지 > 나에게 기본 템플릿으로 메시지 보내기를 사용했다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1b2d925b-2220-4196-8519-fe1901603cee/Untitled.png

import requests
import json
from bs4 import BeautifulSoup
import re
import time
from datetime import datetime

# 토큰 갱신 6시간마다 => <https://developers.kakao.com/tool/rest-api/open/post/v2-api-talk-memo-default-send>
KAKAO_TOKEN = "-g_Rygit-vhddtbYOEpgCCMydXIsOlOaQQdFkwo9cxcAAAF6o4hETA"

def sendToMeMessage(text):
    url = "<https://kapi.kakao.com/v2/api/talk/memo/default/send>"

    # 사용자 토큰
    headers = {
        "Authorization": "Bearer " + KAKAO_TOKEN
    }

    data = {
        "template_object" : json.dumps({ "object_type" : "text",
                                         "text" : text,
                                         "link" : {
                                                     "web_url" : "www.naver.com"
                                                  }
        })
    }

    response = requests.post(url, headers=headers, data=data)
    print(response.status_code)
    if response.json().get('result_code') == 0:
        print('메시지를 성공적으로 보냈습니다.')
    else:
        print('메시지를 성공적으로 보내지 못했습니다. 오류메시지 : ' + str(response.json()))

def alarm_books():
    url = "<https://www.itlo.org/booking>"
    r = requests.get(url) # url에 접근
    # 참고로 r.text는 binary, r.content는 str형태의 데이터이다.
    bs = BeautifulSoup(r.content, "lxml") # "lxml"이라는 parser가 앞서 가져온 데이터에서 html요소로 접근
    divs = bs.select("div.col-xs-12.col-md-6.col-lg-3.cropbkiddata") # select의 결과 = 리스트
    #print(len(divs[0]))

    # 시간 출력 => <https://codechacha.com/ko/python-get-current-time/> 참고함
    current_time = datetime.now()
    print('-' * 10)
    print("{hour}시 {minute}분".format(hour=current_time.hour,
                                      minute=current_time.minute))
    print('-' * 10)

    for d in divs:
        images = d.select("img")[0]
        image = images.get("src")
        ahref = d.select("a")
        link = ahref[0].get("href")
        title = ahref[1].select("font")[0].text # 태그 사이의 글은 text로 접근 가능
        #available = d.select("div")[-1].get("style")

        # 상대주소로 되어있기 때문에 앞에 도메인 주소를 붙여줘야함.
        #print("<https://www.itlo.org>" + image)
        #print("<https://www.itlo.org>" + link)
        print(title)
        #print(available)

        b_url = "<https://www.itlo.org>" + link
        b_r = requests.get(b_url)
        bbs = BeautifulSoup(b_r.content, "lxml")
        b_pages = bbs.select("span")[-1].text
        print(b_pages)
        numbers = re.findall(r'\\d+', b_pages)

        text_form = "[NEW!!] 제작가능한 도서 등록됨\\n{link}\\n제목:{title}\\n{book_pages}"

        if numbers[0] != '0':
            info = text_form.format(link="<https://www.itlo.org>" + link,
                                    title=title,
                                    book_pages=b_pages)
            print(info)
            return info

if __name__ == "__main__":
    while True:
        try:
            text = alarm_books()
            if text != None:
                sendToMeMessage(str(text))
            time.sleep(60*5)    #5분
        except KeyboardInterrupt:
            print("You pressed 'CTRL+C'. Stop running program.")
            break

결과

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/dde8d7ee-9066-4b17-8038-c6d0854428ac/Untitled.png

와 성공!!ㅎㅎ

단점이 있다면 자신에게 보내는 카톡이라 상단바에 알림이 뜨지는 않는다는 점..

그래도 덕분에 봉사활동하기가 수월했다.

카톡 토큰이 만료되면 새로 발급받아야 해서 이 부분도 자동화하도록 코드를 짠다면 더 편할 것이다.

그리고 지금은 낮에만 실험을 해봤는데 나중에 서버에 올려서 코드를 실행해두면 알림을 계속해서 받을 수 있을 것이다.

아쉬운 점 및 해결방안

관련 활동 바로가기

  1. 웹페이지 알림 카카오톡으로 보내기 [2021-07-12]
  2. Slack을 이용해 웹페이지 알림 보내기 [2021-07-23~2021-07-24] 👈 NEXT
  3. Selenium을 이용해 동적인 웹크롤러 만들기 [2021-08-08]