jellimin / 2023-kopis

0 stars 0 forks source link

데이터 수집, 적재 | 공연 중/개막예정 데이터 #15

Open sum-k opened 1 year ago

sum-k commented 1 year ago

플레이DB 페이지에서 각 장르마다 현재 공연 중/개막예정 으로 분류된 공연 데이터를 가져오는 코드입니다.
먼저 [공연명/ 장르/ 공연 세부 url] 을 가져와 csv 파일을 생성했고, 이 후 줄거리, 기간 등을 가져오는 코드를 추가하도록 하겠습니다! 각 장르마다 html 주소가 조금씩 다르고, 통일된 id 등을 찾지 못해 직접 수정하면서 코드를 진행시켰습니다. 시간되실때 수정할 부분이 있나 한번씩 봐주시면 감사하겠습니다:)

# 필요한 모듈 불러오기
import re
from bs4 import BeautifulSoup
import time
import csv
import pandas as pd
from tqdm import tqdm
from tqdm import trange
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import warnings
warnings.filterwarnings('ignore')

# 현재 공연중 -> 공연 리스트 먼저
title = []
url = []
genre = []

for i in [6]: #range(1, 8) -> [4,7] -> [6] # 탭마다 위치가 계속 다름.. 

    query = f"http://www.playdb.co.kr/playdb/playdblist.asp?sReqMainCategory=00000{i}" # 사이트 주소
    driver = webdriver.Chrome()
    driver.get(query)
    driver.implicitly_wait(10)

    c = '//*[@id="contents"]/div[1]/ul/li[{}]/a/img'.format(i) # 장르
    cc = driver.find_element(By.XPATH, c).get_attribute('alt')

    # 현재 공연중, 개막예정으로 이동
    try:
        elem = driver.find_element(By.XPATH, '//*[@id="contents"]/div[2]/table/tbody/tr[5]/td/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr/td[2]/table/tbody/tr[2]/td/table/tbody/tr[2]/td/a[1]')
    except:
        print('오류발생')
        continue

    elem.send_keys(Keys.ENTER)
    driver.implicitly_wait(5)

    while(True):
        try:
            for j in range(1, 11): # 10개의 탭 존재
                for k in range(1, 16): # 한 탭에 15개의 공연 존재
                    kk = 2*k + 1

                    a = "/html/body/div[1]/div[2]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[{}]/td/table/tbody/tr/td[1]/table/tbody/tr/td[3]/table/tbody/tr[1]/td/b/font/a".format(kk) # 제목
                    b = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[{}]/td/table/tbody/tr/td[1]/table/tbody/tr/td[3]/table/tbody/tr[1]/td/b/font/a'.format(kk) # url

                    aa = driver.find_element(By.XPATH, a).text
                    bb = driver.find_element(By.XPATH, b).get_attribute('onclick')

                    bb = re.sub(r'[^0-9]', '', bb)

                    title.append(aa)
                    url.append(bb)
                    genre.append(cc)

                # 다음페이지 클릭
                if (page==0 & j < 10):
                    botton = '//*[@id="contents"]/div[2]/table/tbody/tr[11]/td/table/tbody/tr[35]/td/a[{}]'.format(j)
                    driver.find_element(By.XPATH, botton).send_keys(Keys.ENTER)
                    driver.implicitly_wait(10)

                elif (page > 0 & j < 10):
                    botton = '//*[@id="contents"]/div[2]/table/tbody/tr[11]/td/table/tbody/tr[35]/td/a[{}]'.format(j+1)
                    driver.find_element(By.XPATH, botton).send_keys(Keys.ENTER)
                    driver.implicitly_wait(10)

                #10번 다음페이지
                elif (page == 1 & j == 10):
                    botton_2 = '//*[@id="contents"]/div[2]/table/tbody/tr[11]/td/table/tbody/tr[35]/td/a[10]'
                    driver.find_element(By.XPATH, botton_2).send_keys(Keys.ENTER)
                    driver.implicitly_wait(5)

                else:
                    botton_2 = '//*[@id="contents"]/div[2]/table/tbody/tr[11]/td/table/tbody/tr[35]/td/a[11]'
                    driver.find_element(By.XPATH, botton_2).send_keys(Keys.ENTER)
                    driver.implicitly_wait(5)

            page += 1

        except: # 더이상 없으면 멈춤
            break

# 개막예정 -> 공연 리스트 먼저
title = []
url = []
genre = []

for i in [6]: #range(1, 8) -> [4,7] -> [6] # 탭마다 위치가 계속 다름.. 

    query = f"http://www.playdb.co.kr/playdb/playdblist.asp?sReqMainCategory=00000{i}" # 사이트 주소
    driver = webdriver.Chrome()
    driver.get(query)
    driver.implicitly_wait(10)

    c = '//*[@id="contents"]/div[1]/ul/li[{}]/a/img'.format(i) # 장르
    cc = driver.find_element(By.XPATH, c).get_attribute('alt')

    # 현재 공연중, 개막예정으로 이동
    try:
        elem = driver.find_element(By.XPATH, '//*[@id="contents"]/div[2]/table/tbody/tr[5]/td/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr/td[2]/table/tbody/tr[2]/td/table/tbody/tr[2]/td/a[2]')
    except:
        print('오류발생')
        continue

    elem.send_keys(Keys.ENTER)
    driver.implicitly_wait(5)

    page=0

    while(True):
        try:
            for j in range(1, 11): # 10개의 탭 존재
                for k in range(1, 16): # 한 탭에 15개의 공연 존재
                    kk = 2*k + 1

                    a = "/html/body/div[1]/div[2]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[{}]/td/table/tbody/tr/td[1]/table/tbody/tr/td[3]/table/tbody/tr[1]/td/b/font/a".format(kk) # 제목
                    b = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[{}]/td/table/tbody/tr/td[1]/table/tbody/tr/td[3]/table/tbody/tr[1]/td/b/font/a'.format(kk) # url

                    aa = driver.find_element(By.XPATH, a).text
                    bb = driver.find_element(By.XPATH, b).get_attribute('onclick')

                    bb = re.sub(r'[^0-9]', '', bb)

                    title.append(aa)
                    url.append(bb)
                    genre.append(cc)

                # 다음페이지 클릭
                if (page==0 & j < 10):
                    botton = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[35]/td/a[{}]'.format(j)
                    driver.find_element(By.XPATH, botton).send_keys(Keys.ENTER)
                    driver.implicitly_wait(10)

                elif (page > 0 & j < 10):
                    botton = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[35]/td/a[{}]'.format(j+1)
                    driver.find_element(By.XPATH, botton).send_keys(Keys.ENTER)
                    driver.implicitly_wait(10)

                #10번 다음페이지
                elif (page == 1 & j == 10):
                    botton_2 = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[35]/td/a[10]'
                    driver.find_element(By.XPATH, botton_2).send_keys(Keys.ENTER)
                    driver.implicitly_wait(5)

                else:
                    botton_2 = '//*[@id="contents"]/div[2]/table/tbody/tr[8]/td/table/tbody/tr[35]/td/a[11]'
                    driver.find_element(By.XPATH, botton_2).send_keys(Keys.ENTER)
                    driver.implicitly_wait(5)

            page += 1

        except: # 더이상 없으면 멈춤
            break
sum-k commented 1 year ago

개막예정_list.csv 공연중_list.csv

sum-k commented 1 year ago

밑에 코드는 필요한 정보들 불러오는 코드이고, 줄거리와 작품설명 불러오는 코드는 계속 오류가 떠서.. 일단 지워뒀습니다!
링크 위 페이지에서 '기본소개' 탭에는 모든 텍스트가 나오지 않아있어서 '작품소개' 탭으로 옮겨서 크롤링을 하려고 했는데, XPATH로 해도, CSS selector로 해도 텍스트가 추출되지 않고 오류가 나요ㅠㅠ '/html/body/table/tbody/tr[2]/td/table/tbody/tr[3]/td' 이게 XPATH로 나오는데, id가 없어서 그런건지 table이라 그런건지 원인파악을 못하겠습니다..

# 필요한 모듈 불러오기
import re
from bs4 import BeautifulSoup
import time
import csv
import pandas as pd
from tqdm import tqdm
from tqdm import trange
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
import warnings
warnings.filterwarnings('ignore')

# [기간/줄거리/장소/이미지 url/인터파크 url] 추출
# 1. 현재 공연중
data1 = pd.read_csv("공연중_list.csv")

# 빈 리스트 생성
date = []
place = []
image = []
actor = []
content = [] # 줄거리
detail = [] # 상세정보
url = [] # 후기 추출을 위한 인터파크 url

# for문을 이용해 data의 링크에 하나씩 접근
for k in tqdm(range(len(data1))):
  # 공연 사이트 주소
  try:
    query = f"http://www.playdb.co.kr/playdb/playdbDetail.asp?sReqPlayno={data1['url'][k]}" # 사이트 주소
    driver = webdriver.Chrome()
    driver.get(query)
    driver.implicitly_wait(10)
  except:
      continue

  try:
    ur = driver.find_element(By.CSS_SELECTOR, '#wrap > div.pddetail > div.pddetail_info > div.detaillist > p > a').get_attribute('href')
  except:
    ur = '후기탭 없음'
  url.append(ur)

  # 공연소개 탭으로 이동(줄거리)

  tab = '//*[@id="contents"]/div[1]/div[1]/ul[1]/li[2]/a'
  driver.find_element(By.XPATH, tab).send_keys(Keys.ENTER)
  driver.implicitly_wait(5)

  a = '//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[2]/td[2]' # 기간
  b = '//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[3]/td[2]/a' # 장소
  c = '//*[@id="wrap"]/div[3]/h2/img' # 이미지 주소
  # d = # 상세정보
  # e = # 줄거리

  temp = [] # 배우
  while(True):
    try:
      for p in range(1, 6):
        e = f'//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[4]/td[2]/a[{p}]'
        ee = driver.find_element(By.XPATH, e).text
        temp.append(ee)
      temp = ",".join(temp)
    except:
      break
  actor.append(temp)

  aa = driver.find_element(By.XPATH, a).text
  bb = driver.find_element(By.XPATH, b).text
  cc = driver.find_element(By.XPATH, c).get_attribute('src')

  date.append(aa)
  place.append(bb)
  image.append(cc) 

  # try:  
  #   content.append(dd)
  # except:
  #   dd = '줄거리 없음'
  #   content.append(dd)
  #   continue

data1['기간'] = date
data1['장소'] = place
data1['이미지url'] = image
data1['배우'] = actor
data1['후기용url'] = url

data1.to_csv("공연중_후기용_list.csv", index=False)
alsrud2298 commented 1 year ago

저번에 민영님 오류있었던 것과 같이 해당 내용이 iframe 내부에 있어서 오류가 발생했던 것 같습니다 ! 아래와 같이 태그가 iframe 내부에 있는 경우 image

driver.switch_to.frame("iFrmContent") #iframe 페이지로 전환 다음과 같이 페이지 전환을 해주어야 내부 정보에 접근이 가능하더라구요 !

그리고 혹시나 공연 소개 탭이 2번째에 없는 경우도 존재할 것 같아서 공연 소개탭으로 이동하는 부분도 조금 수정했습니다 !

# 필요한 모듈 불러오기
import re
from bs4 import BeautifulSoup
import time
import csv
import pandas as pd
from tqdm import tqdm
from tqdm import trange
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

import warnings
warnings.filterwarnings('ignore')
chrome_options = Options()
chrome_options.add_experimental_option('detach', True) # 자동 창꺼짐 방지

# [기간/줄거리/장소/이미지 url/인터파크 url] 추출
# 1. 현재 공연중
data1 = pd.read_csv("./data/공연중_list.csv")[:1]

# 빈 리스트 생성
date = []
place = []
image = []
actor = []
content = [] # 줄거리
detail = [] # 상세정보
url = [] # 후기 추출을 위한 인터파크  url

# for문을 이용해 data의 링크에 하나씩 접근
for k in tqdm(range(len(data1))):
  # 공연 사이트 주소
  try:
    query = f"http://www.playdb.co.kr/playdb/playdbDetail.asp?sReqPlayno={data1['url'][k]}" # 사이트 주소
    service = Service(executable_path = "./chromedriver.exe" )
    driver = webdriver.Chrome(service = service, options=chrome_options)

    driver.get(query)
    driver.implicitly_wait(5)
  except:
      continue

  try:
    ur = driver.find_element(By.CSS_SELECTOR, '#wrap > div.pddetail > div.pddetail_info > div.detaillist > p > a').get_attribute('href')
  except:
    ur = '후기탭 없음'
  url.append(ur)

  # 공연소개 탭으로 이동(줄거리)
 # 수정한 파트 !! 
 tab = '//*[@alt="공연소개"]'
  a = driver.find_element(By.XPATH, tab)

  driver.execute_script("arguments[0].click();", a)
  driver.implicitly_wait(5)

  a = '//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[2]/td[2]' # 기간
  b = '//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[3]/td[2]/a' # 장소
  c = '//*[@id="wrap"]/div[3]/h2/img' # 이미지 주소

  temp = [] # 배우
  while(True):
    try:
      for p in range(1, 6):
        e = f'//*[@id="wrap"]/div[3]/div[1]/div[2]/table/tbody/tr[4]/td[2]/a[{p}]'
        ee = driver.find_element(By.XPATH, e).text
        temp.append(ee)
      temp = ",".join(temp)
    except:
      break
  actor.append(temp)

  aa = driver.find_element(By.XPATH, a).text
  bb = driver.find_element(By.XPATH, b).text
  cc = driver.find_element(By.XPATH, c).get_attribute('src')
  # 수정한 파트 !! 
  driver.switch_to.frame("iFrmContent") #iframe 페이지로 전환

  cont = driver.find_elements(By.CLASS_NAME, 'news')
  dd = cont[0].text # 작품설명
  if len(cont) > 1: # 줄거리 있는 경우
    ee = cont[1].text # 줄거리
  else:
    ee = '줄거리없음'

  date.append(aa)
  place.append(bb)
  image.append(cc) 

data1['기간'] = date
data1['장소'] = place
data1['이미지url'] = image
data1['배우'] = actor
data1['후기용url'] = url

# data1.to_csv("공연중_후기용_list.csv", index=False)
sum-k commented 1 year ago

공연중_상세정보_list.csv 현재공연중_후기.csv 개막예정_상세정보_list.csv