클라이언트가 서버에 데이터를 요청할 때 CRUD라는 4가지 타입이 있다. 이때 CRUD는 읽기(Read), 쓰기(Create), 수정(Update), 삭제(Delete)를 말한다.
게시판 사이트가 있다고 할 때를 예를 들어보자. 게시판의 모든 게시글 리스트를 가져오거나 특정 게시글에 대한 정보를 가져올 때는 Read이다. 게시글을 추가하면 Create, 게시글을 수정하면 Update, 게시글을 삭제하면 Delete라고 한다. 하지만 클라이언트와 서버는 Read, Create, Update, Delete라고 직접 명시하지 않는다. 이러한 요청을 헤더에 GET, POST, PUT, DELETE의 형태로 메소드를 정의한다.

GET 요청
POST 요청
PUT 요청
DELETE 요청
웹 크롤링은 'URL을 탐색해 반복적으로 링크를 찾고 가져오는 과정'이다. '기어 다니다' 라는 뜻의 영어 단어 크롤링(crawling)을 사용한 것에서 알 수 있듯이, 웹 크롤링은 웹 페이지를 찾아다니며 정보를 수집한다.
대표적인 웹 크롤링으로는 검색엔진의 웹 크롤러(web crawler)가 하는 일을 예로 들 수 있다. 웹 크롤러는 URL을 수집하고 웹 페이지를 복사하여, 수집한 웹 페이지에 색인(index)을 부여한다. 분류가 잘 되어있으면 그만큼 검색 속도가 올라갈 테니까.
즉, 쉽게 말해 데이터를 수집하고 분류하는 것을 크롤링(Crawling)이라고 지칭한다.
웹페이지에서 원하는 데이터를 추출하여 가공하기 쉬운 상태로 바꾸는 것이다.
웹페이지에서 떠다니는 데이터는 리스트, 딕셔너리 같은 자료구조와 달라 사용자 마음대로 접근하고 자르고 추가하는 등의 편집이 쉽지않다. 그렇기 때문에 이런 데이터들을 다루기 쉬운 형태로 바꿔주는 과정이 필요한데, 이 역할을 하는 함수나 프로그램을 파서(parser)라고 하며, 이 과정을 파싱(parsing)이라고 한다.
웹크롤링을 할 때 필연적으로 만나게 되며, python에서는 beautifulsoup 라이브러리를 사용하여 html 문서를 파싱한다.
웹 스크래핑은 '우리가 정한 특정 웹 페이지에서 데이터를 추출하는 것'이다. 우리가 특정 주제의 뉴스만을 가져오거나, 인기 검색어 정보를 가져오는 것, 어떤 상품의 가격을 모니터링하는 것 모두 웹 스크래핑이다. 그래서 웹 스크래핑을 웹 데이터 추출(web data extraction), 웹 하베스팅(web harvesting)이라고도 부른다.
즉, 스크래핑(Scraping)이란 크롤링(Crawling)한 데이터를 파싱(Parshing)하여 Web에서 필요한 데이터를 추출하는 것이라 할 수 있다.
import requests
from bs4 import BeautifulSoup
url = "http://www.daum.net/"
response = requests.get(url)
print(response.text)
Requests란 Python용 HTTP 라이브러리이다.
Python에서 특정 웹사이트에 HTTP 요청을 보내는 모듈이라고 생각하면 될 것 같다.
좀 더 쉽게 말해서 특정 웹사이트에 HTTP 요청을 보내 HTML 문서를 받아올 수 있는 라이브러리이다.
근데 정확히 말하면 얘가 가져오는 HTML 문서는 문서가 아닌 그냥 단순한 String이고,
뒤에서 배우는 BeautifulSoup에 의해 살아있는 HTML 문서로 바뀌게 된다.

BeautifulSoup이란 스크래핑을 하기위해 사용하는 패키지이고, lxml은 구문을 분석하기 위한 파서이다.
즉, BeautifulSoup은 response.text를 통해 가져온 HTML 문서를 탐색해서 원하는 부분을 뽑아내는 그런 역할을 하는 라이브러리이다.
또한, response.text로 가져온 HTML문서는 단순히 String에 지나지 않으니, lxml을 통하여 의미있는 HTML문서로 변환하는 것이다.
결론적으로, response.text로 가져온 String은 lxml이라는 모듈의 해석에 의하여 의미있는 HTML 문서로 변환되고, 이렇게 변환된 HTML문서는 BeautifulSoup에 의해서 원하는 부분을 탐색할 수 있게 된다.

참고자료
https://ponyozzang.tistory.com/626 (.starftime 함수)
https://wikidocs.net/26 (open 함수)
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 = "http://www.daum.net/"
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
rank = 1
results = soup.findAll('a','link_favorsch')
search_rank_file = open("rankresult.txt","w")
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
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)
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

API(Application Programming Interface)는 응용 프로그램에서 사용할 수 있도록 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻합니다. 주로 파일 제어, 창 제어, 화상 처리, 문자 제어 등을 위한 인터페이스를 제공합니다.

참고자료
https://ittrue.tistory.com/31 (API)
https://www.daleseo.com/python-f-strings/ (f-string)
JSON (JavaScript Object Notation)
참고자료
https://velog.io/@surim014/JSON%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80
import requests
import json
city = "Seoul"
apikey = "################################"
lang = "kr"
# units - metric
api = f"""http://api.openweathermap.org/data/2.5/\
weather?q={city}&appid={apikey}&lang={lang}&units=metric"""
result = requests.get(api)
# print(result.text)
data = json.loads(result.text)
# 지역 : name
print(data["name"],"의 날씨입니다.")
# 자세한 날씨 : weather - description
print("날씨는 ",data["weather"][0]["description"],"입니다.")
# 현재 온도 : main - temp
print("현재 온도는 ",data["main"]["temp"],"입니다.")
# 체감 온도 : main - feels_like
print("하지만 체감 온도는 ",data["main"]["feels_like"],"입니다.")
# 최저 기온 : main - temp_min
print("최저 기온은 ",data["main"]["temp_min"],"입니다.")
# 최고 기온 : main - temp_max
print("최고 기온은 ",data["main"]["temp_max"],"입니다.")
# 습도 : main - humidity
print("습도는 ",data["main"]["humidity"],"입니다.")
# 기압 : main - pressure
print("기압은 ",data["main"]["pressure"],"입니다.")
# 풍향 : wind - deg
print("풍향은 ",data["wind"]["deg"],"입니다.")
# 풍속 : wind - speed
print("풍속은 ",data["wind"]["speed"],"입니다.")
참고자료 (파라미터)
https://velog.io/@pm1100tm/python-%ED%95%A8%EC%88%98%EC%99%80-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0
from googletrans import Translator
translator = Translator()
# sentence = "안녕하세요 코드라이언입니다."
sentence = input("번역을 원하는 문장을 입력해주세요 : ")
dest = input("어떤 언어로 번역을 원하시나요?")
result = translator.translate(sentence,dest)
detected = translator.detect(sentence)
print("===========출 력 결 과===========")
print(detected.lang,":",sentence)
print(result.dest,":",result.text)
print("=================================")

1) 이메일을 만들고 보내게 되면 Gmail, Outlook 등의 Client가 SMTP를 이용해서 메시지를 Email 서버로 보내게 된다.
2) Email Server는 SMTP를 이용해서 송신자의 이메일 서버에 메일을 보내게 된다.
3) SMTP 통신을 통해서 메일을 받게 되면 수신자의 이메일 Client는 IMAP를 이용해서 메시지를 가져오고 Inbox에 메일을 가져오게 된다.
Multipurpose Internet Mail Extensions의 약자로 간단히 말하면 파일 변환을 의미한다.현재는 웹을 통해 여러 형태의 파일을 전달하는데 사용하고 있지만 이 용어가 생길 땐 이메일과 함께 동봉할 파일을 텍스트 문자로 전환해서 이메일 시스템을 통해 전달하기 위해 개발되어 Internet Mail Extensions라고 불리기 시작했다고 한다.
예전에는 텍스트 파일을 주고 받는데에 ASCII로 공통된 표준에 따르기만 하면 문제가 없었으나 네트워크를 통해 ASCII가 아닌 바이너리 파일을 보내는 경우가 생기게 되었다. 음악파일, 무비파일, 워드파일 등등 ASCII만으로는 전송이 안되기 때문에 기존 시스템에서 문제 없이 전달하기 위해서는 텍스트로의 변환이 필요했다.
텍스트 파일로 변환하는 것을 인코딩(Encoding), 텍스트 파일을 바이너리 파일로 변환하는 것을 디코딩(Decoding)이라고 한다.
MIME으로 인코딩한 파일은 Content-type정보를 앞부분에 담게되며 Content-type은 여러가지 타입이 있다.
웹 브라우저에서 서버에 접속하여 html 문서를 요청하면서 html문서에 있는 이미지 파일의 경로를 불러올 수 있다. 이러한 과정에서 이미지의 경로에 있는 파일이 웹브라우저에서 지원되는 MIME-Type이라면 웹브라우저를 이용하여 열어볼 수 있다.
바이너리파일(음악 파일, 무비 파일, 워드 파일 등) 또한 마찬가지 이다. 주로 쓰고 있는 대부분의 포맷인 .gif .jpg .mov 등등의 파일들은 웹 브라우저에서 무리없이 열리게 되는데 브라우저에서 지원하지 못하는 유형은 따로 지정해줘야 한다.
참고자료 (MIME)
https://velog.io/@aerirang647/MIME-type%EC%9D%B4%EB%9E%80
import smtplib
from email.message import EmailMessage
import imghdr
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 465
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","######")
smtp.send_message(message)
smtp.quit()
이메일을 보낼 때, 그 이메일 주소가 존재하는지 정확히 확인하기 위해서 유효성 검사가 필요

^$[a-zA-Z0-9.+_-]+ : a부터 z까지 A부터Z까지, 0부터 9까지, . , +, _ , - 이 중에서 하나 가져오라는 것a부터 z까지 A부터Z까지, 0부터 9까지, . , +, - , -\. => 점 필수라는 것![a-zA-Z]{2,3} => a부터 z까지, A부터 Z까지가 최소 2회, 최대 3번 반복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","######")
# 메일을 보내는 sendEmail 함수를 호출해서 실행해보기
sendEmail("###gmailcom")
smtp.quit()