□ 상황
○ 사용자는 일일 시간별 매출 데이터를 웹 사이트에 직접 로그인하여 정보를 조회하고있음
○ 직접 로그인하지 않고 자동화하여 실시간으로 시간별 매출 데이터를 조회하고자함
□ 요구사항
○ 실시간 매출 데이터 추출/조회
○ 매출 데이터를 개인 구글 스프레드시트에 저장
○ 추출된 데이터를 주기적으로 카카오톡을 통해 알림받고 조회
○ 하루가 지나면 시간별 데이터 엑셀로 저장
□ 개발개요(위 그림에 기재된 번호 순서대로 기재함)
○ 함수정의 → 함수호출 → 사용자가 설정한 주기시간에 맞춰 코드진행
○ 크롤링
- 사용 라이브러리 : 셀레니움(Selenium)
→ 매출 데이터가 있는 웹사이트에 로그인 및 해당 페이지에서 출력되는 데이터를 추출하기 위해 사용
- 프로세스 : 로그인 페이지 접속 ▶ ID/PW 입력 ▶ 총 매출금액, 시간대별 매출금액 추출
- 구현코드
→ 셀레니움 구글 드라이버 실행시 웹 창 숨김처리 : options.add_argument("headless") # 창 숨기는 옵션 추가
# 브라우저 자동 꺼짐옵션지정
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
# 셀레니움옵션기능 활성화
options = webdriver.ChromeOptions()
options.add_argument("headless") # 창 숨기는 옵션 추가
print('드라이버 실행 / 창옵션 숨김 완료')
# 드라이버 변수 지정
core_driver = webdriver.Chrome(options=options)
# 접속 페이지 지정
core_driver.get("https://www.orderqueen.kr/backoffice_admin/login.itp")
→ 로그인 input 창에 ID, PW 자동입력 : core_driver.find_element(by='태그', value = '속성값').send_keys(변수값)
# 입력 : 아이디(.find_element, .send_keys) / find_element 중 id의 값이 id인 부분을 찾고 값을 입력
core_driver.find_element(by='id', value = 'userId').send_keys(per_id)
# 입력: 비밀번호(.find_element, .send_keys) / find_element 중 id의 값이 pw인 부분을 찾고 값을 입력
core_driver.find_element(by='id', value = 'pw').send_keys(per_pw)
→ 로그인 버튼 자동클릭 : core_driver.find_element(by = '태그', value = '속성값').click()
core_driver.find_element(by = 'id', value = 'btnLoginNew').click()
print('계정/비번 입력완료')
print('로그인 성공')
print(f'현재 url 주소\t:\t{core_driver.current_url}')
time.sleep(2)
→ 일자, 총 매출금액, 시간대별 매출금액 데이터 추출 : core_driver.find_element(By.태그, value = '태그값').text
# 추출 : 데이터
total_sale = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-kiosk"]/tbody[2]/tr/td[2]').text
print(f'{now} 누적매출액(당일기준)\t:\t{total_sale} 원')
p = 0
for v in range(1,25):
time_zone = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr['+ str(v) + ']/td[1]').text
sale_cnt = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr['+ str(v) + ']/td[3]').text
time_sale = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr[' + str(v) + ']/td[2]').text
time_sale_int = int(time_sale.replace(',',''))
p += time_sale_int
excel_sheet.append([now, time_zone, sale_cnt, time_sale, p])
print(f'시간대 : {time_zone}\t 판매건수 : {sale_cnt}\t 매출액 : {time_sale} 원\t 소계 : {p} 원')
print(f'{now} 데이터 갱신 완료 / 현시간까지 소계 : {p} 원')
○ 구글 스프레드시트 API
→ 구글스프레드시트 연동관련 세팅
# 구글스프레드시트 연동을 위한 사용자 세팅
my_gs_json = 'json 파일 위치'
gs_account_detail = gspread.service_account(my_gs_json) #사용자 계정 json 파일 사용 및 활성화
main_gs_sheet = '사용시트 url' #구글 사용시트 주소
useSheet = gs_account_detail.open_by_url(main_gs_sheet) #사용자 계정이 사용하고자하는 시트 url 설정
print('구글 스프레드시트 연동 성공')
* API 연동관련 아래 참조
→ 구글스프레드시트 업데이트
# 구글 엑셀시트 업데이트
my_sheet = useSheet.worksheet('일일 매출현황') #시트명과 동일하게 기재
my_sheet.update('a1','날 짜') #a열 1행 필드명 지정
my_sheet.update('b1','현재 매출') #b열 1행 필드명 지정
my_sheet.update(f'a{code_execution_cnt+1}', now) #회차수 = 행 순번 / 코드시행마다 값 추가
my_sheet.update(f'b{code_execution_cnt+1}', total_sale + '원')
○ 엑셀저장
→ 엑셀 세팅
# 엑셀파일 세팅
excel_data = openpyxl.Workbook() #엑셀파일 생성
excel_sheet = excel_data.active #데이터 적재 시트 지정 및 활성화
excel_sheet.column_dimensions['A'].width = 10 #엑셀 A열 너비 조정
excel_sheet.column_dimensions['B'].width = 10 #엑셀 B열 너비 조정
excel_sheet.column_dimensions['C'].width = 10 #엑셀 C열 너비 조정
excel_sheet.column_dimensions['D'].width = 10 #엑셀 D열 너비 조정
excel_sheet.column_dimensions['E'].width = 10 #엑셀 E열 너비 조정
excel_sheet.append(['오늘날짜', '시간대','판매건수','매출액','중간소계']) #열별 1 행 필드명 지정
print('엑셀파일 세팅 완료')
→ 엑셀 저장 및 종료 : excel_data.save('경로.xlsx'), excel_data.close()
# 엑셀저장
if code_execution_cnt == code_execution_max: #시행차수가 24회(execution_max)가되면 엑셀저장 및 기능 종료
excel_data.save('cureent_saleprice.xlsx')
excel_data.close()
print(f'{code_execution_cnt} 회차 시행완료 및 코드실행 종료')
exit()
○ 카카오톡 API
→ 토큰 callback
import requests
import json
url = 'https://kauth.kakao.com/oauth/token'
per_id = 'rest api 키'
redirect_url = '개인이 설정한 경로'
code = '리다이렉트된 키 입력'
data = {
'grant_type' : 'authorization_code',
'client_id' : per_id,
'redirect_url' : redirect_url,
'code' : code
}
#토큰 수신 및 덮어쓰기
response = requests.post(url, data=data)
tokens = response.json()
with open('token, json','w') as kakao: #받은 토큰 덮어쓰기 저장을 위해 코드작성
json.dump(tokens, kakao)
* API 연동관련 아래 참조
→ 토큰 use : 저장한 토큰을 읽어 다시 url 헤더 데이터로 담아 발신
import requests
import json
with open('token, json','r') as kakao:
tokens = json.load(kakao)
url="https://kapi.kakao.com/v2/api/talk/memo/default/send"
headers={
"Authorization" : "Bearer " + tokens["access_token"]
}
data={
"template_object": json.dumps({
"object_type":"text",
"text":"전송할 내용",
"link":{
"web_url":"www.google.com"
}
})
}
response = requests.post(url, headers=headers, data=data)
response.status_code
print(f'상태 : {response.status_code} ')
if response.json().get('result_code') == 0:
print('메시지를 성공적으로 보냈습니다.')
else:
print('메시지를 성공적으로 보내지 못했습니다. : ' + str(response.json()))
□ 코드전체
# 필요 라이브러리 호출
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options #자동꺼짐방지옵션 라이브러리
from datetime import datetime
import openpyxl #엑셀활용위해 사용
import schedule #주기적실행을 위해 설정
import time #타임설정
import gspread #구글스프레드시트 연동을 위한 라이브러리
import requests #카카오톡 파싱을 위한 라이브러리
import json #카카오톡 json 파일을 위한 라이브러리
# □■□■□■□■ 주기적으로 코드실행을 위한 변수
code_execution_cnt = 0
code_execution_max = 24 #24시간 기준으로 24지정
# □■□■□■□■ 함수정의
def action_start():
# 전역변수 선언 및 회수출력
global code_execution_cnt
code_execution_cnt += 1
print(f'{code_execution_cnt}회차 시작')
# 구글스프레드시트 연동을 위한 사용자 세팅
my_gs_json = 'json 파일 경로'
gs_account_detail = gspread.service_account(my_gs_json) #사용자 계정 json 파일 사용 및 활성화
main_gs_sheet = '사용시트 url' #구글 사용시트 주소
useSheet = gs_account_detail.open_by_url(main_gs_sheet) #사용자 계정이 사용하고자하는 시트 url 설정
print('구글 스프레드시트 연동 성공')
# 엑셀파일 세팅
excel_data = openpyxl.Workbook() #엑셀파일 생성
excel_sheet = excel_data.active #데이터 적재 시트 지정 및 활성화
excel_sheet.column_dimensions['A'].width = 10 #엑셀 A열 너비 조정
excel_sheet.column_dimensions['B'].width = 10 #엑셀 B열 너비 조정
excel_sheet.column_dimensions['C'].width = 10 #엑셀 C열 너비 조정
excel_sheet.column_dimensions['D'].width = 10 #엑셀 D열 너비 조정
excel_sheet.column_dimensions['E'].width = 10 #엑셀 E열 너비 조정
excel_sheet.append(['오늘날짜', '시간대','판매건수','매출액','중간소계']) #열별 1 행 필드명 지정
print('엑셀파일 세팅 완료')
# 기본값 변수지정
per_id = '로그인 ID'
per_pw = '로그인 PW'
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
now_YMD = datetime.now().strftime('%Y-%m-%d')
# 브라우저 자동 꺼짐옵션지정
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
# 셀레니움옵션기능 활성화
options = webdriver.ChromeOptions()
options.add_argument("headless") # 창 숨기는 옵션 추가
print('드라이버 실행 / 창옵션 숨김 완료')
# 드라이버 변수 지정
core_driver = webdriver.Chrome(options=options)
# 접속 페이지 지정
core_driver.get("https://www.orderqueen.kr/backoffice_admin/login.itp")
# 입력 : 아이디(.find_element, .send_keys) / find_element 중 id의 값이 id인 부분을 찾고 값을 입력
core_driver.find_element(by='id', value = 'userId').send_keys(per_id)
# 입력: 비밀번호(.find_element, .send_keys) / find_element 중 id의 값이 pw인 부분을 찾고 값을 입력
core_driver.find_element(by='id', value = 'pw').send_keys(per_pw)
time.sleep(1)
core_driver.find_element(by = 'id', value = 'btnLoginNew').click()
print('계정/비번 입력완료')
print('로그인 성공')
print(f'현재 url 주소\t:\t{core_driver.current_url}')
time.sleep(2)
# 추출 : 데이터
total_sale = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-kiosk"]/tbody[2]/tr/td[2]').text
print(f'{now} 누적매출액(당일기준)\t:\t{total_sale} 원')
p = 0
for v in range(1,25):
time_zone = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr['+ str(v) + ']/td[1]').text
sale_cnt = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr['+ str(v) + ']/td[3]').text
time_sale = core_driver.find_element(By.XPATH, value = '//*[@id="tbl-time"]/tbody[1]/tr[' + str(v) + ']/td[2]').text
time_sale_int = int(time_sale.replace(',',''))
p += time_sale_int
excel_sheet.append([now, time_zone, sale_cnt, time_sale, p])
print(f'시간대 : {time_zone}\t 판매건수 : {sale_cnt}\t 매출액 : {time_sale} 원\t 소계 : {p} 원')
print(f'{now} 데이터 갱신 완료 / 현시간까지 소계 : {p} 원')
# 구글 엑셀시트 업데이트
my_sheet = useSheet.worksheet('일일 매출현황') #시트명과 동일하게 기재
my_sheet.update('a1','날 짜')
my_sheet.update('b1','현재 매출')
my_sheet.update(f'a{code_execution_cnt+1}', now) #회차수 = 행 순번 / 코드시행마다 값 추가
my_sheet.update(f'b{code_execution_cnt+1}', total_sale + '원')
#카카오톡
with open('token, json','r') as kakao:
tokens = json.load(kakao)
url="https://kapi.kakao.com/v2/api/talk/memo/default/send"
headers={
"Authorization" : "Bearer " + tokens["access_token"]
}
data={
"template_object": json.dumps({
"object_type":"text",
"text":f"{now} / 현재 매출액 : {total_sale} 원",
"link":{
"web_url":"연결 url"
}
})
}
response = requests.post(url, headers=headers, data=data)
response.status_code
print(f'상태 : {response.status_code} ')
if response.json().get('result_code') == 0:
print('메시지를 성공적으로 보냈습니다.')
else:
print('메시지를 성공적으로 보내지 못했습니다. 오류메시지 : ' + str(response.json()))
# 엑셀저장
if code_execution_cnt == code_execution_max: #시행차수가 24회(execution_max)가되면 엑셀저장 및 기능 종료
excel_data.save('cureent_saleprice.xlsx')
excel_data.close()
print(f'{code_execution_cnt} 회차 시행완료 및 코드실행 종료')
exit()
#--------------------------------------------------------함수정의 끝--------------------------------------------------------
# □■□■□■□■ 함수실행
# 1초에 한번씩 함수 실행 schedule.every(1).seconds.do(함수)
# 1분에 한번씩 함수 실행 schedule.every(1).minutes.do(함수)
# 2시간에 한번씩 함수 실행 schedule.every(1).hours.do(함수)
schedule.every(1).hours.do(action_start) # 1시간 마다 action_start 함수 실행
while True:
schedule.run_pending() # 함수 실행 메서드 .run_pending()
if code_execution_cnt == code_execution_max: # 코드 시행 회수가 24이상되면 실행 멈춤
break
'Portfolio & Toy-Project' 카테고리의 다른 글
프로젝트 : 부산항만공사 서비스 제안관련 데이터분석-1 (0) | 2024.03.11 |
---|---|
판다스 : .melt() 함수1 (0) | 2024.02.07 |
청소년 우울증(18년도, 22년도) : 연속 시각화(파이형그래프) 차트 생성 및 배치 (1) | 2024.02.07 |
타이타닉 데이터 전처리 및 시각화 (1) | 2024.02.06 |
임의 페이지 텍스트 크롤링 및 엑셀저장 (1) | 2024.01.30 |