본문 바로가기

⚙️ 직장인의 파이썬

[직장인의 파이썬] 셀레니움을 활용해 출장경비 결산 증빙자료 자동화하기

반응형

직장인은 회사를 다니면서 이곳저곳 출장을 다녀야 한다

 

나도 출장을 다니고 있다

 

회사마다 다르지만 출장 가는 것은 가끔씩은 사무실을 벗어나서 리프레쉬가 되기도 하지만

시간도 많이 들여야 하고 내근할때보다 몸이 고되다

 

 

출장을 서로 미루는 직장인들

 

출장가기전 다녀오고 난 후 출장명령지, 기안문 등 처리해야할 서류도 많다

 

출장경비도 이런 정신없는 와중에 처리해야 한다

 

출장지가 많고, 들린곳이 많고, 비용을 많이 사용했으면

그에 따른 출장경비 자료를 취합해서 회사에 제출하는 것도 시간을 엄청 잡아 먹는다

 

회사일은 하기가 싫다 ㅋㅋㅋㅋㅋㅋㅋ

 

회사마다 증빙 제출 자료나 양식이 다르지만

 

필자의 경우에는 공무원 여비규정에 따라서 회사 지침을 만들었기 때문에

 

우선

1) 네이버나 다음 지도 최단거리 캡처본

2) 통행비

3) 유류비

 

을 엑셀로 정리해서 정산을 청구한다

 

출장지가 많을 경우

 

엑셀로 시작점과 목적지를 연번으로 정리를 해두면

 

위에 관련된 내용을

 

파이썬 셀레니움으로 자동화해서 호로로로록 정리를 해준다

 

전체 코드는 아래 코드박스와 같고 중간중간 필요한 부분이나 내용을 커스텀화해서 사용하여

도움을 많이 받았으면 좋겠음

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 openpyxl import load_workbook

import pyautogui
import time



driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.maximize_window()


# 엑셀 불러오기
wb = load_workbook(r'C:\Users\user01\Desktop\출장자료\출장내역.xlsx')
ws = wb.active

# 마지막 행(ROW) 찾기
MaxRow = int(ws.max_row)
print(MaxRow)

# 마지막 까지 반복하기
for i in range(2, MaxRow) :

    # 엑셀이 중간에 빈값이면 PASS 
    if ws[f'A{i}'].value is None :
        print(f'{i}열은 None Type')
        continue
        
    # (출발지/도착지) 변수 선언
    start = ws[f'A{i}'].value
    arrival = ws[f'B{i}'].value

    print(ws[f'A{i}'].value)
    print(ws[f'B{i}'].value)


    # 1. 지도 이동
    driver.get('https://map.naver.com/v5/?c=15,0,0,0,dh')
    WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "/html/body/app/layout/div[3]/div[1]/navbar/perfect-scrollbar/div/div[1]/div/ul/li[2]/a/span")))

    # 2. 길찾기 클릭
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[1]/navbar/perfect-scrollbar/div/div[1]/div/ul/li[2]/a/span').click()
    WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div[1]/directions-search/div[1]/directions-search-box[1]/div/div/div[1]/input")))


    # 3. 출발지 입력 
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div[1]/directions-search/div[1]/directions-search-box[1]/div/div/div[1]/input').click()
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div[1]/directions-search/div[1]/directions-search-box[1]/div/div/div[1]/input').send_keys(start)
    time.sleep(0.6)
    pyautogui.press('enter')
    time.sleep(1.5)

    # 4. 도착지 입력
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div[1]/directions-search/div[1]/directions-search-box[2]/div/div/div[1]/input').click()
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div[1]/directions-search/div[1]/directions-search-box[2]/div/div/div[1]/input').send_keys(arrival)
    time.sleep(0.6)
    pyautogui.press('enter')
    time.sleep(1.5)

    # 5. 길찾기 클릭
    driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div/directions-search/div[2]/button[2]').click()

    # 5.1. [최적] 단어 대기
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div/directions-search/div[2]/button[2]')))
    time.sleep(1.5)

    # 6. 자동차 길찾기 클릭
    driver.find_element(By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div/ul/li[2]/a').click()
    time.sleep(0.5)
    driver.find_element(By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/div/ul/li[2]/a').click()

    # 6.1. [차종/연료] 대기
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/directions-summary-list/directions-summary-list-tab/div/directions-summary-fuel-type/div/button')))
    time.sleep(1.5)

    # 7. 거리 / 통행료 / 연료비 가져오기
    Distance = driver.find_element(By.XPATH, '//*[@id="container"]/shrinkable-layout/div/directions-layout/directions-result/div[1]/directions-summary-list/directions-hover-scroll/div/ul/li[1]/directions-summary-item-car/directions-summary-item-car-card/div[1]/div[1]/span/readable-distance').get_attribute('innerText')
    Fee = driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/directions-summary-list/directions-hover-scroll/div/ul/li[1]/directions-summary-item-car/directions-summary-item-car-card/div[1]/div[2]/ul/li[2]').get_attribute('innerText')
    Fuel = driver.find_element(By.XPATH, '/html/body/app/layout/div[3]/div[2]/shrinkable-layout/div/directions-layout/directions-result/div[1]/directions-summary-list/directions-hover-scroll/div/ul/li[1]/directions-summary-item-car/directions-summary-item-car-card/div[1]/div[2]/ul/li[3]/span').get_attribute('innerText')

    print(Distance)
    print(Fee)
    print(Fuel)


    # 8. 엑셀에 저장 
    ws[f'C{i}'] = Distance
    ws[f'D{i}'] = Fee.replace('통행료 ', '').replace(' ', '')
    ws[f'E{i}'] = Fuel

    wb.save(r'C:\Users\user01\Desktop\출장자료\출장내역.xlsx')


    # 9. 스크린샷 저장
    image = pyautogui.screenshot(f'C:\\Users\\user01\\Desktop\\출장자료\\출장지{start}_{arrival}.png')


# 브라우저 종료
driver.quit()

 

 

 

반응형