[BeautifulSoup4] Python 게시판 크롤러 텔레그램 봇 제작기(2)

(1)편의 게시판 크롤링에 이은  텔레그램 봇 제작기입니다.

 

1. 토큰(Token) 발급받기

먼저, 텔레그램 봇의 토큰을 발급받기 위해 @BotFather에게 말을 겁니다.

/newbot (새로운 봇 생성) 부터 시작하여 봇 이름 생성, username을 생성하여 토큰을 발급받습니다.

토큰은 000000000:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 형태로 되어 있습니다.

발급받은 토큰은 작성한 봇의 권한을 가지게 되므로 외부로의 유출에 주의하시기 바랍니다.

봇 이름이 이미 있는 경우 다시 입력하라고 친절하게 안내해 준다

2. 간단한 Echo 봇 작성

토큰을 발급했으니 간단한 봇을 작성해 보겠습니다.

 

먼저 telegram bot 사용을 위해 모듈을 설치해 줍니다.

$pip install python-telegram-bot --upgrade

또는 소스 코드를 직접 내려받아 사용하는 경우 다음과 입력합니다.

$git clone https://github.com/python-telegram-bot/python-telegram-bot
$cd python-telegram-bot
$python setup.py install

그리고 파이썬에서 다음 코드를 입력합니다.

import logging
from telegram.ext import Updater, MessageHandler, Filters

my_token = '9000000000:AAAAAAAAAAAAAAAA'  # 여기에 토큰 입력 또는 저장해둔 토큰 불러오기


def get_message(update, context):
    print(update.message)


if __name__ == "__main__":
    updater = Updater(my_token, use_context=True)

    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
    dp = updater.dispatcher
    dp.add_handler(MessageHandler(Filters.text, get_message))  # text가 입력되면 get_message 메소드 호출

    updater.start_polling(timeout=3, clean=True)
    updater.idle() #계속 데이터를 polling하며 사용자 입력 대기

입력하고 텔레그램에서 자신의 봇을 찾아서 메시지를 보내게 되면 파이썬 콘솔 창에 메시지가 시현된다.(일부 값은 프라이버시 보호 되었다.)

 

단순히 "입력한 메시지"만 전달하는 게 아니라 많은 정보들을 주고 받는 것을 알 수 있다. 메시지가 입력될 때 마다 객체가 전달되므로 사용자의 입맛에 맞게 코드라인을 수정하여 필요한 정보를 취할 수 있다.

 

만약 보낸 사람의 이름을 가져오고 싶다면 다음과 같이 작성한다.

update.message.from_user["first_name"]

받은 메시지를 문자열로 가져오고 싶다면 다음과 같이 작성한다.

update.message.text

지금은 봇이 전송할 채팅방의 ID를 알아야 하기 때문에 다음과 같이 작성한다.

update.effective_message.chat_id

이렇게 하면 마지막으로 채팅을 수신한 채팅방의 id 값을 가지게 된다.

이제 이 id 값을 가지고 봇에서 메시지를 보내면 되는 것이다.

 

메시지를 보내기 위해 방금 작성했던 get_message메소드를 다음과 같이 수정한다.

def get_message(update, context):
    print(update.message)
    context.bot.send_message(chat_id=update.effective_message.chat_id, text="저는 봇이예요!")

이렇게 하면 어떤 메시지든 수신을 하면 지정한 텍스트를 봇이 전송한다.

저는 봇이에요!

 

3. 채널에서 봇 메시지 보내기

게시판 새글 알림 봇은 혼자만 보기에는 그 기능이 아까운 경우들이 많다.

현재 많은 능력자분들이 지진정보알림, 기상청 날씨 정보, 온라인마켓 할인 정보 채널 등을 개설하여 모두에게 공유하고 있다.

 

먼저 텔래그램에서 채널을 생성한다. 적당한 이름과 적당한 사진을 첨부하여 단계를 진행한다.

Public 채널은 공개된 링크를 제공하며 누구나 검색을 통해 입장할 수 있는 채널이다.

Private 채널은 채널 소유자가 제공한 링크를 통해서만 입장할 수 있는 채널이다. 

Public 채널을 기준으로 설명하겠다.

 

채널을 생성하게 되면 아래 t.me 도메인을 생성할 수 있는데 이 도메인을 통해 채널에 입장할 수 있다.(또는 채널명의 검색을 통해 입장이 가능하다.)

채널을 생성한 후 앞의 단계에서 생성한 봇을 초대하고 관리자 권한을 부여해야 한다. 개발자의 판단에 따라 권한을 부여해 주면 되지만 토큰 관리만 잘 해준다면

채널 소유자 권한 = 봇 관리 권한을 주는 것이 편하다.

봇의 권한 설정이 끝나면 코드를 작성한다.

보내야할 데이터를 메소드의 text의 인자로 전달해주면 된다.

아래는 새글알림 챗봇 코드의 일부입니다.

my_token = '000000000:000000000000000000' #여기에 토큰 입력
bot = telegram.Bot(token=my_token)

"""... 코드 일부 생략 ..."""

for p in soup.find_all("div", class_='activity-content'):
    if p.find(string=" started the topic "):
        pass
    elif p.find(string=" replied to the topic "):
        pass
    else:
        res = p.find("div", class_="activity-inner")


        after.append(res.get_text().strip())

try:
    with open(os.path.join(BASE_DIR, 'data.pickle'), 'rb') as f_read:
        before = pickle.load(f_read)

        if before != after: #저장해둔 글 목록과 새로 파싱한 글 목록을 비교해서 다르면 = 새글이 있다
            new = list(set(after) - set(before)) # 새글의 목록만 가져오기
            for i in new: # 새글을 전송
                bot.sendMessage(chat_id='@KAAMnoti', text=i) # 공개 채널인경우 '@t.me 도메인명'으로 id 전달 가능
            with open(os.path.join(BASE_DIR, 'data.pickle'), 'wb') as f_write:
                pickle.dump(after, f_write, pickle.HIGHEST_PROTOCOL) # 새글의 목록을 다음 비교를 위해 저장
        else: #새글이 없으면
            pass
except FileNotFoundError:
    with open(os.path.join(BASE_DIR, 'data.pickle'), 'wb') as f_write:
        pickle.dump(after, f_write, pickle.HIGHEST_PROTOCOL)

 

설명에 사용된 채널의 초대 링크입니다

https://t.me/KAAMnoti

 

 

4. 추가

텔레그램 봇 버전 12.0 부터 Updater의 사용과 콜백함수의 호출 방법에 변화가 생겼다.

https://github.com/python-telegram-bot/python-telegram-bot/wiki/Transition-guide-to-Version-12.0

Updater(token)의 사용을 지양하고 Updater(token, use_context=yes)의 사용을 권장하고 있다.

매개변수 전달을 context에 모두 포함시켜 전달하고 이러한 규칙을 지키지 않고 구 버전의 스타일을 사용하게 되면 deprecated 경고를 띄운다.

경고만 띄우고 프로그램의 진행에는 영향을 끼치지 않지만 그래도 구 버전 API의 사용은 보안, 성능과 연관되는 경우가 많기 때문에 코드를 수정했다.

블로그 내의 코드들을 수정중인 상태이며 이에 대한 코드 비교는 나중에 시간이 되면 추가하도록 하겠다.

반응형