ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. 텔레그램(telegram) 봇(bot)에 날씨 기능을 추가하자
    Python/telegram-bot 2020. 11. 9. 13:00
    반응형

    기상청 크롤링, XML 파싱에 관한 글을 올린 적 있습니다. 
    크롤링에 대한 설명은 위 링크를 참고하십시오. 

    datetime

    기상청 RSS 데이터는 발표일을 기준으로 0일, 1일, 2일 까지의 데이터가 담겨 있습니다. 
    보기 좋게 출력하려면 발표일, 발표일 + 1일, 발표일 + 2일을 처리해야 하는데요. 
    날짜에 관련된 계산을 하려면 꽤나 복잡하기 때문에 기본 내장 라이브러리를 사용하는 게 편합니다. 

    파이썬에서 날짜에 관련된 계산을 할 때는 datetime의 timedelta를 이용합니다. 

    사용법은 다음과 같습니다. 

    • 모년 모월 모일에서 2일 후를 계산해야한다면 날짜가 담긴 datetime 객체를 만들어야 합니다.
    • 직접 객체를 만들어도 됩니다만,
    • 만약 년월일이 담긴 문자열이 있다면 strptime 메서드로 날짜를 추출해서 datetime 객체를 만들 수 있습니다.
    • 이제 만들어진 datetime 객체에 timedelta(=2일)을 더해줍니다.
    • 마지막으로 출력할 때는 strftime 메서드를 이용하면, 원하는 문자열 포맷으로 출력할 수 있습니다.

     

    아래 코드에서 사용하진 않았습니다만 참고로...
    타임델타 값으로 1달은 사용할 수가 없습니다.
    1달의 날수가 31, 30, 29, 28로 왔다 갔다 하기 때문인 것 같습니다. 
    별도의 라이브러리(dateutil.relativedelta)로 해결할 수 있습니다. 

    서울 강남 개포1동 RSS 주소 : https://www.kma.go.kr/wid/queryDFSRSS.jsp?zone=1168066000 

    import xml.etree.ElementTree as ET
    from datetime import datetime, timedelta
    from urllib import request
    
    from telegram import Bot
    from telegram.ext import Updater, MessageHandler, Filters
    
    
    def weather():
        r = request.urlopen('http://www.kma.go.kr/wid/queryDFSRSS.jsp?zone=168066000')
        xml_data = r.read().decode()
        xml_root = ET.fromstring(xml_data)
        announce_time = datetime.strptime(xml_root.find('.//tm').text, '%Y%m%d%H%M')
        result = xml_root.find('.//item/category').text + '\n'
        result += f"발표: {announce_time.strftime('%Y-%m-%d %H:%M')}" + '\n'
        for each in xml_root.findall('.//data'):
            if each.find('day').text == '2':
                continue
            forecast_date = announce_time + timedelta(days=int(each.find('day').text))
            result += f"{forecast_date.strftime('%d')}일 " \
                      f"{each.find('hour').text:>02}시, " \
                      f"{float(each.find('temp').text):.0f}℃, " \
                      f"{each.find('wfKor').text}, " \
                      f"강수확률: {each.find('pop').text}, " \
                      f"습도: {each.find('reh').text}, " \
                      f"풍속: {float(each.find('ws').text):.1f}" \
                      '\n'
        return result
    
    
    def echo(update, context):
        user_id = update.effective_chat.id
        msg = update.message.text
        print(msg)
        if '안녕' in msg or '하이' in msg:
            context.bot.send_message(chat_id=user_id, text='방가 방가')
        elif '날씨' in msg:
            context.bot.send_message(chat_id=user_id, text=weather())
        elif '주식' in msg:
            context.bot.send_message(chat_id=user_id, text='주식는 안 알랴줌')
        elif '사진' in msg:
            context.bot.send_message(chat_id=user_id, text='잠시만')
            context.bot.send_photo(chat_id=user_id, photo=open('img.png', 'rb'))
        else:
            context.bot.send_message(chat_id=user_id, text=f'미안 {msg}이(가) 뭔지 잘 몰라.')
    
    
    token = '<>:<>'
    chat_id = 000000000
    
    bot = Bot(token=token)  # 봇 객체 생성
    
    bot.sendMessage(chat_id=chat_id, text="봇을 실행합니다.")  # 메세지 보내기
    
    updater = Updater(token=token, use_context=True)
    dispatcher = updater.dispatcher
    
    echo_handler = MessageHandler(Filters.text & (~Filters.command), echo)
    dispatcher.add_handler(echo_handler)
    
    updater.start_polling()

    반응형
Designed by Tistory.