# -*- coding: utf-8 -*-
"""
Created on Thu Jul 8 11:20:51 2021
@author: hs-702
"""
# Selenium 이용한 실습
# K-stat (https://stat.kita.net/) 국내통계>>품목수출입>>100개씩보기
import pandas as pd
from selenium import webdriver
from bs4 import BeautifulSoup
import time
import shutil
import os, sys
url = 'https://stat.kita.net/main.screen'
driver = webdriver.Chrome('C:/Users/hs-702/Desktop/veroro/chromedriver_win32/chromedriver.exe') # 빈 브라우저 띄움
defalt_next_page_tag_path = "/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/"
driver.get(url) # url 접속
from selenium.webdriver.support.ui import Select
# 국내통계 링크를 x+path로 접근
driver.find_element_by_xpath("/html/body/div[2]/div[1]/div/div[2]/ul/li[1]/a/img").click()
# 픔목수출입 링크를 x+path가 아닌 텍스트로 접근
driver.find_element_by_link_text("품목 수출입").click()
# 표시행수선택
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[2]/form/div[1]/div/select").click()
select = Select(driver.find_element_by_id('listCount')) # select를 쓰려면 import Select를 해줘야 함
select.select_by_value('100') # select.click()을 하면 'NoneType' object has no attribute 'click' 에러발생
# 조회버튼클릭
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[2]/form/fieldset/div[3]/a/img").click()
time.sleep(2)
# bs로 parsing
bs = BeautifulSoup(driver.page_source,'html.parser')
time.sleep(2)
total_page = bs.find('span',{'id':'total_count'}).get_text()
total_page= int(total_page.replace(',',''))
# print(total_page)
# 다음페이지로 넘어가기
# 5,291
# /html/body/div[2]/div[2]/div[2]/div[2]/form/div[1]/dl[1]/dd/span
# pages = int(total_count)/100
# 현재페이지 HTML속성값: "selected">숫자
# 다음페이지 버튼 상대경로: /html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/a[숫자]
# 다음페이지 버튼 HTML속성값:
# nextpage = driver.find_element_by_class_name('doPagingSearch') >>> 속성값이라서 따로 숫자만 빼서 이와 같이 사용할 수 없음
# 해당 URL에서 파일을 다운받고 특정 폴더에 이동시켜 파일 이름을 규칙에 맞게 순차적으로 변경시키시오 (file_1부터 file_53까지)
# shutill.move(path + 'A', path + 'B')>> 파일을 다운 받은 A경로에서 B경로로 파일을 이동하시오
# os.rename(path A, path B) >> 파일이름을 다음과 같이 변경시키시오 (파일확장자까지 써야함)
# 다운로드 링크 상대주소 : /html/body/div[2]/div[2]/div[2]/div[2]/form/div[1]/div/a[1]
# 다운로드 링크 속성값 :
default_path = '/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/a'
pages = int((total_page/100)+1)
# pages = 53
counter = 0
for page in range(1, pages):
if (page % 10) != 0:
var = page % 10
time.sleep(2)
# 한 페이지에 존재하는 엑셀파일 다운로드 후 shutill 이용해서 폴더 옮기기
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[2]/form/div[1]/div/a[1]").click()
time.sleep(3)
shutil.move('C:/Users/hs-702/Downloads' + '/K-stat 총괄 .xls', 'C:/Users/hs-702/Desktop/veroro' + '/fileDir')
time.sleep(2)
# os.rename을 이용해서 파일명을 1부터 53까지 순차적으로 변환하기
file_name = 'kstat_' + str(counter) + '.xls'
#time.sleep(3)
os.rename('C:/Users/hs-702/Desktop/veroro' + '/fileDir/K-stat 총괄 .xls', 'C:/Users/hs-702/Desktop/veroro' + '/fileDir/' + file_name)
#time.sleep(3)
counter = counter + 1
#time.sleep(3)
# 다음 페이지를 클릭하기
nextpage = driver.find_element_by_xpath(default_path +'[' + str(var) + ']')
nextpage.click()
#time.sleep(3)
else:
nextpage = driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/a[2]')
nextpage.click()
time.sleep(3)
'''
Xpath의 상대주소 숫자값은 [1]-[9]까지이며 클릭하고 있는 해당 페이지는 a[숫자]대신 strong이다.
/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/a[1]
/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/strong
다음페이지 화살표의 상대주소 값은 다음과 같다
/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/a[2]
page의 range가 1부터 53까지 간다면 다음과 같은 에러가 뜬다.
NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/span/a[10]"}
(Session info: chrome=91.0.4472.124)
이 문제를 해결하기 위해 1~53까지의 페이지에서 나머지가 1~9까지 나오는 행위를 반복시키는 코드를 짜야한다.
'''
# 데이터를 다운받고 폴더와 이름을 바꿀 때, 파일자체가 없거나 파일내용이 없을 때 예외처리가 필요하다.
#pd.remove('C:\Users\hs-702\Desktop\veroro\fileDir\kstat_0.xls) >> 잘못된 파일을 삭제한다.
#pd.read_excel('C:\Users\hs-702\Desktop\veroro\fileDir\kstat_0.xls') >> 판다스를 활용해서 데이터사이즈를 볼 수 있다.
# try, except, pass 문을 사용하게되면 특정 페이지의 파일을 받지 못하는 문제가 발생하게 된다.
# 또한 counter+1 이 except 전에 실행되므로 에러발생을 제외하고 파일은 순차적으로 받아지지만 53페이지 파일 중 49개 만 받게 되는 문제가 발생한다.
# 실습시간이 부족해서 예외처리 이후의 실습은 선생님 답을 참고하도록 한다.
'''
print(temp, shape)
shape[0]은 row값, shape[1]은 column값
for page in range(1, pages):
if (page % 10) != 0:
var = page % 10
time.sleep(2)
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[2]/form/div[1]/div/a[1]").click()
time.sleep(3)
try:
temp = pd.read_excel('C:/Users/hs-702/Downloads/K-stat 총괄 .xls')
shutil.move('C:/Users/hs-702/Downloads' + '/K-stat 총괄 .xls', 'C:/Users/hs-702/Desktop/veroro' + '/fileDir')
time.sleep(2)
file_name = 'kstat_' + str(counter) + '.xls'
os.rename('C:/Users/hs-702/Desktop/veroro' + '/fileDir/K-stat 총괄 .xls', 'C:/Users/hs-702/Desktop/veroro' + '/fileDir/' + file_name)
counter = counter + 1
nextpage = driver.find_element_by_xpath(default_path +'[' + str(var) + ']')
nextpage.click()
except (FileNotFoundError):
pass
except temp.shape[0]<5 or temp.shape[1]!=13:
pass
else:
nextpage = driver.find_element_by_xpath('/html/body/div[2]/div[2]/div[2]/div[2]/form/div[4]/div/a[2]')
nextpage.click()
time.sleep(3)
'''
# 다운로드받은 파일을 전처리가 된 하나의 큰 데이터프레임으로 만든다
# 중복되는 헤더정보 제거, K-stat 총괄 column 없애기, unnamed된 column 이름을 바꾼다.
# Merge된 column은 DF에서 읽을 수 없다.
'''
#시작 디렉터리부터 시작하여 그 하위 모든 디렉터리를 차례대로 방문
temp = os.walk ('C:/Users/hs-702/Desktop/veroro/fileDir')
# 파일디렉터리의 idx와 row를 차례대로 프린트해서 보기.
for idx, row in enumerate(temp):
print(idx)
print(row)
# print(row)를 해보면 다음과 같은 결과를 얻는다.
'''
('C:/Users/hs-702/Desktop/veroro/fileDir2', [],
['kstat_0.xls', 'kstat_1.xls', 'kstat_10.xls', 'kstat_11.xls', 'kstat_12.xls', 'kstat_13.xls', 'kstat_14.xls',
'kstat_15.xls', 'kstat_16.xls', 'kstat_17.xls', 'kstat_18.xls', 'kstat_19.xls', 'kstat_2.xls', 'kstat_20.xls',
'kstat_21.xls', 'kstat_22.xls', 'kstat_23.xls', 'kstat_24.xls', 'kstat_25.xls', 'kstat_26.xls', 'kstat_27.xls',
'kstat_28.xls', 'kstat_29.xls', 'kstat_3.xls', 'kstat_30.xls', 'kstat_31.xls', 'kstat_32.xls', 'kstat_33.xls',
'kstat_34.xls', 'kstat_35.xls', 'kstat_36.xls', 'kstat_37.xls', 'kstat_38.xls', 'kstat_39.xls', 'kstat_4.xls',
'kstat_40.xls', 'kstat_41.xls', 'kstat_42.xls', 'kstat_43.xls', 'kstat_44.xls', 'kstat_45.xls', 'kstat_46.xls',
'kstat_47.xls', 'kstat_48.xls', 'kstat_49.xls', 'kstat_5.xls', 'kstat_50.xls', 'kstat_51.xls', 'kstat_52.xls',
'kstat_6.xls', 'kstat_7.xls', 'kstat_8.xls', 'kstat_9.xls'])
'''
# row[2]는 row의 3번째 element인 kstat_1.xls부터 kstat_52.xls까지의 파일 이름들을 의미한다.
# 하지만 character순서로 정렬되어 있어서 0, 1, 10~19, 2, 20~29, 3, 30~39, 4, 40~49, 5, 50~52, 6, 7, 8, 9.xls 순서가 된다.
# total에는 read_excel 메서드를 사용해서 파일 경로안의 파일을 업로드함 (파일이름의 string값이 들어간다.)
total = []
for row in row[2]:
print(row)
total.append(pd.read_excel('C:/Users/hs-702/Desktop/veroro/fileDir2/' + row))
# pd.concat는 각각의 DF를 기하학적으로 붙이는 기능을 한다.
# concat에서 축정보를 주지 않으면 세로로 붙인다. DF를 붙일 때는 각 DF의 row/column명이 일치해야 한다.
# 그래서 total.append하기 전에 column명에 이름을 먼저 주고 같은형식으로 append를 하는 것이 좋다.
# test1: total의 index 2, 3 row가 pd.concat로 세로연결되어 있음을 볼 수 있다.
test1 = pd.concat([total[1], total[2]])
# test2와 3은 total의 index 2 row의 전처리 전후 과정을 나타낸다. (test3 = 2열부터 끝까지 모든 데이터)
test2 = total[1]
test3 = test2.iloc[:,1:]
# test4는 전처리된 test3의 column명을 코드로 바꾼 것이다.
test4 = test3.rename(columns = {'Unnamed: 1': '코드'})