Part 1. 파이썬 필수 문법 & 백엔드의 이해
Ch 2. 변수와 데이터타입
미리 정의된 예약어들
Dynamic Typing 은 생산성을 올려주지만, 예기치 못한 이슈가 생길 수 있다.
파이썬은 기본적으로 스네이크 케이스를 사용한다.
% 연산자 사용하기
c언어에서 사용하던 방식과 유사
format 함수
포맷 스트링: f-문자열
직관적이고, 가독성이 좋다.
Ch 4. 흐름제어 (조건문, 반복문, 예외처리)
예외처리
간단한 예외처리를 실습해보자.
Ch 5. 함수와 모듈
03. 함수 매개변수와 반환
04. 다양한 매개변수 실습
- 기본 매개변수는 일반 매개변수 뒤에 둬야한다.
- 기본 매개변수에는 가변객체를 넣을 때 조심하자.
가변인자 리스트
dictionary 로 전달해도 된다.
전달하려면 앞에 ** 를 붙여야 한다.
05. 모듈과 패키지
패키지 3.3 이후 버전에서는 init 파일 없이도 패키지로 인식할 수 있다.
06. 모듈과 패키지 실습
07. 파이썬의 라이브러리
문서: https://docs.python.org/ko/3/library/index.html
pip 는 파이썬을 설치할 때 함께 설치된다.
Ch 6. 객체 지향 프로그래밍
01. 객체지향 프로그래밍
02. 객체와 클래스
03. 멤버변수와 메소드
05. 객체지향 프로그래밍 주요 오소
speed 가 음수가 되어버렸다.
06. 객체지향 프로그래밍 주요 요소 실습
Person 추상 클래스로 만들어보자.
추상 클래스는 추상 메서드를 만들 수 있다.
추상 메서드를 구현하지 않았다면 에러가 나게 된다.
private 멤버변수는 언더바를 두개 붙인다.
상속 시 사용가능한 메서드는 protected 메서드라고 한다.
Ch 8. 정규표현식
01. 정규 표현식이란
02. 정규 표현식 사용하기
- I: ignore case
- M: multiline
- S: dot all
03. 정규 표현식 활용하기
csv 파일에서 4번째 값과 6번째 값 불러오기
휴대폰 번호 마스킹하기
정규표현식 테스트 사이트: https://regexr.com/
엔진마다 문법이 약간 다를 수 있다.
python 이라면 PCRE 를 체크해서 체크한다.
파이썬에서 플래그를 썼던 것 처럼 /i (대소문자 구문 x) 플래그를 넣을 수 있다.
개인정보 데이터를 넣고 잘 동작하는지 확인해보자.
정규표현식 레퍼런스도 볼 수 있다.
Ch 9. 웹 개발 기초
Ch 10. 챗봇용 데이터 수집하기
01. 웹 크롤러와 웹 스크래퍼
사람이 수동으로 할 수도 있고, 봇으로 할 수도 있다.
데이터 수집 시 유의할 점
- 로봇 표준 준수
- 저작권 및 이용 정책 확인
- 서버 부하 최소화
- 개인 정보 보호
02. requests, BeautifulSoup 라이브러리 살펴보기
공식문서: https://pypi.org/project/requests/
Quickstart
beautiful soup 알아보기
공식문서: https://www.crummy.com/software/BeautifulSoup/bs4/doc/
태그는 하나만 찾아온다.
모두 찾아오고 싶다면 find_all('a') 와 같이 쓴다.
이 내용들은 스크래퍼를 만들면서 다시 확인해볼 것이다.
03. 웹 페이지 가져오기
여러개의 라이브러리 함께 설치하기
python3 -m pip install bs4 requests
from bs4 import BeautifulSoup
import requests
url = 'https://www.musinsa.com/app/contents/onsale'
params = {
'd_cat_cd': '018',
'page_kind': 'onsale',
'list_kind': 'small',
'sort': 'pop_category',
'page': '1',
'display_cnt': '90',
'sale_fr_rate': '70',
'sale_yn': 'Y',
'sale_dt_yn': 'Y',
'sale_campaign_ym': 'N',
'chk_timesale': 'on',
}
response = requests.get(url,params=params)
print(response.status_code)
기본적으로 사이트에서 차단해둔다.
대량의 봇들을 막기위해서이다.
웹브라우저가 보낸 것 처럼 유저 agent 값을 넣어야 한다.
개발자도구의 콘솔을 열고 navigator.userAgent 를 검색한다.
header 에 user-agent 값을 넣으면
response.text
여기 상품 리스트부분을 가져와보자.
from bs4 import BeautifulSoup
import requests
url = 'https://www.musinsa.com/categories/item/018'
params = {
}
headers = {
'user-agent': "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'"
}
response = requests.get(url, params=params, headers=headers)
soup = BeautifulSoup(response.text,'html.parser')
list_box = soup.find('div', class_='list-box')
print(list_box)
실행을 하면
response = requests.get(url, params=params, headers=headers)
soup = BeautifulSoup(response.text,'html.parser')
list_box = soup.find('div', class_='list-box')
item_boxes = list_box.find_all('li', class_='li_box')
for item_box in item_boxes:
item_link = item_box.find('p',class_='list_info').findChild('a')
name = item_link.text.strip()
print(name)
for item_box in item_boxes:
item_title = item_box.find('p', class_='item_title').findChild('a')
brand = item_title.text
item_link = item_box.find('p',class_='list_info').findChild('a')
name = item_link.text.strip()
url = item_link['href']
item = {
'brand': brand,
'name': name,
'url': url,
}
print(item)
가격 가져오기
item_price = item_box.find('p',class_='price')
prices = re.findall(r'[\d,]+원',item_price.text)
print(prices)
정규표현식은 컴파일해서 쓰는 것이 더 좋으므로 아래와 같이 수정하면,
price_pattern = re.compile(r'[\d,]+원')
for item_box in item_boxes:
item_title = item_box.find('p', class_='item_title').findChild('a')
brand = item_title.text
item_link = item_box.find('p',class_='list_info').findChild('a')
name = item_link.text.strip()
url = item_link['href']
item_price = item_box.find('p',class_='price')
prices = price_pattern.findall(item_price.text)
img_box = item_box.find('div',class_='list_img').find('img')
print(img_box['data-original'])
최종코드
from bs4 import BeautifulSoup
import requests
import re
# https://www.musinsa.com/categories/item/018?d_cat_cd=018&brand=&list_kind=small&sort=pop_category&sub_sort=&page=1&display_cnt=90&group_sale=&exclusive_yn=&sale_goods=×ale_yn=Y&ex_soldout=&plusDeliveryYn=&kids=&color=&price1=&price2=&shoeSizeOption=&tags=&campaign_id=&includeKeywords=&measure=
url = 'https://www.musinsa.com/categories/item/018'
params = {
'd_cat_cd':'018',
'list_kind':'small',
'sort':'pop_category',
'page':'1',
'display_cnt':'90',
'timesale_yn':'Y',
}
headers = {
'user-agent': "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'"
}
response = requests.get(url, params=params, headers=headers)
soup = BeautifulSoup(response.text,'html.parser')
list_box = soup.find('div', class_='list-box')
item_boxes = list_box.find_all('li', class_='li_box')
price_pattern = re.compile(r'[\d,]+원')
for item_box in item_boxes:
item_title = item_box.find('p', class_='item_title').findChild('a')
brand = item_title.text
item_link = item_box.find('p',class_='list_info').findChild('a')
name = item_link.text.strip()
url = item_link['href']
item_price = item_box.find('p',class_='price')
prices = price_pattern.findall(item_price.text)
img_box = item_box.find('div',class_='list_img').find('img')
item = {
'brand': brand,
'name': name,
'url': 'https:' + url,
'original_price': prices[0],
'sale_price': prices[1],
'image':img_box['data-original'],
}
print(item)
04. 코드 정리하기
from bs4 import BeautifulSoup
import requests
import re
class Scraper:
def __init__(self):
# https://www.musinsa.com/categories/item/018?d_cat_cd=018&brand=&list_kind=small&sort=pop_category&sub_sort=&page=1&display_cnt=90&group_sale=&exclusive_yn=&sale_goods=×ale_yn=Y&ex_soldout=&plusDeliveryYn=&kids=&color=&price1=&price2=&shoeSizeOption=&tags=&campaign_id=&includeKeywords=&measure=
self.__url = 'https://www.musinsa.com/categories/item/018'
self.__params = {
'd_cat_cd':'018',
'list_kind':'small',
'sort':'pop_category',
'page':'1',
'display_cnt':'90',
# 'timesale_yn':'Y',
}
self.__headers = {
'user-agent': "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'"
}
self.__price_pattern = re.compile(r'[\d,]+원')
def do(self):
response = requests.get(self.__url, params=self.__params, headers=self.__headers)
soup = BeautifulSoup(response.text, 'html.parser')
list_box = soup.find('div', class_='list-box')
item_boxes = list_box.find_all('li', class_='li_box')
result = []
for item_box in item_boxes:
# 브랜드명 가져오기
item_title = item_box.find('p', class_='item_title').findChild('a')
brand = item_title.text
# 아이템 이름, URL 가져오기
item_link = item_box.find('p', class_='list_info').findChild('a')
name = item_link.text.strip()
url = 'https:' + item_link['href']
# 가격정보 가져오기
item_price = item_box.find('p', class_='price')
prices = self.__price_pattern.findall(item_price.text)
sale_price = prices[1] if len(prices) >= 2 else prices[0]
# 이미지 가져오기
img_box = item_box.find('div', class_='list_img').find('img')['data-original']
item = {
'brand': brand,
'name': name,
'url': url,
'original_price': prices[0],
'sale_price': sale_price,
'image': img_box,
}
result.append(item)
return result
if __name__ == '__main__':
scraper = Scraper()
items = scraper.do()
print(items)
Ch 11. 챗봇 제작하기
01. 챗봇이란
제작할 디스코드 챗봇을 살펴보자.
discord.py 라이브러리도 살펴보자.
챗봇 (Chatbot)
02. 디스코드 챗봇 등록하기
디스코드 개발자 사이트: https://discord.com/developers/docs/intro
create app 을 한 후
왼쪽의 사이드메뉴의 bot 으로 접근한다.
봇의 사용량에 따라 실제 과금이 일어나므로 토큰 값은 유출되지 않아야 한다.
OAuth2 로 이동 후 URL 제네레이터로 이동한다.
bot scope 를 추가한다.
send message 를 보내는 기능을 허용한다.
bot 과 send message 만 체크한다.
아래 url 을 복사해 새로운 링크로 열면 봇을 서버에 추가할 수 있다.
이어서 애플리케이션을 봇에 추가해보자.
봇에게 파이썬 코드를 집어넣기 위해 discord.py 를 사용해보자.
03. 챗봇 기능 연동하기
사이드탭의 Bot 으로 넘어가보자.
공식문서: https://discordpy.readthedocs.io/en/stable/#
설치
python3 -m pip install -U discord.py
minimal bot 코드를 복사해 실행해보자.
권한을 모두 준 후 변경사항을 저장해준다.
메서드
on_ready: 봇이 사용가능해졌을 때 메시지 출력
on_message: 봇이 있는 채널에서 메시지가 전달되었을 때 실행되는 함수
$hello 로 시작하는 메시지를 보내면
임베드라고 하는 타입의 객체를 사용해보자.
embed 메뉴얼: https://discordpy.readthedocs.io/en/stable/api.html?highlight=embed#discord.Embed
디스코드 메뉴얼에서 embed 타입의 종류를 볼 수 있다.
우리는 rich 라는 타입을 사용해 볼 것 이다.
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
if message.content.startswith('!타임세일'):
# 무신사 타임세일 결과를 출력한다.
scraper = Scraper()
results = scraper.do()
for item in results:
embed = discord.Embed(type='rich', title=item['name'])
embed.description = item['brand']
embed.set_thumbnail(url=item['image'])
embed.url = item['url']
await message.channel.send(embed=embed)
마지막으로 가격정보를 추가해보자.
bot.py 전체코드
# This example requires the 'message_content' intent.
import discord
from scraper import Scraper
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
@client.event
async def on_ready():
print(f'We have logged in as {client.user}')
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
if message.content.startswith('!타임세일'):
# 무신사 타임세일 결과를 출력한다.
scraper = Scraper()
results = scraper.do()
for item in results:
embed = discord.Embed(type='rich', title=item['name'])
embed.description = item['brand']
embed.set_thumbnail(url=item['image'])
embed.url = item['url']
embed.add_field(name='원래 가격',value=item['original_price'],inline=True)
embed.add_field(name='할인 가격',value=item['sale_price'],inline=True)
await message.channel.send(embed=embed)
client.run('your token here')
04. 코드 정리하기
embed 생성구문을 함수화하고 .env 파일에 토큰을 담았다.
# This example requires the 'message_content' intent.
import os
import discord
from scraper import Scraper
from dotenv import load_dotenv
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
def build_message(item):
embed = discord.Embed(type='rich', title=item['name'])
embed.description = item['brand']
embed.set_thumbnail(url=item['image'])
embed.url = item['url']
embed.add_field(name='원래 가격', value=item['original_price'], inline=True)
embed.add_field(name='할인 가격', value=item['sale_price'], inline=True)
return embed
@client.event
async def on_ready():
print(f'We have logged in as {client.user}')
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
if message.content.startswith('!타임세일'):
# 무신사 타임세일 결과를 출력한다.
scraper = Scraper()
results = scraper.do()
embeds = []
for item in results:
embeds.append(build_message(item))
await message.channel.send(embeds=embeds)
load_dotenv()
client.run(os.getenv('token'))
Part 2. Django 필수 개념 & 실전 프로젝트 (맛집 추천 사이트의 어드민 만들기)
'Backend > 노트' 카테고리의 다른 글
러닝 타입스크립트 (0) | 2024.03.30 |
---|---|
NestJS로 API 만들기 (1) | 2024.03.26 |
FastAPI 를 사용한 파이썬 웹 개발 (2) | 2023.12.01 |
고랭 애플로그인 구현 (golang apple login) (0) | 2023.05.06 |
도커 환경에서 디버그하기 (0) | 2023.04.30 |