Programming Language/Python

역세권 청년주택 자동 이메일 알람 설정

깜태 2021. 1. 10. 16:48
728x90

Python을 이용하여 역세권 청년주택 공고가 올라왔을 때 자동으로 이메일을 보내주는 코드를 작성해보았습니다.

 

필요한 설정은 다음과 같습니다.

 

1. 코드를 주기적으로 실행하기 위한 Crontab 설치는 다음의 링크를 참고하였습니다. (decdream08.tistory.com/67

 

2. Python에서 이메일을 보내기 위한 설정은 다음의 링크를 참고하였습니다. (yeolco.tistory.com/93

 

코드는 아래와 같습니다.

 

import requests
from bs4 import BeautifulSoup as bs
import datetime
import smtplib
from email.mime.text import MIMEText

url = 'https://housing.seoul.go.kr/site/main/sh/publicLease/10/list'
gmail_id = 'gmail 아이디 입력'
APP_password ='APP 비밀번호 입력'

# 홈페이지로부터 데이터 받아오기
response = requests.get(url)
html = bs(response.text, 'html.parser')

notice_list = html.find('tbody').find_all('tr')

today = datetime.datetime.now().strftime('%Y-%m-%d')

# 구글 이메일 설정
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login(gmail_id, APP_password)

# 게시물 확인

for idx, notice in enumerate(notice_list):
    link = 'https://housing.seoul.go.kr/' + notice.find('td', {'class': 'txl td-m'}).find('a').attrs['href']
    title = notice.find('td', {'class': 'txl td-m'}).get_text().strip()
    write_date = notice.find_all('td')[3].get_text().strip()
    write_date = datetime.date.fromisoformat(write_date)
    
    # 작성일이 같은 경우 알람을 보냄
    if write_date == today:
        msg = MIMEText(title, link)
        msg['Subject'] = "{}년 {}월 역세권 청년주택 공고 알림".format(today.year, today.month)
        s.sendmail(gmail_id, gmail_id, msg.as_string())

s.quit()

 

코드를 작성한 뒤, python 파일로 저장을 해야 합니다.

 

이후로 해야할 일은, 1번 사이트를 참고하여 crontab을 이용해 주기를 설정하면 됩니다.

 

 

제 경우는 위를 아래와 같이 작성할 수 있습니다.

 

0 9-18 * * 1-5 프로젝트_파일경로/house_mail_alarm.py

(참고 : Anaconda를 이용하시는 경우 eslife.tistory.com/1101 를 참조해주세요)

 

풀어서 설명하면 매월 매일 월~금요일마다, 9-18시, 0분일 때마다 해당 파일을 실행하게 되고,

 

코드를 따라서 알람이 유효한 경우는 메일이 오게 돼겠죠! 

 

하지만, 해당 코드로 실행하게 되면, 발표가 났다 하더라도 매시간마다 날아오게 됩니다.

 

매일 날아오지 않게 하려면 어떻게 해야할까 고민하다가, logging을 이용하려고 합니다.

 

logging 파일을 읽어와서, 오늘 이미 보낸 날짜가 있을 경우에는 더 보내지 않기 기능을 추가하여

 

구현하였습니다.

 

# 로그 파일 설정하기
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#로그 Format 설정
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

#로그 file handler 추가
file_handler = logging.FileHandler('my.log')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

# log 파일 확인 함수
def is_sent(send_email, today):
    
    # log 파일 읽기
    log_file = open('my.log', 'r').readlines()
    
    #파싱 후 같으면 True, 다르면 False
    for line in log_file:
        time, name, levelname, message = line.strip().split(' - ')
        send_email_log = message.strip().split('to: ')[1]
        log_day = datetime.date.fromisoformat(str(time.split(' ')[0].strip()))
        if today == log_day and send_email_log == send_email:
            return True
    return False

 

위의 로그 기능까지 확인하여 구현한 코드는 다음과 같습니다.

 

import requests
from bs4 import BeautifulSoup as bs
import datetime
import smtplib
from email.mime.text import MIMEText
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

url = 'https://housing.seoul.go.kr/site/main/sh/publicLease/10/list'
my_gmail_id = 'gmail 아이디 입력'
APP_password ='APP_password 입력'
response = requests.get(url)
html = bs(response.text, 'html.parser')

notice_list = html.find('tbody').find_all('tr')
today = datetime.datetime.now().strftime('%Y-%m-%d')
# today = datetime.date(2020, 10, 12)

# gmail 설정
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login(my_gmail_id, APP_password)
send_email_list = ['아이디 1, 아이디2, 아이디3']

# log 파일 설정
file_handler = logging.FileHandler('my.log')
# file_handler = RotatingFileHandler(filename='my.log', mode='a', maxBytes=file_max_bytes, backupCount=10)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

def is_sent(send_email, today):
    log_file = open('my.log', 'r').readlines()
    for log in log_file:
        time, name, levelname, message = log.strip().split(' - ')
        send_email_log = message.strip().split('to: ')[1]
        log_day = datetime.date.fromisoformat(str(time.split(' ')[0].strip()))
        if today == log_day and send_email_log == send_email:
            return True
    return False

for idx, notice in enumerate(notice_list):
    link = 'https://housing.seoul.go.kr/' + notice.find('td', {'class': 'txl td-m'}).find('a').attrs['href']
    title = notice.find('td', {'class': 'txl td-m'}).get_text().strip()
    write_date = notice.find_all('td')[3].get_text().strip()
    write_date = datetime.date.fromisoformat(write_date)

    if write_date == today:
        print("새로운 공고가 뜸!!")
        msg = MIMEText(f'{title}, {link}')
        msg['Subject'] = "{}년 {}월 역세권 청년주택 공고 알림".format(today.year, today.month)
        for send_email in send_email_list:
            if not is_sent(send_email, today):
                s.sendmail(my_gmail_id, send_email, msg.as_string())
                logger.info(f'{write_date}, {title}, from: {my_gmail_id} to: {send_email}')

s.quit()

 

읽어주셔서 감사합니다.

728x90