[TIL] 심화 같이 푸는 파이썬

Yiju Kim·2022년 2월 24일
0

멋사 같이 푸는 파이썬 심화과정에서는 서버에 요청을 하여 자료를 수집하고 내가 원하는 자료로 가공하는 수업을 진행하였고, OpenAPI 프로그램도 사용해보고 SMTP 방식으로 파이썬을 이용하여 이메일을 보내는 프로그램을 만들어보았다.

1. 실시간 검색어 웹 크롤링

- 우선 웹 크롤링이 무엇인가?

웹 페이지에서 데이터를 모아주는 소프트웨어인 "crawler" 크롤러를 사용하여 데이터를 수집하는 행위를 "웹 크롤링"이라고 한다.

♦️ 웹 크롤링을 하기 위해서는 requests 모듈을 설치해야한다. 하지만 코드라이언 비디팅 수업에서는 개발 환경이 제공되어 생략하겠다.

✏️ 정적 웹페이지 vs 동적 웹페이지

웹 크롤링을 하기 전 우리가 만나게 될 페이지는 위 두가지로 분류할 수 있다.
위 두가지의 차이점에 대한 이해가 선행되어야지만 우리들의 코드가 제대로 작동할 수 있다.

1) 정적 웹페이지

정적 웹페이지란, 서버에 미리 저장된 파일이 그대로 전달되는 웹페이지이다.
특정 웹페이지의 url 주소만 주소창에 입력하면 웹 브라우저로 HTML 정보를 마음대로 가져다 쓸 수 있다.

동적 웹페이지와의 가장 큰 차이점은 "url 주소 외에는 아무것도 필요없다"는 것이다.
만약 마우스 휠을 스크롤 다운 했는데, url 변화가 없고 페이지에 내용이 추가 된다면 동적 웹페이지 이다.

예시
1. 네이버에 "엄준식" 검색한다.
2.검색창 url 복사한후 새로운 웹 브라우저 창에 붙여넣는다.
3. 처음 검색 결과와 동일한 페이지 볼 수 있다.

2) 동적 웹페이지

동적 웹페이지란, url만으로는 들어갈 수 없는 웹페이지이다.
혹시 들어가더라도 url 변화가 없는데도 실시간으로 내용이 계속해서 추가되거나 수정된다면 동적 웹페이지이다. 여기서 무언가를 클릭해서 페이지가 변경되는 것은 다른 경우이다.

예시
1. 로그인을 해야만 접속 가능한 네이버 메일
2. 보고 있는 위치에 출력 결과에 url이 계속 변하는 네이버 지도
3. 스크롤 다운을 하면 새로운 사진, 영상이 나오는 인스타그램이나 유튜브

정적/동적 수집

정적 페이지에서 정보를 수집 하느냐, 동적 페이지를 하느냐에 따라서 사용되는 파이썬 패키지는 달라집니다. 간단히 표로 정리해보면 아래와 같습니다.

- 모듈(Module)은 무엇인가?

자주 사용하는 함수들을 모아 놓은 파일을 모듈이라고 한다. 파이썬 상단에 import를 사용하여 불러와야한다.

requests 모듈 사용방법

  1. 모듈에서 get함수를 꺼낸다.
  2. "get함수야~ 요청을 나에게 보내줘" 명령하면 get 함수가 return 응답값을 뿅~ 하고 내보낸다.

- 요청의 종류

요청에는 4가지가 있다. PUT / GET / POST / DELETE 이번 시간에는 이런게 있다는 것만 알아두자.

- 서버와 클라이언트

클라이언트: 응답값에서 원하는 정보를 찾아야지~

서버: 클라이언트 요청에 대해 응답을 하는 존재

1-1. 서버에 요청을 하기

import requests

url = "http://daum.net" # 요청을 원하는 서버의 url 적어줘야한다.

requests.get(url) # 서버에 요청을 보내는 함수

print(requests.get(url))

#result
<Response [200]>

결과값이 200번대가 나온다는 의미는 "요청에 성공했어!"

잘 안됐을 경우에는 결과값이 400번대(클라요청 오류) 혹은 500번대(서버내부 오류)가 출력된다.

1-2. 응답을 출력하기

import requests

url = "http://daum.net" 

response = requests.get(url) # get함수는 return을 남긴다고 했으니 return값을 변수에 저장

print(response.text)

#result
응답값 내부의 text를 출력해주세요~

response.text 말고 . 뒤에 올 수 있는 것들이 다양하다.

print(response.url)

print(response.content)

print(response.encoding)

print(response.headers)

print(response.json)

print(response.links)

print(response.ok)

print(response.status_code)

필요할 때 마다 그때 그때 구글링 하여 사용하자.

1-3. Beautiful Soup

"저렇게 많은 응답중에서 내가 원하는 데이터만 어떻게 찾지?"

from bs4 import BeautifulSoup # 함수나 모듈에는 공백이 올 수 없습니다 !

Beautiful Soup는 모듈안의 하나의 기능이다.
Beautiful Soup의 기능은 자료 덩어리를 칸막이가 있는 통안에 넣어 정리해준다.
우리는 그 칸막이를 그 때 그 때 필요할 때마다 꺼내서 쓰면 된다.

즉, Beautiful Soup를 이용하여 야생의 데이터를 의미있는 데이터로 변환시킬 수 있다.

- BeautifulSoup( 데이터, 파싱방법 ) 함수

파싱방법: 데이터를 의미있는 데이터로 분류하는 것, 이를 도와주는 것이 바로 parser 이다.
위에서는 파이썬에 기본으로 내장된 html.parser를 사용하였다.

import requests
from bs4 import BeautifulSoup

url = "http://daum.net" 

response = requests.get(url) 

soup = BeautifulSoup(response.text,'html.parser') # BeautifulSoup함수의 return 값을 변수에 저장

- BeautifulSoup는 무슨 type일까?

print(type(response.text)) # str

print(type(BeautifulSoup(response.text, ‘html.parser’))) # bs.BeautifulSoup

- BeautifulSoup을 사용하여 원하는 데이터 출력

print(soup.title) # <title>Drum</title>
print(soup.span) # 가장 위에 있는 span 태그만 출력
print(soup.findAll(’span’)) # 모든 span 태그 출력

# . 뒤에 뭐가 올 수 있는지는 구글링 하여 필요할 때마다 찾아서 쓰자

우리는 실시간 검색어들만 출력하고 싶으니 실시간 검색어들간에 어떤 공통점이 있는지 확인해야한다.
데이터를 확인해보면 실시간 검색어들은 a태그 안에 들어있고 class="link_favorsch" 라는 값을 가지고 있다.

import requests
from bs4 import BeautifulSoup

url = "http://daum.net" 

response = requests.get(url) 

soup = BeautifulSoup(response.text,'html.parser')

print(soup.findAll(“a”, “link_favorsch”)) # 모든 a 태그 안에 “link_favorsch” 포함한 것 다 출력해주세요

#result
리스트 자료형이 출력될 것이다.

여기서 클래스명이 아닌 a태그들을 찾아달라고 하면 실시간 검색어 외에 사용된 a태그들도 모조리 찾아내니 주의하자.

import requests
from bs4 import BeautifulSoup

url = "http://daum.net" 

response = requests.get(url) 

soup = BeautifulSoup(response.text,'html.parser')

results = soup.findAll(“a”, “link_favorsch”) # return 값을 변수에 저장

변수 results는 리스트 자료형이니 이 안에서 실검(text)만 하나씩 출력해보자.

import requests
from bs4 import BeautifulSoup
from datetime import datetime # datetime함수 사용하기 위해 모듈 import

url = "http://daum.net" 
response = requests.get(url) 
soup = BeautifulSoup(response.text,'html.parser')
rank = 1

results = soup.findAll(“a”, “link_favorsch”)

print(datatime.today().strftime(%Y년 %m월 %d일의 실시간 검색어 순위 입니다.\n”) # 시간 제외하고 일까지만 나오도록 날짜 출력

for result in results:
	print(rank,"위 : ",result.get_text(),"\n") # result.get_text() 를 이용하여 리스트 속 자료에서 text만 뽑아온다.
    rank +=1

- 파일을 만들어 데이터 저장

import requests
from bs4 import BeautifulSoup
from datetime import datetime

url = "http://daum.net" 
response = requests.get(url) 
soup = BeautifulSoup(response.text,'html.parser')
rank = 1

results = soup.findAll(“a”, “link_favorsch”)

search_rank_file = open(“rankresult.txt”, “w”) # open()함수로 파일을 생성 후 변수에 저장

print(datatime.today().strftime(%Y년 %m월 %d일의 실시간 검색어 순위 입니다.\n”) # 시간 제외하고 일까지만 나오도록 날짜 출력

for result in results:
    search_rank_file.write(str(rank)+"위:"+result.get_text()+"\n") # 생성된 파일에 .write() 함수로 실검 text 저장
    print(rank,"위 : ",result.get_text(),"\n")
    rank += 1

파일을 생성하면 파이썬 파일이 들어있는 폴더에 새로운 파일이 생성된것을 확인 할 수 있다.

파일 생성 및 수정

File = open(“rankresult.txt", ”w”) # 파일을 생성
File.write(response.text) # 파일에 내용 작성
File.close() #파일 닫기

파일을 열었으면 마지막에 꼭 닫아줘야한다.

- 파일의 모드

r - read 읽기만 가능
w - write 새로운 파일로 덮어쓰기
a - append 기존 파일 보존하고 새로운 내용 덮어쓰기

- 응용하기

네이버나 가끔 사이트에서 로봇이 웹 크롤링 하는 것을 막는다.
그 때, "나는 로봇이 아니에요~" 라고 하는 문구를 추가해줘야 웹 크롤링이 가능하다.

from bs4 import BeautifulSoup
import requests
from datetime import datetime

# "로봇 아니에요~" 문구
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
url = "https://datalab.naver.com/keyword/realtimeList.naver?age=20s"
response = requests.get(url,headers=headers) # headers=headers 문구 추가
soup = BeautifulSoup(response.text, 'html.parser')
rank = 1
# span - item_title
results = soup.findAll('span','item_title')

print(response.text)

search_rank_file = open("rankresult.txt","a")

print(datetime.today().strftime("%Y년 %m월 %d일의 실시간 검색어 순위입니다.\n"))

for result in results:
    search_rank_file.write(str(rank)+"위:"+result.get_text()+"\n")
    print(rank,"위 : ",result.get_text(),"\n")
    rank += 1

✏️ beautifulsoup 한글 깨짐 현상

방법1.

from bs4 import BeautifulSoup
import requests

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
url = "http://daum.net"
response = requests.get(url,headers=headers)
soup = BeautifulSoup(response.text,'html.parser')

file = open("daum.html","w")
file.write(response.content.decode('utf-8','replace'))
file.close

print(response)
print(soup.select('a.link_favorsch'))

"daum.html" 파일에 get 요청하여 서버의 content를 받아오고 그것을 decode('utf-8','replace')를 붙여주면 한글 깨짐을 해결 할 수 있다.

방법2.
# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import requests

url = "http://daum.net"
response = requests.get(url)
soup = BeautifulSoup(response.content,'html.parser',from_encoding='cp949')
response.encoding = 'utf-8'

file = open("daum.html","w")
file.write(response.text)
file.close

print(soup)
print(soup.findAll('a','.link_favorsch'))

2. 날씨 정보 받아오기 (OpenAPI)

API Key 생성받기 레퍼런스 https://bit.ly/3y936aM

본 프로젝트를 진행하기 전에 API Key 를 받아놓아야 진행이 가능하다.

- API란?

Application
Programming
Interface
...
API란, 방명록 같은 것이다.

우리와 컴퓨터를 이어주는 도구는 마우스와 키보드가 있듯이, 클라이언트 컴퓨터와 서버 컴퓨터가 서로 데이터를 잘 이동할 수 있도록 도와주는 역할을 하는 것이 바로 API의 기능이다.

우리는 누군가가 만들어 놓은 API를 특정 규약에 맞춰 사용할 것이다.

city = "Seoul"
apikey = "#your API Key"
api = f"http://api.openweathermap.org/data/2.5/weather?q={city name}&appid={your api key}" # F-string 기능으로 {}안에 변수 대입 가능하다.

print(api) 

#result
http://api.openweathermap.org/data/2.5/weather?q=Seoul&appid=###### #My API Key

F-string을 사용하여 {}에 변수를 대입 가능하다.

- API 주소로 요청 보내기

import requests # 요청 보내기 위해 requests 모듈 불러온다

result = requests.get(api) # get함수로 api주소로 요청보내고 return값을 변수에 저장
print(result.text)

우리가 받아온 result.text를 type을 확인해보면 str인것을 확인할 수 있다.
이것을 json type으로 바꿔줘야지 데이터를 다루기 쉽다.

- JSON

Javascript object notation 자바스크립트 기반의 데이터 포맷으로, JSON은 데이터를 주고 받을 때 사용하는 포맷, 형식이다.

JSON의 구조는 이런식으로 딕셔너리와 비슷하다.

- 파이썬의 JSON 모듈로 원하는 정보 출력

import requests
import json

city = "Seoul"
apikey = "#your API Key"
api = f"http://api.openweathermap.org/data/2.5/weather?q={city name}&appid={your api key}"

result = requests.get(api) # get함수로 api주소로 요청보내고 return값을 변수에 저장
print(result.text)

data = json.loads(result.text) #json 함수를 이용하여 return받은 정보를 data 변수에 저장 / json 함수로 불러오면 알아서 json 타입으로 변환된다.

print(data["name"],"의 날씨입니다.") # json의 형식이 dictionary형이니 딕셔너리형 자료의 출력과 방법이 같다. dict[key]입력하면 value값이 나온다.
print("날씨는 ",data["weather"][0]["main"],"입니다.") # "weather"라는 key 안에 리스트 형태로 딕셔너리가 또 있는 형태
print("현재 온도는 ",data["main"]["temp"],"입니다.")
print("하지만 체감 온도는 ",data["main"]["feels_like"],"입니다.")
# 최저 기온 : main - temp_min
print("최저 기온은 ",data["main"]["temp_min"],"입니다.")

json 데이터를 보고 원하는 자료구조가 딕셔너리와 리스트로 어떻게 구성되어있는지 확인한다.

- 한글번역과 단위변환 하기

import requests
import json

city = "Seoul"
apikey = "#your API Key"
lang = “kr” # 변수 설정해서 F-string으로 대입 변수로 넣고 싶으면 API에 {} 감싸서 넣어준다

api = f”http://api.openweathermap.org/data/2.5/weather?q={city}&appid={apikey}&lang={lang}&units=metric” # units=metric API에 바로 넣어도 된다.

api 속 내용은 ?를 기준으로 뒤쪽은 파라미터이다.
파라미터는 & 기호로 구분한다.

3. 번역기 프로그램

만드는 과정

  1. 번역기 만들기
  2. 언어감지할 문장설정
  3. 언어감지
  4. 번역을 원하는 언어설정

3-1. 번역기 생성

from googletrans import Translator # 번역기 모듈 

translator = Translator() # 번역기 생성 후 변수에 저장

3-2. 언어감지 원하는 문장 설정

sentence = input("번역할 문장을 입력하세요 : ")

3-3. 언어 감지

from googletrans import Translator

detected = translator.detect(sentence) # 언어감지 해준 값을 변수에 저장

print(detected) # detected(lang=ko, confidence=1)

print(detected.lang) # ko .lang함수 사용하여 감지된 언어만 출력한다.

3-4. 번역을 원하는 언어 설정

translator.traslate() 함수에 대해 알아보자

translator.translate(text,dest,src) 

# 위 함수에서 파라미터
# text: 번역을 원하는 문장
# dest: 번역을 원하는 언어 ex) ko,en,fr ...
# src: 앞서 만든 translator가 알아서 언어를 감지해줘서 생략가능

- 결과

from googletrans import Translator

translator = Translator()

sentence = input("번역을 원하는 문장을 입력해주세요 : ")
dest = input("어떤 언어로 번역을 원하시나요?")

result = translator.translate(sentence,dest)
detected = translator.detect(sentence)

print("===========출 력 결 과===========")
print(detected.lang,":",sentence)
print(result.dest,":",result.text)
print("=================================")

#result
번역을 원하는 문장을 입력해주세요 : 안녕하세요
어떤 언어로 번역을 원하시나요?en
===========출 력 결 과===========
ko : 안녕하세요
en : Hello
=================================

4. SMTP로 구글 메일 보내기

IMAP 사용

https://bit.ly/3drYoeC

보안 수준 변경

https://bit.ly/3dr0Ced

프로젝트를 시작하기전 사전 준비를 하고 시작하자.

- SMTP 작동원리

그림을 보면서 이해하면 편하다.
우리(email client)는 메일을 B라는 사람에게 보낼 때, 우리의 메일은 우리의 이메일 서버로 전송된다. 이 때, 사용되는 것이 SMTP이다.

우리 A이메일 서버(a@gmail.com)에서 메일을 받았다.
이것을 B이메일 서버(b@gmail.com)과 주고 받을 때도 SMTP를 사용한다.

반대로 이메일 서버가 이메일 클라이언트에게 메일을 보낼 때 사용하는 것이 IMAP이다.

SMTP 서버도 사람처럼 주소를 가지고 있다.
Address: smtp.gmail.com
Port: 465

우리가 SMTP서버에 들어갈 때, 465번(포트)문을 통해 들어간다. 이 때, 465번 포트는 구글이 지정해 놓은 것이라 변경 불가능하다.

- 메일을 보내기 위한 절차

1. SMTP서버에 연결

이전에 배웠던 것과 달리 서버에 요청을 하여 응답을 받는 것이 아닌 직접 연결해서
서버로 메일을 보낸 후 서버에게 "원하는 곳에 메일을 보내줘" 라고 명령을 내리는 것이다.

SMTP 서버에 접속하기 위해 라이브러리를 사용할 것이다.

import smtplib # smtp 라이브러리

SMTP_SERVER = “smtp.gmail.com”
SMTP_PORT = 465

smtp = Smtplib.SMTP(SMTP_SERVER,SMTP_PORT) # .SMTP()함수는 서버 연결에 대한 정보를 return 해준다.

print(smtp)


#result
Error!!

하지만 출력 시 보안때문에 접근할 수 없다는 오류가 난다.
이유는 gmail의 smtp서버는 SSL을 요구한다.

SSL이란, 아무나 우리 메일 서버에 접근할 수 없도록 막아주는 암호화 방식이다.
때문에 우리는 SSL이라는 암호화 방식을 포함하는 함수를 사용해야한다.

import smtplib # smtp 라이브러리

SMTP_SERVER = “smtp.gmail.com”
SMTP_PORT = 465

smtp = Smtplib.SMTP_SSL(SMTP_SERVER,SMTP_PORT) # _SSL만 붙혀주면 된다.

print(smtp)

#result
<smtplib.SMTP_SSL object at 0x7fef31269700>

자 서버에 성공적으로 접속했다.

2. SMTP 서버에 로그인

smtp 서버를 연결하는 것에 관한 모든 정보를 가진 변수이자 객체인 smtp를 사용하여 로그인한다.

import smtplib # smtp 라이브러리

SMTP_SERVER = “smtp.gmail.com”
SMTP_PORT = 465

smtp = Smtplib.SMTP_SSL(SMTP_SERVER,SMTP_PORT)

smtp.login("yourmail@gmail.com", "yourpassword") # 파라미터로 gmail 아이디와 비밀번호를 넣어준다.

❗️ 오류 Tip

# SMTPAuthenticationError

해당 오류가 뜬다면 https://greensul.tistory.com/31 링크를 접속해 앱비밀번호를 생성한 후 앱비밀번호를 넣어보자.

3. SMTP 서버에 메일 보내기

smtp.send_message() 함수로 메일을 보내기 위해서는 메일의 내용이 필요하다.

파라미터로 보내고 싶은 이메일을 넣어준다. 하지만 smtp는 MIME 형식만 읽을 수 있으니 MIME 형식으로 변환이 필요하다.

smtp.quit() # 종료

- MIME란, 전자 우편을 위한 인터넷 표준 포맷이다.

3-1. 이메일 생성

email.message 모듈 속 EmailMessage 기능 사용한다.

from email.message import EmailMessage

message = EmailMessage() # 함수가 이메일 담을 통을 만들고 그것을 변수에 저장

3-2. 이메일 내용을 담는다.

message.set_content("codelion 수업중~!")

set_content() 함수로 본문의 내용을 담는다.

3-3. 제목, 발신자, 수신자 만들기

header를 이용하여 추가한다.

message[“Subject”] = “이것은 제목입니다”
message[“From”] = “발신자 메일주소”
message[“To”] = “수신자 메일주소”

Subject,From,To는 MIME형식 이메일 만들 때, header부분에 들어가기 때문에 []로 작성해줘야한다.

4. 메일에 사진 첨부

메일에 사진을 첨부하기 위해서는 모드를 사용한다. 앞서 배운 파일 생성 모드와 비슷하다.

rb - read binary
wb - write binary
ab - append binary

binary란, 이미지의 정보를 컴퓨터가 읽을 수 있는 정보로 바꿔 놓은 것이다. ex) png, jpg ...

image = open(“codelion.png”, “rb”)
print(image.read())

파일 생성과 마찬가지로 open()함수를 사용한다. open()을 했으면 꼭 close()로 닫아줘야 하지만, 새로운 기능을 사용해보자.

with open(“codelion.png”,”rb”) as image:
	image_file = image.read()

with ~ as 기능을 사용하면 close() 안해도 된다.

- MIME의 type

MIME에는 여러가지 type이 있다. 일반적인 텍스트만 들어간 타입과 텍스트가 아닌 다른 포맷도 함께 들어가 있는 타입(mixed type)

메일 본문에 텍스트와 이미지가 함께 들어가니깐 mixed type으로 변환해야지만 메일을 보낼 수 있다.

add_attachment() 기능을 사용하면 자동으로 mixed type으로 변환해준다.

add_attachment() 사용도구 
1. image
2. maintype (image, video…)
3. subtype (확장자png,mp4…)

message.add_attachment(image_file,maintype = “image”, subtype = “png”)

❗️ 이미지 확장자 바뀌면 그 때마다 바꿔주기 귀찮으니 새로운 기능 추가

import imghdr # 확장자를 판단해주는 모듈

image_type = imghdr.what(“codelion”, image_file) # 확장자를 파악해서 자동으로 변환해서 넣어주는 기능

파라미터로 파일명과 실제 파일 데이터가 필요하다.

이메일 유효성 검사

유효성 검사란, 우리가 보내는 이메일 주소가 진짜 이메일 주소가 맞는지 확인해주는 것을 유효성 검사라고 한다.
이 때, 정규 표현식을 사용하여 확인한다.

정규표현식(Regular Expression)이란, 이메일에만 나타나는 특정한 조건을 주고 이메일이 이 조건에 부합하는지 판단한다.


그림을 보고 이해하면 조금 쉬울 것이다.

^ : 정규표현식 시작
$ : 정규표현식 끝
[] : 대괄호 안에있는 문자를 포함한다 라는 뜻

[A-zA-Z0-9.+_-] +
a부터z까지, A부터 Z까지, 0부터9까지, ., +, _, - 
+ : 위에것들이 1회 이상 반복된다.

\. :일반 .을 표현하기 위한 방법

정규 표현식을 사용하기 위해서는 파이썬 모듈을 불러와야한다.

import re

reg =^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$”

re.match(reg,”codelion.example@gmail.com”) # match()함수의 파라미터로는 정규표현식,비교하려는 식이 들어간다.

print(re.match(reg,”codelion.example@gmail.com”)) # 만약 적합하지 않으면 결과값이 none이 출력된다.

- 최종 결과 및 유효성 검사 완성하기

import smtplib
from email.message import EmailMessage
import imghdr
import re

SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 465

def sendEmail(addr):
    reg = "^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$"
    if bool(re.match(reg,addr)):
        smtp.send_message(message)
        print("정상적으로 메일이 발송되었습니다.")
    else:
        print("유효한 이메일 주소가 아닙니다.")

message = EmailMessage()
message.set_content("코드라이언 수업중입니다.")

message["Subject"] = "이것은 제목입니다."
message["From"] = "###@gmail.com"
message["To"] = "###@gmail.com"

with open("codelion.png","rb") as image:
    image_file = image.read()

image_type = imghdr.what('codelion',image_file)
message.add_attachment(image_file,maintype='image',subtype=image_type)

smtp = smtplib.SMTP_SSL(SMTP_SERVER,SMTP_PORT)
smtp.login("###@gmail.com","password")
sendEmail("###gmailcom")
smtp.quit()

중간에 정규식 유효성 검사를 함수로 정의내렸다.

def sendEmail(addr):
	Reg =^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$”
	if bool(re.match(reg,addr)): # bool() 함수는 ()안에 존재한다면 True, none이나 존재하지 않는다면 false로 처리한다.
		smtp.send_message(message)
		print(“정상적으로 메일이 발송되었습니다.)
	else:
		print(“유효한 이메일 주소가 아닙니다.)

🔔 오늘의 소감

4일차다. 확실히 심화 과정이라 그런지 잠깐이라도 딴 생각을 하면 되돌아보기를 수없이 반복했던 하루 같았다. 그래도 포기하지 않고 강의 내용을 최대한 이해하려고 노력하였고 TIL 정리 블로그를 보면서 틈틈히 복습을 해야겠다. 이제 남은 하루도 열심히 하고 오프라인에서 빛을 발하고 싶다.

profile
제로베이스 스쿨 커넥to 프론트엔드 1기

0개의 댓글