카카오톡 봇만들기

컴공과 재학중 방학 때 할 미니 프로젝트로 학교에 학식은 있는데 인기가 없고 이를 홍보할 수 있는 도구가 없어 친구들과 미니 프로젝트로 기획하였다.

1. 개발환경

  • 서버를 구축하기 위해서 pythonflask 를 사용해 구축한다,
  • 크롤링을 위해서 bs4 , selenium 을 사용할 것이다.
  • 서버로는 azure 를 사용할 것이다.

2. 카카오톡 비지니스 가입

  • 카카오톡 봇을 만들기 위해서는 우선 카카오톡 비지니스에서 카카오톡 봇을 만들고 카카오톡 오픈빌더 OBT 에 신청을 해야한다.

카카오톡 비지니스 / 카카오톡 오픈빌더

  • 카카오톡 로그인 후 새 채널 만들기로 새로운 채널을 생성한다.

  • 새로운 채널을 생성했으면 비지니스도구 → 챗봇으로 들어가서 오픈빌더 신청을 하면된다. 보통 기간은 2~3일 정도 승인까지 소요된다. 반려되는 경우가 많으니 자세하게 작성하는 것을 추천한다. 👍

3. Azure 서버 만들기

  • 필자는 학생이기 때문에 Azure 학생인증을 하여 무료 크레딧 100$를 사용하여 서버를 구축하였다. Azure은 카드등록을 미리 하지 않아서 과금걱정이 없어 사용하였다.
  • 프리티어로 구축하는 방법은 링크로 들어가서 체험 계정을 우선 만든다.
  • 체험 계정을 만들었으면 본격적으로 가상머신을 생성 해보도록 하자

  • 계정을 만들었으면 포털로 들어간다.

  • 리소스 만들기를 눌러 리소스를 생성한다.

  • 서버는 당연히 Ubuntu Server 20.04 LTS 를 사용한다.

  • 가상머신 이름은 프로젝트 이름으로 설정하자.
  • 지역은 한국 남부로 설정하였다.
  • 크기는 Standard_B1s로 설정하였다. 무료크레딧이 100$이므로 월 만원씩이면 얼추 1년 비스무리하게 사용할 수 있다.
  • 인증형식은 나중에 바꿀 수 있으므로 SSH 공개 키 혹은 암호로 설정하면 된다.

  • 디스크 크기는 새 디스크 만들기로 들어가 p6 성능 계층인 64GB 하나와 프리미엄 ssd를 선택하였다.
  • 나머지는 딱히 건들이지 않고 생성하면된다.

  • ssh에 접속하기 위해서 암호를 까먹었다면 암호 다시설정에서 암호 재설정으로 ssh에 들어갈 암호를 설정한다.
  • ssh 공개 키로 만들었다면 ssh 공개키를 사용하는 법은 많이 있기 때문에 검색하여 ssh로 접속을 하도록한다.

4. 가상머신 서버 접속

  • 가상머신 접속을 하기 위해서는 접속을 하기 위한 프로그램이 필요한데 putty 를 보통 사용한다.
  • 코드를 자주 편집하거나 할 때는 Visual Studio Code를 사용해서 Remote ssh 라는 확장 익스텐션을 설치하거나 또는, python으로 작업하기 때문에 Pycharm을 사용하여 ssh접속을 진행한다.
  • 필자는 일단 putty 로 진행하도록 하겠다 Putty 다운로드 링크
  • putty를 실행하고 가상머신의 아이피를 입력하여 접속하도록 한다.

  • 접속이 안된다면 Azure에서 네트워킹으로 가서 공용인바운더리 규칙을 추가하도록 한다.

  • 대상 포트 범위만 22 로 변경한 뒤 다시 접속하도록 한다.

  • 이름과 비빌번호를 Putty에서 입력해서 이런 창이 뜨면 성공이다.

'Python > Flask' 카테고리의 다른 글

[Python/Flask] 카카오톡 봇 만들기(3)  (0) 2021.07.08
[Python/Flask] 카카오톡 봇 만들기 (2)  (0) 2021.06.30

[Pair]

1. Pair 클래스

#include <utility>

utility 헤더를 사용
두개의 변수를 묶을 때 사용


2. 기본 형

//pair을 선언할때
pair<int,int> p;

//vector에 선언할 때
vector<pair<int,int>> vec;

3. 기본문법

//pair에 값을 집어넣을 때
pair<int,int> p = make_pair(1,2);

//vector pair에 값을 집어 넣을 때;
vec.push_back(make_pair(1,2));

값을 집어 넣을 때는 make_pair(a,b) 형태를 사용

//pair맴버 변수에 접근
#include <utiiity>
pair<int,int> p;

// 첫번 째 맴버변수에 접근
int valA = p.first;
// 두번 째 맴버변수에 접근
int valB = p.second;

첫 번쨰 맴버변수에 접근할때는 p.fisrt 를 사용
두 번째 맴버변수에 접근할때는 p.second 를 사용

//vector에서 정렬할떄의 예시
#include<utility>
#include<algorithm>

bool cmp (const pair<int,int>& a, const pair<int,int>& b){
    if(a.first == b.first){
        return a.second < b.second;
    }
    return a.first < b.first;
}

int main(){
vector<pair<int,int>> vec;

sort(vec.begin(),vec.end(),cmp);

}

문제

최대공약수와 최소공배수

[유클리드의 호제법]

#include <string>
#include <vector>

using namespace std;

vector<int> solution(int n, int m) {
    vector<int> answer;
    int c;
    int a = n;
    int b = m;
    while(b){
        c = a % b;
        a = b;
        b = c;
    }
    answer.push_back(a);
    answer.push_back(n*m/a);
    return answer;
}

해설

유클리드의 호제법

2개의 자연수(또는 정식) a, b에 대해서 ab로 나눈 나머지r이라 하면(단, a>b), ab최대공약수br최대공약수와 같다.
최대공약수최소공배수를 구할 수 있는 알고리즘 이다.

int a , b;
int c;

while(b){
        c = a % b;
        a = b;
        b = c;
}

return a;
  1. 입력으로 두 수 a,b(a>b)가 들어온다.
  2. a0이 아니라면, b를 출력하고 알고리즘을 종료한다.
  3. ba으로 나누어 떨어지면, a를 출력하고 알고리즘을 종료한다.
  4. 그렇지 않으면 ba로 나눈 나머지를 새롭게 a에 대입하고, ba를 바꾸고 3번으로 돌아온다.

최소공배수 = a * b / 최대공약수이다.

문제

[1차] 비밀지도

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

string convert(int a, int n) {
    string str;
    for (int i = 0; i < n; i++) {
        if (a % 2 == 0){
            str += ' ';   
        }
        else{
            str += '#';   
        }
        a /= 2;
    }
    reverse(str.begin(), str.end());
    return str;
}

string add(string str1, string str2) {
    string str;
    for (int i = 0; i < str1.size();i++)
    {
        if (str1[i] == ' ' && str2[i] == ' '){
            str += ' ';   
        }
        else {
            str += '#';
        }
    }
    return str;
}
vector<string> solution(int n, vector<int> arr1, vector<int> arr2) {
    vector<string> answer;
    for (int i = 0; i < n; i++) {
        answer.push_back(add(convert(arr1[i], n), convert(arr2[i], n)));
    }
    return answer;
}

해설

1. Convert 함수

  • 2진수 변환
    arr[i]의 값을 계속 2로 나누어서 나머지가 1일 때는 #을 저장 " "을 저장하고 <algorithm>헤더에 있는 convert로 거꾸로 출력해준다.

    2. Add 함수

  • arr1arr2를 2진수로 변환 한 값들 더해준다. 둘다 " "이면 " "을 입력해주고 둘 중 하나라도 #라면 #을 입력해준다.

[1차 다트게임]

#include <string>
#include <vector>

using namespace std;

int solution(string dartResult) {
    int answer = 0;
    int count = -1;
    vector<int> vec;
    for(int i = 0 ; i < dartResult.length() ; i++){

        if(dartResult[i] == 'S'){
            vec[count] = vec[count];        
        }
        else if(dartResult[i] == 'D'){
            vec[count] = vec[count] * vec[count];  
        }
        else if(dartResult[i] == 'T'){
           vec[count] = vec[count] * vec[count] * vec[count];  
        }

        if(dartResult[i] == '*'){
            if(count == 0){
                vec[count] = vec[count] *2;
            }
            else{
                vec[count-1] *= 2;
                vec[count] *= 2;
            }
        }
        else if(dartResult[i] == '#'){
            vec[count] *= -1;
        }

        if(dartResult[i] == '1'){
            if(dartResult[i+1] == '0'){
                vec.push_back(10);
                i += 1;
            }
            else{
                vec.push_back(1);
            }
            count++;
        }
        else if(dartResult[i] > 46 && dartResult[i] < 58){
            vec.push_back(dartResult[i] - 48);
            count++;
        }

    }

    for(int i = 0 ; i < vec.size(); i++){
        answer += vec[i];
    }
    return answer;
}

해설

점수계산을 하나의 백터(vec)에 담아서 계산을 하였다.

String 형에서 10을 판별할때는 맨처음이 숫자 1이면 그 다음 값이 0인지 다른것지 확인하고 if-else 문을 돌려서 확인했다.

또한 String 값에서 0을 int형으로 변환시키면 48 이었기 때문에 나머지 값들은 모두 String 값에서 48을 뺴주었다.

마지막으로 *인 아차상의 경우 count라는 변수를 활용하여 지금까지 숫자가 몇번 나온지를 확인하여 한번 나왔을 경우에는 그 점수에만 2배를 시키도록 예외처리를 하였다.

[실패율]

#include <string>
#include <vector>
#include <algorithm>
#include <utility>

using namespace std;

bool cmp(const pair<float,int>& a , const pair<float, int>& b){
    if(a.first == b.first)
        return a.second < b.second;
    return a.first > b.first;
}

vector<int> solution(int N, vector<int> stages) {
    vector<int> answer;
    int number = stages.size();
    pair<float, int> p;
    vector<pair<float,int>> vec;
    int index;
    float failure;
    int cnt;
    for (int i = 0; i < N; i++) {
        index = i + 1;
        cnt = count(stages.begin(), stages.end(), i + 1);
        if(cnt == 0)
            failure = 0;
        else{
             failure = cnt / (float)number;
            number -= cnt;
        }
        vec.push_back(make_pair(failure,index));
    }

    sort(vec.begin(), vec.end(), cmp);

    for (int i = 0; i < vec.size(); i++) {
         answer.push_back(vec[i].second);
    }

    return answer;
}

해설

Pair 로 실패율과 index번호를 결합한 vector를 생성하였다.

Algorithm 에 있는 Count 를 사용하여 벡터안에 같은 숫자가 몇개있는지 1stage 부터 판별하였다.

또한 count가 0일때는 stage에 도달한 사람이 없다는 것 이므로 그 때는 실패율을 0으로 예외처리해주었다.

Algorithm 에 있는 Sort 를 사용하고 cmp라는 bool형의 함수를 만들어 만약 실패율이 같을 경우는 스테이지가 낮은쪽이 먼저 정렬되도록 만들었다.

문제

예산

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int solution(vector<int> d, int budget) {
    int max = 0;
    int sum = 0;
    sort(d.begin(), d.end());
    for(int i = 0 ; i < d.size(); i++){
        sum += d[i];
        if(sum <= budget)
            max++;
    }

    return max;
}

해설

첫 번째로 백터들을 Sort 로 정렬시킨 후 하나씩 더해서 합이 budget 의 숫자보다 작거나 같으면 max 변수를 1씩 더해준다

문제의 해석이 중요한 문제이다.

물품을 구매해 줄 때는 각 부서가 신청한 금액만큼을 모두 지원해 줘야 합니다.

라는 말이 예를들어 예산이 9원이면 9원을 남김없이 써야하는것 같지만 그렇지 않다.

예를들어 {1,2,3,4,5} 라는 부서에 예산이 9원이면 1원 2원 3원을 주어서 총 6원을 주어도 상관없다.

하지만 {1,2,3,3,5} 인 부서인 경우에는
1원 2원 3원만 줄 수 없다.

왜냐하면 1원 2원 3원에서 나머지 3원을 더 주면 총 9원 이기 떄문이다.

2016년

#include <string>
#include <vector>

using namespace std;

string solution(int a, int b) {
    string answer;
    int sum = 0;
    for(int i = 1 ; i < a ; i++){
        if(i == 2){
        sum += 29;
    } 
    else if(i == 1 || i==3 || i==5 || i==7 || i== 8 || i == 10 || i==12){
        sum += 31;
    }
    else{
        sum+= 30;
    }
    }
    sum += b;
    switch(sum % 7)
    {
        case 1: answer = "FRI";
            break;
        case 2: answer = "SAT";
            break;
        case 3: answer = "SUN";
            break;
        case 4: answer = "MON";
            break;
        case 5: answer = "TUE";
            break;
        case 6: answer = "WED";
            break;
        case 0: answer = "THU";
            break;
    }

    return answer;
}

해설

1. 윤년이란

  • 연수가 4로 나누어 떨어지는 해
  • 연수가 100으로 나누어 떨어지는 해
  • 연수가 400으로 나누어 떨어지는 해

2016년은 윤년이므로 1년이 총 366 일이다.

2. 해설

일수의 총 합을 구한뒤 % 7로 나머지를 구하여 날짜를 출력한다.

+ Recent posts