TEAMLAB

Human knowledge belongs to the world . -AntiTrust

Theater Information Guide - 이지헌

이 포스팅은 2019 Winter Course for Undergraduate Students를 통하여 주차별로 학습하고 진행한 프로젝트 과정을 정리 및 최종 코드를 업로드 한 내용입니다.

2019 Winter Course for Undergraduate Students

주차별로 학습한 내용은 다음과 같습니다.

1주차 Linux Bootcamp, Git & Github

2주차 Crawling with Python

3주차 Web Bootcamp

4주차 Database Bootcamp

5주차 Django, IDE

6주차 AWS Bootcamp

마일스톤 일정

마일스톤 일정을 계획하고 각 기간에 따라 정의한 산출물이 나오도록 하였습니다.

일정 산출물 기간
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

프로젝트 진행 과정

  1. 먼저 프로젝트에 필요한 데이터를 수집하기 위해 Python으로 Crawling 코드를 작성합니다. 업무 자동화를 위해 Selenium을 사용합니다. 데이터는 pandas를 활용하여 Dataframe을 생성하고 csv 파일로 저장합니다.

네이버(Naver) 연극 정보

Naver_theater

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 DataFrame


  • Theater CSV
    Theater CSV


  • Theater IMG
    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 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
    Theater_Detail DataFrame


  1. Bootstrap을 활용하여 웹 Front-end 제작합니다.

    https://github.com/Jiheon-Lee/teamlab_2019_winter/tree/master/Week_3

index index_under theater_detail


  1. 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


tig_database_ERD


  • Theaters Table


Theaters Table


  • Theaters_details Table


Theaters_details


  1. Django로 Mysql과 연동하여 Database와 Front-end를 연결 후 Django Form을 이용하여 검색 기능을 구현하고 Pagination, 인기순, 최신순과 같은 각 기능들을 구현하기 위한 jQuery ajax 코드를 작성합니다. 전체적인 코드는 아래 링크에서 자세하게 확인할 수 있습니다.

    https://github.com/Jiheon-Lee/teamlab_2019_winter/tree/master/Week_5


  1. 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/

AWS Instance


http://ec2-54-180-113-171.ap-northeast-2.compute.amazonaws.com:8080/


내용 정리

https://github.com/Jiheon-Lee/teamlab_2019_winter

Theater Information Guide 프로젝트

  1. Theater Information Guide로 파이썬으로 웹 크롤링을 위한 코드를 작성
  2. 수집한 데이터를 MYSQL을 이용하여 DB화
  3. 여러 기능을 제공하는 시스템을 개발
  4. Bootstrap으로 웹 Front-end를 구현
  5. Django로 Database와 Front-end를 연결, jQuery(ajax) 코드 작성
  6. AWS(아마존웹서비스) 서버를 이용하여 배포하는 것이 목표

2020.01.02 ~ 2020.02.19


Theater Information Guide 기능

  • Keyword와 Filter를 이용하여 연극에 대하여 원하는 정보를 검색 할 수 있습니다.
  • 인기순, 관람등급, 공연시간, 기간, 장소, 내용 등 연극에 대하여 자세한 정보를 제공합니다.
  • 연극 관람 티켓을 최저가로 구매할 수 있도록 최저가, 구매처 정보를 제공하고 도와드립니다.


개인으로 프로젝트를 진행하여 힘들었지만 학습한 내용을 바탕으로 실제로 직접 적용하며 데이터를 수집, 시스템을 설계, Database와 Web을 구현, AWS 배포까지 프로젝트를 진행할 수 있는 좋은 경험이었습니다. 아쉬웠던 부분은 기간이 짧아서 부족한 부분이 보였습니다. 이러한 부분은 이후에 더 깊게 학습하여 개선하도록 하겠습니다. 감사합니다.