파이썬 프로그래밍

파이썬 카카오톡 챗봇 만들기 flask 서버 및 api 사용하기

코니코니 2022. 10. 2. 06:00
반응형

여기저기 검색을 해보니까 카카오톡 챗봇 만들기 포스팅 대부분이 발화 패턴에 관한 정보밖에 없어서 개발자가 원하는 문장을 api에서 자체적으로 인식하고 출력하는 아주 간단한 기능을 만드는데 생각보다 많은 시간을 투자했네요. 그래도 성공했으니 정리해서 올려봅니다~

해당 포스팅에서는 최초 카카오톡 챗봇 만들기에 대해서는 기록하지 않았습니다. https://i.kakao.com 좌측 사이트에서 챗봇을 생성하지 않은 분들은 챗봇 생성 먼저 해주시면 됩니다. 챗봇 만들기는 타 포스팅을 참고하여 주세요!

파이썬 플라스크 서버에 원하는 코드를 넣어서 카카오톡 챗봇 api로 사용이 가능합니다. 예를 들어서 특정 문장이나 문구 등을 챗봇에 입력을 했을 때 특정 지역의 날씨나 뉴스기사 등 크롤링 된 내용을 챗봇으로 출력을 할 수도 있겠죠.

이러한 기능을 챗봇에서 활용하기 위해서는 flask와 ngrok 사용법을 배울 필요가 있습니다. ngrok 사용법에 관련된 글은 제 블로그 https://hotel-iu.tistory.com/25 포스팅에서 확인 가능합니다. 포스팅 내에서는 디장고 서버를 사용했지만 flask 또한 ngrok 사용방법은 동일합니다. (또는 구름 ide 사용해도 좋음!)

테스트로 생성한 코드는 아래와 같습니다.

from flask import Flask, request, jsonify
import requests
from bs4 import BeautifulSoup
import random

application = Flask(__name__)


@application.route("/", methods=['POST'])
def keyword():
    req = request.get_json()
    text_ck = req['userRequest']['utterance']
    text = '정보를 찾을 수 없습니다.'

    if str(text_ck).count('서울 날씨'):
        url = 'https://search.naver.com/search.naver?where=nexearch&query=%EC%84%9C%EC%9A%B8+%EB%82%A0%EC%94%A8&ie' \
              '=utf8&sm=tab_she&qdt=0 '
        response = requests.get(url)
        if response.status_code == 200:
            html = response.text
            soup = BeautifulSoup(html, 'html.parser')
            location = soup.find(class_='title_area _area_panel').find(class_='title').text
            weather_1 = soup.find(class_='weather_info').find(class_='temperature_text').text.replace(' 현재', '현재')
            weather_2 = soup.find(class_='weather_info').find(class_='summary').text.replace('  ', ' ')
            text = f'{location}\n{weather_1}\n{weather_2}'

    if str(text_ck).count('부동산 뉴스'):
        url = 'https://news.naver.com/main/list.naver?mode=LS2D&mid=shm&sid1=101&sid2=260'
        response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
        if response.status_code == 200:
            html = response.text
            soup = BeautifulSoup(html, 'html.parser')
            main_class = soup.find(class_='type06_headline').find_all('li')
            text = '부동산 뉴스 최신 기사정보 입니다.'
            num = 1
            for t in main_class:
                sub_urls = t.find_all('a')
                url = str(sub_urls[-1].get('href')).replace('\n', '')
                name = str(sub_urls[-1].text).replace('\n', '').replace('     ', '').replace('    ', '')
                try:
                    time = t.find(class_='date is_new').text
                except AttributeError:
                    time = t.find(class_='date is_outdated').text
                sub_text = f'\n\n[{num}]\n{name}\n{url}\n{time}'
                num += 1
                text = text + sub_text

    if str(text_ck).count('로또번호'):
        text = '로또번호 리스트 출력합니다.\n1등 갈끄니까~\n'
        lotto_list = []
        while len(lotto_list) != 10:
            lotto = random.sample(range(1, 46), 6)
            lotto.sort()
            if len(lotto_list) + 1 == lotto[0]:
                if lotto[5] >= 38:
                    lotto_list.append(lotto)

        for lo in lotto_list:
            text = f'{text}\n{lo}'

    # 답변 텍스트 설정
    res = {
        "version": "2.0",
        "template": {
            "outputs": [
                {
                    "simpleText": {
                        "text": text
                    }
                }
            ]
        }
    }

    # 답변 전송
    return jsonify(res)


if __name__ == "__main__":
    application.run(host='0.0.0.0', port=5000, threaded=True)

길게 설명 할 필요가 없습니다. 챗봇에서 사용자가 텍스트를 입력하면 text_ck 변수에 담깁니다. 이 담긴 내용에서 특정 문장이나 단어 등을 if문으로 체크하여 특정 단어가 있을 때 그에 해당하는 코드를 적용시켜 text 변수에 담고 챗봇에서 출력을 시키는 원리입니다. 위 코드에서는 3개의 if문이 있는데요. 서울 날씨와 뉴스기사, 그리고 랜덤 로또번호를 출력하는 기능이 들어가 있습니다.

flask와 위에서 설명한 ngrok를 열어둔 상태입니다. flask에서 포트가 5000으로 되어있기 때문에 ngrok에서 ngrok http 5000을 입력하여 실행하면 됩니다. 열어둔 flask와 ngrok를 끄면 서버 접속이 안되기 때문에 기능을 사용하기 위해서는 켜둬야 합니다. 이제 위에 Forwarding에 있는 http://1adb-218-52-119-4.ngrok.io로 되어있는 주소를 카카오톡 api url로 사용을 하면 됩니다. 아래 이미지를 참고합시다.

챗봇 api를 사용하기 위해서 먼저 스킬을 등록해야 합니다. 스킬 생성을 눌러줍니다.

설명에는 아무거나 문구를 넣어줘도 상관없습니다. 그리고 url 부분에는 기존에 생성한 ngrok 주소를 넣어주면 됩니다. 그리고 우측 상단에 저장을 꼭 눌러주세요!

스킬 저장을 하고 시나리오에서 폴백 블록으로 들어옵니다. 파라미터 설정에서 기존에 생성한 스킬을 클릭하고 1번으로 설정을 해줍니다.

스킬데이터를 눌러줍니다. 그리고 시나리오 또한 스킬과 동일하게 저장은 필수!

배포를 하고 카카오톡 자체적으로 테스트를 해도 되지만 위에 보이는 봇테스트를 클릭하여 api 기능을 테스트 해볼 수 있습니다.

사용자가 보내온 문장에서 로또번호, 부동산 뉴스 등 작성한 if문 코드가 작동하여 특정 내용을 출력하는 모습을 볼 수 있습니다. 그리고 지정하지 않은 문장을 입력하면 정보를 찾을 수 없다는 답변을 볼 수 있습니다.

아 그리고 api 스킬을 사용하는 경우 서버간 time out이 5초로 설정이 되어 있다고 합니다. 이말인 즉슨 사용자가 특정 문장을 입력하고 서버를 거쳐 챗봇에서 출력을 하는 시간이 5초가 넘어가면 출력이 안됩니다. 서버를 켜둔 컴퓨터의 사양이나 네트워크 상태가 좋지 않아서 통신이 원활하지 않으면 출력이 안될 수 있습니다.

처음에 flask 말고 goorm ide 무료 클라우드 환경으로 테스트를 해봤는데 클라우드의 경우 메모리도 적고 네트워크 통신이 원활하지 않아서 출력이 안되는 현상을 볼 수 있었습니다.

막상 만들고 나면 쉽지만 만들기 전에는 어려운 챗봇이네요..!

반응형