[리원아빠] 파이썬으로 새로운 게시글 등록시 카카오톡 메시지 보내기

2022. 3. 4. 10:43Python

반응형

새로운 게시글 카카오톡 메시지 보내기



 

이 포스팅에 대한 이해도를 높이기 위해서 아래의 포스팅을 먼저 보고 오는것을 추천한다.

 

2022.03.02 - [IT/Python] - [리원아빠] 파이썬으로 카카오톡 메시지 나에게 보내기

 

[리원아빠] 파이썬으로 카카오톡 메시지 나에게 보내기

카카오톡 메시지 나에게 보내기 파이썬을 통해 키워드 챗봇을 만들었다. 텔레그램이 아닌 카카오톡으로 만들다보니 카카오 인증이 필요했다. 인증은 json으로 처리했는데 처음해봐서 구글링이

liwonfather.tistory.com

2022.03.03 - [IT/Python] - [리원아빠] 카카오톡 자동 토근 발행 후 나에게 메시지 보내기

 

[리원아빠] 카카오톡 자동 토근 발행 후 나에게 메시지 보내기

카카오톡 자동 토근 발해 및 메시지 보내기 이전 포스팅에 카카오톡을 통해 자신에게 메시지를 보내는 방법에 대해 알아봤다. 2022.03.02 - [IT/Python] - [리원아빠] 파이썬으로 카카오톡 메시지 나에

liwonfather.tistory.com

 

위 포스팅을 작성하는 과정에서 본격적으로 내가 만들고자 했던 프로그램을 코딩을 시작했었다.

자주 가는 사이트의 핫딜 정보를 카카오톡으로 자동 보내주는 프로그램이였는데

만족할만한 결과를 보여주고 있어 포스팅을 한다.

 

대상 사이트는 FM Korea이라는 사이트로 축구게임인 Football Manger를 하면서 알게 되었는데

요즘엔 축구게임 정보보단 핫딜 정보때문에 더 자주 방문하고 있다.

 

코드는 모듈화를 위해 카카오톡 인증을 진행하는 파일과 

대상 사이트에서 핫딜 정보를 추출하는 파일로 나누었다.

 

먼저 카카오톡 인증을 진행하는 코드를 살펴보자.

import time
import requests
import json

# code url  https://kauth.kakao.com/oauth/authorize?client_id=자신의 rest api key 값&redirect_uri=https://example.com/oauth&response_type=code
url = 'https://kauth.kakao.com/oauth/token'  # 카톡 인증 url
rest_api_key = '자신의 rest api key 값'  # 카톡 rest 키
redirect_uri = 'https://example.com/oauth'  # 카톡 인증용 redirect url
authorize_code = 'code url을 통해 얻은 code 값'  # 카톡 인증용 코드 수행시마다 재발급 필요


# 최초 token들 발급하여 refresh token 저장
def f_get_refresh_token():
    data = {
        'grant_type': 'authorization_code',
        'client_id': rest_api_key,
        'redirect_uri': redirect_uri,
        'code': authorize_code,
    }

    response = requests.post(url, data=data)
    tokens = response.json()

    with open('refresh_token.json', 'w') as fd:
        json.dump(tokens, fd)


# refresh token을 이용하여 새로운 access token 발급
def f_reissue_token():
    with open('refresh_token.json', 'r') as fd:
        token = json.load(fd)
    refresh_token = token['refresh_token']
    data = {
        'grant_type': 'refresh_token',
        'client_id': rest_api_key,
        'refresh_token': refresh_token
    }
    response = requests.post(url, data=data)
    tokens = response.json()

    with open('access_token.json', 'w') as fd:
        json.dump(tokens, fd)
    with open('access_token.json', 'r') as fd:
        ts = json.load(fd)
    access_token = ts['access_token']
    return access_token


# 메시지 전송
def f_send_msg(access_token, msg):
    header = {'Authorization': 'Bearer ' + access_token}
    url = 'https://kapi.kakao.com/v2/api/talk/memo/default/send'  # 나에게 보내기 주소
    post = {
        'object_type': 'text',
        'text': msg,
        'link': {
            'web_url': 'https://developers.kakao.com',
            'mobile_web_url': 'https://developers.kakao.com'
        },
        'button_title': '키워드'
    }
    data = {'template_object': json.dumps(post)}
    return requests.post(url, headers=header, data=data)

필자가 작성한 코드를 그대로 사용한다고 하면 수정이 필요한 부분은 두가지다.

아래 두가지에 대한 이해도가 부족하다면 이전에 포스팅한 글을 참조하길 바란다.

  • rest api key
  • code 값

두번째로 실제 대상 사이트에서 핫딜 정보를 가져오는 코드를 살펴보자.

import requests
import json
import time
import copy
import re
from bs4 import BeautifulSoup
from datetime import datetime

import kakao


site_url = 'https://m.fmkorea.com/hotdeal'
board_list = []  # 크롤링 결과 저장 리스트
p_board_list = []  # 이전 크롤링 결과 저장 리스트


def f_get_list():
    result_search = requests.get(site_url)
    html = result_search.text
    soup = BeautifulSoup(html, 'html.parser')
    times = soup.select('.regdate') #글 작성시간 크롤링
    titles = soup.find_all('a', re.compile('hotdeal_var8*'))    #딜 종료 게시글까지 가져오기 위해 정규식을 사용함, select 함수는 정규식 미지원 (딜 진행중 게시글은 hotdeal_var8, 딜 종료 게시글은 hotdeal_var8Y 클래스)
    #titles = soup.select('h3.title > a')    #핫딜과 핫딜종료 게시글의 제목을 가지고 있는 클래스명이 상이하여 부모노드를 명시하여 크롤링을 함
    prices = soup.select('.hotdeal_info > span:nth-child(2) > a.strong') #가격 크롤링

    for idx in range(0, len(titles), 1):
        t = titles[idx].text.replace('\t', '') #제목 앞에 탭 제거
        loc = t.rfind('[') #댓글 수가 제목에 포함되어 댓글 수는 날려버리기 위해서 '[' 문자의 위치 값 찾음
        board_list.append('제목: ' +t[0:loc] +'\n작성시간: '+times[idx].text.replace('\t','') +'\n가격: ' +prices[idx].text +'\n링크: ' +site_url +titles[idx]['href'])


#kakao.f_get_refresh_token() #최초 refresh token 추출시에만 수행

while True:
    f_get_list()  #게시글 크롤링
    access_token = kakao.f_reissue_token()  # 새로운 액세스 토큰을 발급 받음
    sms_list = list(set(board_list) - set(p_board_list))  # 이전 리스트와 비교하여 다른 값만 문자 보낼 리스트로 저장
    p_board_list = copy.deepcopy(board_list)  # 현재 게시글을 이전 게시글로 저장

    kakao.f_send_msg(access_token, 'FM 결과\n'  +'현재 시간 {} 최신글은 총 {}개입니다.'.format(datetime.now().strftime('%H:%M:%S'),len(sms_list)))

    for i in range(0, len(sms_list), 1):
        kakao.f_send_msg(access_token, sms_list[i])

    board_list.clear()
    sms_list.clear()
    time.sleep(1800)  # 반복 주기

위 코드는 핫딜 게시판을 방문하여 게시글들을 크롤링하고 다음 정보를 가져온다.

  • 게시글 제목
  • 게시글 작성시간
  • 상품 가격

이렇게 가져온 정보는 리스트로 저장하여 가지고 있다가 다시 크롤링한 결과와

비교하여 차이가 나는 게시글에 대해서만 카카오톡으로 전송한다.

따라서 최초 수행시에는 비교대상이 없으므로 크롤링한 대상 모두 카카오톡으로 전송된다.

 

추가적으로 제목을 크롤링하는 방식을 두가지로 모두 코드에 반영했는데

하나는 fild_all 함수를 사용하여 정규식으로 제목의 클래스명을 찾는 방식이고

또 다른 하나는 select 함수에 부모노드와 자식노드의 경로를 입력하여 제목을 찾는 방식이다.

기호에 따라 원하는 방식을 선택하여 사용하면 된다.

 

반복주기를 변경하고 싶다면 코드의 마지막 부분인 time.sleep(1800) 부분을 변경하면 된다.

전달되는 값을 단위는 초이므로 코드상 명시된 1800은 분으로 변경하면 30분이다.

 

그럼 끝.

반응형