개요
지난번 메신저봇R을 이용해서 카카오봇을 만들고 echo 기능을 통해 뼈대를 만들었습니다.
https://quantrader.tistory.com/104
이번 포스팅은 기존 뼈대에 살을 덧대 기능확장을 해보고자 합니다. 지역별 날씨를 챗봇에게 물어보면 네이버 날씨 검색과 html 파싱을 통해 챗봇이 답을 해주는 방식입니다.
본문
챗봇에게 질의하는 부분은 /날씨 '지역' 의 형태로 입력할 것이며 챗봇은 입력받는 데이타를 파싱해서 날씨 질의가 들어온 경우 네이버 검색을 통해 날씨 정보를 받아와서 정제한 후 응답을 하도록 할것입니다.
먼저 네이버 날씨 검색을 위해 아래 url 입력을 통해 나오는 결과 데이타 html을 파싱하는 작업을 할것입니다.
https://m.search.naver.com/search.naver?&query=날씨+서울
위 url을 통해 나오는 네이버 날씨 검색 결과는 아래와 같이 나오게 됩니다.
현재 검색 지역의 온도와 어제와의 온도차이, 체감온도, 습도, 풍속 정보가 나오게 되는데 이 정보를 파싱해서 뿌려보도록 하겠습니다.
크롬에서 f12 버튼을 통해 개발자 도구를 띄워봅니다.
개발자 도구 좌측 상단의 마우스커서 포인트 버튼을 통해 우리가 파싱하고자 하는 온도에 커서를 갖다대면 해당 부분의 html 코드를 볼 수 있습니다. 현재 온도는 div class="temperature_text" 아래에 blind 라는 클래스 span 태그 안에 텍스트 값으로 존재하고 있습니다.
어제와의 온도차이는 "temperature up" 클래스 아래 텍스트로 존재합니다. 높은지 낮은지에 대해서도 하위 blind 클래스의 span 태그 아래에 존재하는데 상위 "temperature up" 클래스 아래 전체 텍스트를 가져오면 해결이 됩니다.
카카오톡봇이 들어오는 채팅 내용을 파싱하면서 명령어에 해당하는 부분이 있으면 해당 로직을 탈 수 있도록 하는 코드가 필요합니다.
첫 문자가 "/" 슬러시로 시작하면 명령어로 인식하도록 msg.startsWith("/") 코드를 사용합니다.
그리고 이후 명령어 + 파라미터 구조 확인을 위해 slice() 함수를 이용해 첫 문자를 잘라내고 split() 함수를 이용해 공백으로 구분된 두 단어를 분리해서 cmdArr 배열에 넣어줍니다.
_cmdArr 은 전역으로 선언된 명령어 리스트를 정의해 두었는데 이 리스트 안에 존재하는 명령어와 일치하는게 있을때만 동작하도록 해두었습니다.
if (msg.startsWith("/")) {
let cmd = msg.slice(1);
var cmdArr = cmd.split(' ');
if (_cmdArr.includes(cmdArr[0])) {
let param = cmdArr[0];
if (param == '날씨') {
let area = msg.substr(cmdArr[0].length + 1).trim();
if (isNaN(area)) {
repMsg = getWeatherFromNaver(area);
replier.reply(repMsg);
}
}
}
}
날씨 데이터를 파싱하는 부분은 getWeatherFromNaver 직관적인 함수명을 사용해 작성했습니다.
Jsoup라이브러리로 connect() 와 get() 을 통해 검색 결과 html을 받아옵니다.
select() 함수를 이용해서 검색을 할 수 있는데 여기서는 클래스로 접근해서 데이타를 다 받아오도록 했습니다.
select('.클래스명') 으로 데이타에 접근이 가능하며 중복되는 클래스명이 있으면 리스트로 결과가 나오게 되므로 select()[인덱스] 로 접근이 가능합니다.
// 네이버 날씨 파싱 함수
// url 샘플 : https://m.search.naver.com/search.naver?&query=날씨+서울
function getWeatherFromNaver(msg){
var data = Jsoup.connect("https://m.search.naver.com/search.naver?&query=날씨+" + msg).get();
let retMsg = '';
data = data.select(".weather_info")[0];
let _today = data.select("._today");
// 현재 온도
try{
let cur_temp = _today.select(".temperature_text strong").text().slice(5);
// 어제와 온도차이
let diff_temp = data.select(".temperature_info .temperature").text();
let diff_stat = data.select(".temperature_info .blind").text();
// 체감
let v1 = _today.select(".summary_list .sort .desc")[0].text();
// 습도
let v2 = _today.select(".summary_list .sort .desc")[1].text();
// 풍속
let v3 = _today.select(".summary_list .sort .desc")[2].text();
retMsg += "현재 " + msg + "의 온도는 " + cur_temp + '이며 어제보다 ' + diff_temp;
retMsg += "\n\n현재온도 : " + cur_temp;
retMsg += "\n체감온도 : " + v1;
retMsg += "\n습도 : " + v2;
retMsg += "\n풍속 : " + v3;
}catch(e){
retMsg = e;
Log.e(e);
}
return retMsg;
}
최종적으로 코드를 저장하고 컴파일 한 뒤에 카톡챗방에서 테스트를 해봅니다.
/날씨 서울 의 질문에 정제된 텍스트로 응답하는 걸 보실수 있습니다.
마무리
한시간 정도만 투자하면 네이버 검색 날씨 정보를 이용해서 챗봇 기능을 추가할 수 있었습니다. 메신저봇R에 내장된 라이노 엔진을 통해 java 라이브러리를 참조할 수 있답니 Jsoup 라이브러리를 쓸수 있어서 좋습니다. 라이노 엔진이 java 라이브러리를 어디까지 제공해주는지 분석해보면 더 많은 것을 해 볼수 있을듯 합니다.
다음에는 openai API를 이용해 chatGPT 와 대화를 할 수 있는 기능과 UDP 소켓 통신과 파이썬을 이용한 기능확장에 대해서 포스팅 해보도록 하겠습니다.
repository
전체 소스코드는 github에 올려두었습니다.
https://github.com/eunipapa/kakao_bot/blob/main/naver_weather.js
https://quantrader.tistory.com/104
https://quantrader.tistory.com/123
https://quantrader.tistory.com/128