이 포스팅은 2019 Winter Course for Undergraduate Students를 통하여 주차별로 학습하고 진행한 프로젝트 과정을 정리 및 최종 코드를 업로드 한 내용입니다.
2019 Winter Course for Undergraduate Students
주차별로 학습한 내용은 다음과 같습니다.
1주차 Linux Bootcamp, Git & Github
- 생활코딩 리눅스 강좌, 생활코딩, 2017
- 리눅스 커맨드라인 툴, 인프런, 2019
- 지옥에서 온 Git, 생활코딩, 2018
- 버전 관리 시스템 git, 생활코딩, 2018
- Git과 Github, 생활코딩, 2018
2주차 Crawling with Python
- 파이썬입문과 크롤링기초 부트캠프, 인프런, 2019
- 업무 자동화를 위한 파이썬 pyautogui, beautifulsoup 크롤링 기초, 인프런, 2019
- 현존 최강 크롤링 기술: Scrapy와 Selenium 정복, 인프런, 2019
3주차 Web Bootcamp
- 컴퓨터, 웹, 코딩, 프로그래밍의 시작 - Web1, 생활코딩, 2018
- WEB2 - CSS, 생활코딩, 2018
- WEB2 - JavaScript, 생활코딩, 2018
- Bootstrap 4 & 3 Framework Tutorial, 인프런, 2018
- 나만의 포트폴리오 웹페이지 만들기, 인프런, 2019
- 퍼블리셔 취업을 위해 제대로 배워보는 html과 css, 그리고 웹표준, 인프런, 2018
4주차 Database Bootcamp
- DATABASE 1&2 - MySQL, 생활코딩, 2018
- SQL/DB(MySQL) 기본부터 파이썬/데이터분석 활용까지!, 인프런, 2019
5주차 Django, IDE
- 파이썬으로 장고(Django) 공략하기: 입문, 인프런, 2019
- Django Mini project BEST 3, 인프런, 2019
- 내 손으로 만드는 Django 2.x 인스타그램 클론 강의, 인프런, 2019
- 쉽게 배워보는 파이참(PyCharm) 핵심 가이드, 인프런, 2019
6주차 AWS Bootcamp
- AWS (아마존 웹서비스) 가입부터 활용까지, 생활코딩, 2016
- 진짜 입문자를 위한 클라우드와 AWS, 인프런, 2019
마일스톤 일정
마일스톤 일정을 계획하고 각 기간에 따라 정의한 산출물이 나오도록 하였습니다.
일정 | 산출물 | 기간 |
---|---|---|
Linux Bootcamp, Git & Github | Github 페이지 형성 후 README.md에 프로젝트 명과 기간 등 필요 내용 추가 | 2020.01.02 ~ 2020.01.08 |
Crawling with Python | 프로젝트에 필요한 데이터 수집을 위한 크롤링코드를 작성하고 데이터는 Excel, csv 파일 등등으로 저장 | 2020.01.09 ~ 2020.01.15 |
Web Bootcamp | html, css, JavaScript를 학습하고 Bootstrap, jQuery를 이용하여 웹 Front-end 제작 | 2020.01.16 ~ 2020.01.22 |
Database Bootcamp | Mysql을 이용해 데이터를 Database화 | 2020.01.23 ~ 2020.01.29 |
Django | Django로 이전에 만들었던 Database와 Front-end 연결 | 2020.01.30 ~ 2020.02.05 |
AWS Bootcamp | AWS로 만들었던 웹 서비스 시스템을 배포 | 2020.02.06 ~ 2020.02.12 |
발표 | 간단한 ppt 등을 이용하여 본인이 만든 시스템 소개하기 | 2020.02.13 ~ 2020.02.19 |
프로젝트 진행 과정
- 먼저 프로젝트에 필요한 데이터를 수집하기 위해 Python으로 Crawling 코드를 작성합니다. 업무 자동화를 위해 Selenium을 사용합니다. 데이터는 pandas를 활용하여 Dataframe을 생성하고 csv 파일로 저장합니다.
네이버(Naver) 연극 정보
Crawling with python Code
from urllib.parse import quote_plus # 한글 텍스트를 퍼센트 인코딩으로 변환
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # 해당 태그를 기다림
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException # 태그가 없는 예외 처리
import time
import pandas as pd
_input = input('''-월--일, -월, 이번주, 이번주말 중 선택하여 입력해주세요.
(-은 숫자 입력, 이번년도만 가능) : ''')
user_input = quote_plus(_input)
url = f'https://search.naver.com/search.naver?where=nexearch&sm=tab_etc&query={user_input}%20%EC%97%B0%EA%B7%B9%20%EA%B3%B5%EC%97%B0'
chromedriver = 'C:/Users/LeeJiheon/Desktop/가천대학교/TEAMLAB/2019_winter_study/2주차/crawling/chromedriver'
options = webdriver.ChromeOptions()
options.add_argument('headless') # 웹 브라우저를 띄우지 않는 headlss chrome 옵션 적용
options.add_argument('disable-gpu') # GPU 사용 안함
options.add_argument('lang=ko_KR') # 언어 설정
driver = webdriver.Chrome(chromedriver, options=options)
driver.get(url)
try: # 정상 처리
element = WebDriverWait(driver, 3).until(
EC.presence_of_element_located((By.CLASS_NAME, 'list_title'))
) # 해당 태그 존재 여부를 확인하기까지 3초 기다림
theater_list = []
pageNum = int(driver.find_element_by_class_name('_totalCount').text)
count = 0
for i in range(1, pageNum):
theater_data = driver.find_elements_by_class_name('list_title')
img_data = driver.find_elements_by_class_name('list_thumb')
for k in theater_data:
theater_list.append(k.text.split('\n'))
for j in img_data:
count += 1
j.screenshot(f'img/{count}.png')
driver.find_element_by_xpath("//a[@class='btn_page_next _btnNext on']").click()
time.sleep(2)
except TimeoutException: # 예외 처리
print('해당 페이지에 연극 정보가 존재하지 않습니다.')
finally: # 정상, 예외 둘 중 하나여도 반드시 실행
driver.quit()
for i in range(len(theater_list)):
theater_list[i].append(theater_list[i][1].split('~')[0])
theater_list[i].append(theater_list[i][1].split('~')[1])
for i in range(len(theater_list)):
if theater_list[i][4] == '오픈런':
theater_list[i][4] = '50.01.01.'
theater_list[i].append('True')
else:
theater_list[i].append('False')
theater_df = pd.DataFrame(theater_list,
columns=['연극명', '기간', '장소', '개막일', '폐막일', '오픈런'])
theater_df.index = theater_df.index + 1 # 인덱스 초기값 1로 변경
theater_df['개막일'] = pd.to_datetime(theater_df['개막일'], format='%y.%m.%d.')
theater_df['폐막일'] = pd.to_datetime(theater_df['폐막일'], format='%y.%m.%d.')
theater_df.to_csv(f'theater_{_input}_df.csv', mode='w', encoding='utf-8-sig',
header=True, index=True)
print('웹 크롤링이 완료되었습니다.')
-
Theater DataFrame
-
Theater CSV
-
Theater IMG
최저가 연극 관람 티켓 구매 정보 Crawling
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import pandas as pd
theater_df = pd.read_csv('theater_df.csv')
chromedriver = 'C:/Users/LeeJiheon/Desktop/가천대학교/TEAMLAB/2019_winter_study/2주차/crawling/chromedriver'
driver = webdriver.Chrome(chromedriver)
driver.get('https://shopping.naver.com')
search_word = theater_df['연극명'].values.tolist()
shop_list = []
for i in search_word:
search_input = driver.find_element_by_xpath('//*[@id="autocompleteWrapper"]/input[1]')
search_input.clear()
search_input.send_keys(i)
search_click = driver.find_element_by_xpath('//*[@id="autocompleteWrapper"]/a[2]')
search_click.send_keys(Keys.RETURN)
elem = driver.find_element_by_xpath('//*[@id="_search_list"]/div[1]/ul/li[1]/div[2]/div/a')
purchase_name = elem.text
purchase_link = elem.get_attribute('href')
elem = driver.find_element_by_css_selector('#_search_list > div.search_list.basis > ul > li:nth-child(1) > div.info > span.price > em > span.num._price_reload')
purchase_price = elem.text
shop_list.append([purchase_name, purchase_price, purchase_link])
time.sleep(2)
driver.quit()
shop_df = pd.DataFrame(shop_list,
columns=['Title', 'Price', 'link'])
shop_df.to_csv('shop_df.csv', mode='w', encoding='utf-8-sig',
header=True, index=True)
print('웹 크롤링이 완료되었습니다.')
-
Shop DataFrame
Theater_Detail_Info Crawling
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pandas as pd
theater_df = pd.read_csv('theater_df.csv')
search_word = theater_df['연극명'].values.tolist()
chromedriver = '/home/leejiheon/workspace/crawling/chromedriver'
driver = webdriver.Chrome(chromedriver)
driver.get('https://search.naver.com/search.naver?sm=top_hty&fbm=1&ie=utf8&query=%EA%B7%B9%EC%A0%81%EC%9D%B8%ED%95%98%EB%A3%BB%EB%B0%A4')
detail_list = []
for i in search_word:
search_input = driver.find_element_by_xpath('//*[@id="nx_query"]')
search_input.clear()
search_input.send_keys(i)
search_click = driver.find_element_by_xpath('//*[@id="nx_search_form"]/fieldset/button')
search_click.send_keys(Keys.RETURN)
elem = driver.find_element_by_class_name('item_list')
info = elem.text
info_list = info.strip().split('\n')
age = info_list[2]
time = info_list[4]
discription = info_list[-1]
detail_list.append([i, age, time, discription])
driver.quit()
detail_df = pd.DataFrame(detail_list,
columns=['연극명', '관람등급', '공연시간', '내용'])
detail_df.to_csv('detail_df.csv', mode='w', encoding='utf-8-sig', header=True, index=True)
print('웹 크롤링이 완료되었습니다.')
-
Theater_Detail DataFrame
- Bootstrap을 활용하여 웹 Front-end 제작합니다.
https://github.com/Jiheon-Lee/teamlab_2019_winter/tree/master/Week_3
- Mysql을 이용하여 Web Crawling으로 수집한 데이터를 Database화 합니다.
Database create code
CREATE DATABASE tig;
USE tig;
CREATE TABLE theaters(
TheaterID int not null auto_increment,
TheaterName varchar(50) not null,
Period varchar(50) not null,
Place varchar(50) not null,
OpeningDay date null,
ClosingDay date null,
OpenRun varchar(50) default null,
primary key(TheaterID)
);
CREATE TABLE theaters_details(
TheaterID int not null,
ViewingAge varchar(50) null,
PerformanceTime varchar(50) null,
Descriptions varchar(255) null,
Price decimal(7) null,
ShopTitle varchar(50) null,
ShopLink longtext null,
Image varchar(255) null, # Image File 경로 저장
foreign key(TheaterID)
references theaters(TheaterID) on delete cascade on update cascade
);
CREATE TABLE users(
UserID int not null auto_increment,
UserName varchar(50) not null,
primary key(UserID)
);
CREATE TABLE comments(
CommentID int not null auto_increment,
UserID int not null,
TheaterID int not null,
Content varchar(255) null,
Reply varchar(255) null,
Likes int null,
Image blob null,
primary key(CommentID),
foreign key(UserID)
references users(UserID) on delete cascade on update cascade,
foreign key(TheaterID)
references theaters(TheaterID) on delete cascade on update cascade
);
- Database ERD
- Theaters Table
- Theaters_details Table
- Django로 Mysql과 연동하여 Database와 Front-end를 연결 후 Django Form을 이용하여 검색 기능을 구현하고 Pagination, 인기순, 최신순과 같은 각 기능들을 구현하기 위한 jQuery ajax 코드를 작성합니다. 전체적인 코드는 아래 링크에서 자세하게 확인할 수 있습니다.
https://github.com/Jiheon-Lee/teamlab_2019_winter/tree/master/Week_5
- AWS EC2를 이용하여 가상 컴퓨터 인스턴스를 생성하고 ssh를 사용하여 인스턴스에 접속 한 후 서버 환경 설정을 마치고 scp를 사용하여 완성한 장고 프로젝트를 서버 컴퓨터에 업로드합니다.
$ ssh -i ~/.ssh/EC2-TIG.pem ubuntu@EC2 퍼블릭 DNS 주소
$ scp -i ~/.ssh/EC2-TIG.pem -r /home/leejiheon/workspace/tig ubuntu@퍼블릭 DNS 주소:/srv/
http://ec2-54-180-113-171.ap-northeast-2.compute.amazonaws.com:8080/
내용 정리
https://github.com/Jiheon-Lee/teamlab_2019_winter
Theater Information Guide 프로젝트
- Theater Information Guide로 파이썬으로 웹 크롤링을 위한 코드를 작성
- 수집한 데이터를 MYSQL을 이용하여 DB화
- 여러 기능을 제공하는 시스템을 개발
- Bootstrap으로 웹 Front-end를 구현
- Django로 Database와 Front-end를 연결, jQuery(ajax) 코드 작성
- AWS(아마존웹서비스) 서버를 이용하여 배포하는 것이 목표
2020.01.02 ~ 2020.02.19
Theater Information Guide 기능
- Keyword와 Filter를 이용하여 연극에 대하여 원하는 정보를 검색 할 수 있습니다.
- 인기순, 관람등급, 공연시간, 기간, 장소, 내용 등 연극에 대하여 자세한 정보를 제공합니다.
- 연극 관람 티켓을 최저가로 구매할 수 있도록 최저가, 구매처 정보를 제공하고 도와드립니다.
개인으로 프로젝트를 진행하여 힘들었지만 학습한 내용을 바탕으로 실제로 직접 적용하며 데이터를 수집, 시스템을 설계, Database와 Web을 구현, AWS 배포까지 프로젝트를 진행할 수 있는 좋은 경험이었습니다. 아쉬웠던 부분은 기간이 짧아서 부족한 부분이 보였습니다. 이러한 부분은 이후에 더 깊게 학습하여 개선하도록 하겠습니다. 감사합니다.