파이썬을 사용해서 키보드와 마우스를 제어할 수 있는 방법을 설명한다.

자동화의 필요성 그리고 파이썬

인간의 삶 자체가 반복의 연속이 아닐까 생각한다. 일어나서 밥먹고 일하고 운동하고 씻고 자고. 이러한 반복되는 일들을 자동화할 수 있다면, 남은 시간을 좀더 창의적인 일을 하는데 사용할 수 있지 않을까?
일 또한 마찬가지여서, 단순 반복되는 작업이 최소 절반이상은 될 것이다. 파이썬을 접하지 못했다면, 지금쯤 정신적으로나 육체적으로 피폐해져있을 것이다.

내가 파이썬 이라는 프로그래밍 언어를 처음 접한 것은 20여년 전으로 거슬러 올라간다. 당시 광운대에서 파이썬 공개세미나가 있었는데, 여러가지 세션들이 진행되었고 지금 기억에 남는 것 문구가 있었는데, 파이썬은 3.5 세대 언어라는 것이었다. 당시만 해도 파이썬은 아주 생소한 언어였고, 자바가 대세인 상황이었다. 3세대인 자바보다 한 단계 위인 3.5 세대라니.

명령어줄에서 간단하게 실행할 수 있는 인터프리터 언어라는 점과 간단한 계산기로도 사용할 수 있겠다는 생각, 딱 거기까지였다. 작년 말, 코로나로 인해 국내에 강제 귀국을 한 후, 인터넷 서점을 둘러보니 그야말로 파이썬은 대세가 되어있었다.

개발환경 만들기

뒤에서 설명할 파이썬 자동화 코드를 실행하기 위해서는 파이썬 컴파일러와 실행환경을 구축해야 한다. 여기서는 windows 환경을 기준으로 설명하겠다.

https://www.anaconda.com/products/individual 에 접속하여 Anaconda(아나콘다) 최신버전을 다운받아 설치한다. 컴파일러와 개발환경까지 포함되어 있어 별도의 설정이 필요없다. 정상적으로 설치를 마쳤다면, Jupyter notebook(Anaconda3) 라는 아이콘이 시작버튼에 보일 것이다.

IDE 의 웹버전이라고 생각하면 될 것이다. 실행하면 자동으로 브라우저가 뜨고 로컬의 파일과 디렉토리 구조를 보여준다. http://localhost:8888/tree 에 접속하면 로컬 디렉토리 구조가 표시되고 원하는 경로에 가서 코드를 입력하고 바로 실행해볼 수 있다.

자동화 코드

파이썬은 여러가지 분야에서 다양하게 사용된다. 이 중에서 키보드와 마우스를 제어할 수 있는 pyautogui 라이브러리를 제공한다. https://wikidocs.net/85581https://pyautogui.readthedocs.io/en/latest/ 에서 자세한 설명과 예제를 확인할 수 있다.
먼저 라이브러리를 아래와 같이 설치한다.

pip install pyautogui

코드를 작성하기 전에 어떤 작업을 자동화할 것인가를 정해야 한다.

  • 사용빈도가 높은가?
  • 별도의 프로그램 기반인가? 브라우저 기반인가?
  • 대상이 단일한 프로그램인가? 여러개의 서로 다른 프로그램인가?

결정했다면, 작업에 따른 키보드와 마우스의 동작 순서를 참고하여 프로그래밍해야 한다. 예제코드를 이용해서 여러번의 테스트가 필요하다.

한번의 마우스 또는 키보드 동작이 이뤄지면, 반드시 지연함수(time.sleep)를 사용해야 한다. 일반적인 프로그램은 사람의 실제 입력속도를 예상하고 만들어졌기 때문에, 지연없이 입력값이 들어갈 경우, 예상과는 다른 동작이 발생할 수 있다. 오랜 시간을 지연할 수록 이러한 문제는 줄어들겠지만, 자동화하는 의미가 없을 수 있기 때문에 적당한 선에서 타협해야 한다.

마우스보다는 키보드로 제어하는 편이 오류를 줄일 수 있다. 자동화 대상 프로그램이 키보드로 제어(방향키, 단축키등)가 가능한지 확인한다. 만일 지원하지않는다면, 마우스로 일일이 지정해야 한다.

코드가 실행도중에 카톡 메세지가 오거나 새로운 팝업 창이 뜬다면, 제대로된 결과를 얻기 어렵다. 따라서 코드를 실행할 때는 메신저 프로그램을 로그아웃하고 종료하는 것이 좋다.
또한 프로그램 창의 위치와 크기를 일정하게 맞추는 것이 좋다. 이제 예제코드를 통해 사용법을 익히도록 하자.

마우스를 제어하기 위해서는 화면의 x,y 좌표값을 알아야한다. 본체 모니터에 대해서만 좌표 값을 알 수 있으며 만일 확장모니터를 사용한다면, 좌표값을 확인할 수 없다.
아래 코드를 입력하고 실행해보자.

import pyautogui
import time
time.sleep(5)
x,y = pyautogui.position()
print('x={0}, y={1}'.format(x,y))

5초 후에 마우스 포인터가 위치한 지점의 좌표값을 출력한다.

날마다 발생하는 거래처 상품별 매출내역을 파일로 생성하는 코드다. 아주 유용하게 사용하고 있다.

import pyautogui
import time
time.sleep(10)
 
for i in range(35):
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=648, y=260, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.press('backspace')
    time.sleep(0.6)
    pyautogui.press('backspace')
    time.sleep(0.6)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.press('f12')
    time.sleep(1)
    pyautogui.press('f6')
    time.sleep(1)
    pyautogui.press('n')
    time.sleep(1)    
    pyautogui.click(x=1415, y=16, button='right', clicks=1)
    time.sleep(1)
    pyautogui.press('right')
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=1518, y=557, button='right', clicks=1)
    time.sleep(1)
    pyautogui.press('pageup')
    time.sleep(0.6)
    pyautogui.press('f2')
    time.sleep(0.6)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.click(x=1415, y=16, button='right', clicks=1)
    time.sleep(1)
    pyautogui.press('left')
    time.sleep(1)

아래 사진은 프로그램이 실행될 각 윈도우 창의 위치다.

  1. 총 3개(포스관리프로그램, 거래처매출분석 엑셀프로그램, 엑셀저장디렉토리) 창을 위 사진처럼 띄워놓는다.
  2. 포스관리프로그램은 [거래처별]매출분석 메뉴를 실행해놓고, 거래처상품 탭을 선택해놓는다.
  3. 매출날짜 기간을 설정한다. 거래처매출분석(엑셀) 파일은 거래처명 컬럼(C0)을 선택해놓는다.
  4. 엑셀저장디렉토리(C:\Program Files (x86)\TIPS\EXCEL)창은 수정한 날짜 항목을 클릭하여 나중에 생성된 것이 위로 가도록 설정한다.
  5. 프로그램을 실행하고, 엑셀프로그램 창을 활성화한다.

다수에게 같은 내용의 문자를 보내는 것은 쉽다. 하지만 각기 다른 내용의 문자를 보내야 한다면, 일일이 수작업으로 하는 방법밖에는 없다. 아래 코드 역시 유용하다.

import pyautogui
import time
time.sleep(10)
 
for i in range(32):
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=1119, y=742, button='right', clicks=1)
    time.sleep(1)
    pyautogui.click(x=1546, y=735, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.click(x=507, y=305, button='right', clicks=2, interval=1)
    time.sleep(1)
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.click(x=130, y=374, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','a')
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=1457, y=950, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.click(x=1541, y=82, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','a')
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=1457, y=950, button='right', clicks=1)
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.click(x=1124, y=18, button='right', clicks=1)
    time.sleep(1)

위 코드에서 좌표값이 들어가는 곳은 총 8군데다. 각 윈도우의 위키가 바뀐다면, 그때그때 수정되어야 하고 값들은 다음과 같다.

  1. 순서 있는 목록문자 브라우저의 채팅시작 버튼 위치
  2. 문자 브라우저에서 거래처코드를 입력할 위치
  3. 정산 데이터 엑셀 피벗테이블의 역삼각형 위치
  4. 정산 데이터 엑셀시트 정산데이터(5/1~5/9) 셀의 위치(정산 내역을 복사하기 위함)
  5. 문자 브라우저의 내용을 입력할 위치(정산내역 캡처하여 첨부하기 위함)
  6. 안녕하세요 문구가 입력된 메모장의 줄 위치
  7. 5번과 동일한 위치임(문구를 내용에 추가하기 위함)
  8. 위 그림의 2번 윈도우의 위치(창 제목 위치)

아래 사진은 프로그램이 실행될 각 윈도우 창의 위치다.

  1. 순서 있는 목록먼저 정산서를 피벗테이블을 이용해서 만든다(1번 윈도우). 위 그림을 참조한다. 작성 후, 몇 가지 수정작업을 해야 한다.
  2. 필터가 포함된 셀의 크기가 수시로 변하기 때문에 이를 고정시켜야 한다. 피벗테이블의 셀을 선택하고 오른쪽버튼을 눌러 팝업메뉴에서 피벗테이블 옵션 을 선택한다.
  3. 레이아웃 및 서식 탭의 아래에 업데이트 시 열 자동 맞춤 옵션을 선택 해제한다.
  1. 순서 있는 목록정산서를 보내야하는 거래처코드가 적힌 리스트를 엑셀파일에 작성한다.
  1. 순서 있는 목록정산서와 함께 전송할 텍스트 파일을 메모장에 작성한다.
문자내용
안녕하세요. 괴산로컬푸드직매장입니다. 위와 같이 정산내역서(4월26일~4월30일)를 보내드립니다. 감사합니다.
문자내용
안녕하세요. 괴산로컬푸드직매장입니다. 위와 같이 정산내역서(5월1일~5월31일)를 보내드립니다. 세금계산서 발행을 부탁드립니다. 감사합니다.
  1. 순서 있는 목록문자메세지를 보내기 위한 브라우저를 띄운다(https://messages.google.com/web/conversations)

코드를 실행하고 난 후, 마우스 포인터를 2번 윈도우의 A1 로 선택한다.

각 생산자별로 만든 엑셀파일을 구글드라이브에 업로드하고 각 파일에 대한 경로를 추출하기 위한 작업을 자동화하는 코드다.

import pyautogui
import time
time.sleep(10)
 
for i in range(128):    
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.press('apps')
    time.sleep(1)
    pyautogui.press('down')
    time.sleep(0.2)
    pyautogui.press('down')
    time.sleep(0.2)
    pyautogui.press('enter')
    time.sleep(1.5)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('tab')
    time.sleep(0.2)
    pyautogui.press('enter')
    time.sleep(1)
    pyautogui.click(x=1417, y=21, button='right', clicks=1)    ---- (1)
    time.sleep(1)
    pyautogui.press('down')
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)
    pyautogui.click(x=1125, y=513, button='right', clicks=1)      ---- (2)
    time.sleep(1)

각각의 위치 정보는 아래 번호와 같다.

  1. 순서 있는 목록오른쪽 엑셀 창 제목표시줄의 위치
  2. 왼쪽 크롬 창의 ‘구글 드라이브’ 의 오른쪽 공백(아무 곳이나 상관없음)

크롬창의 선택 포인트는 숫자로 정렬한 상태에서 가장 위의 엑셀시트를 선택해놓는다.
엑셀시트는 가장 ‘스프레드시트 주소’ 컬럼(1번 열)을 선택해 놓는다. 스크립트는 크롬 창에서 먼저 실행되니, 크롬창을 활성화한다.

<주간 정산(6월 28일 ~ 7월 4일) 관련하여 공지드립니다>
이번주 주간 정산(6월 28일 ~ 7월 4일) 관련하여 공지드립니다. 한 주에 6월 말과 7월 초가 포함되어 있는 관계로, 6월 28일부터 6월 30일 까지 3일간의 정산내역서와 7월 1일부터 7월 4일까지의 4일간의 정산내역서를 각각 보내드릴 예정입니다.
정산 후 지급 금액은 평소와 같이 내일(7월 7일 수요일) 입금될 예정입니다. 참고 부탁드립니다.


<주간 정산(7월 26일 ~ 8월 1일) 관련하여 공지드립니다>
이번주 주간 정산(7월 26일 ~ 8월 1일) 관련하여 공지드립니다. 한 주에 7월 말과 8월 초가 포함되어 있는 관계로, 7월 26일부터 7월 31일까지 6일간의 정산을 하고, 8월 1일은 차주 정산 시, 총 8일간(8월 1일 ~ 8월 8일) 내역을 정산해드릴 예정입니다. 참고 부탁드립니다.

#-*- coding: utf-8 -*- 
"""
Author : Byunghyun Ban
GitHub : https://github.com/needleworm
Book : 6���� ġ ������ �Ϸ� ���� ������ ���� �ڵ�ȭ
Last Modification : 2020.02.13.
"""
import time
import os
import pyexcel as px
import sys
 
# �۾� ���� �޽����� ����մϴ�.
print("Process Start")
 
# ���� ������ �ð��� ����մϴ�.
start_time = time.time()
 
# ������ �м��� ��ĥ ���ϵ��� ����� ���� �̸��� �ý������κ��� �Է¹޽��ϴ�.
directory = sys.argv[1]
 
# ������� ������ ������ �����մϴ�.
out_dir ="merged_" + directory
if out_dir not in os.listdir():
    os.mkdir(out_dir)
 
# ������ ���빰�� ������ ����� �����մϴ�.
input_files = os.listdir(directory)
 
# ������� ������ ����Ʈ�� ����ϴ�.
HEADERS = []
 
# ���� ������� ������ ����Ʈ�� ����ϴ�.
CONTENTS = []
 
# input_files�� ����� ���� �̸��� �� ���� �ϳ��� �ҷ��ɴϴ�.
for filename in input_files:
    # ��Ȥ xlsx ������ �ƴ� ������ �������� �� �ֽ��ϴ�. �̰� �ɷ����ϴ�.
    if ".xlsx" not in filename:
        continue
 
    # ���� ������ �´ٸ�, ������ ����Ʈ ���·� �о�ɴϴ�.
    file = px.get_array(file_name=directory + "/" + filename)
 
    # ���� ������ ù ��° ��, �׷��ϱ� ����� �ҷ��ɴϴ�.
    header = file[0]
    content = file[1:]
 
    # �ҷ��� ������ ����� �̹� �о�Դ� ���ϰ� ��ġ�ϴ��� �м��մϴ�.
    # �Ʒ� �ڵ�� ���ο� ����� �߰ߵ� ������ �۵��մϴ�.
    if header not in HEADERS:
        # ó�� �߰ߵ� ������ ����� �Ӵϴ�.
        HEADERS.append(header)
        # ����� ���� ���ø� ����Ʈ�� �����Ͽ� ������ �Ӵϴ�.
        CONTENTS.append([header])
 
    # ������ ���� ����Ʈ�� �ҷ��ɴϴ�.
    index = HEADERS.index(header)
 
    # ����Ʈ�� ������ ���� �Է��մϴ�.
    CONTENTS[index] += content
 
# ������ �����͵��� ���� ���� ���Ϸ� �����մϴ�.
for i in range(len(CONTENTS)):
    px.save_as(array=CONTENTS[i], dest_file_name=out_dir + "/" + str(i) + str(HEADERS[i][26]) + "_merged_File.xlsx")
 
# �۾� ���� �޽����� ����մϴ�.
print("Process Done.")
 
# �۾��� �� �� �ʰ� �ɷȴ��� ����մϴ�.
end_time = time.time()
print("The Job Took " + str(end_time - start_time) + " seconds.")

생산자별 인증품목과 만료날짜 등의 데이터를 정리하기 위한 프로그램이다. 화면구성은 아래와 같다.

번호 생성 및 유의 사항
1 크롬브라우저. https://www.enviagro.go.kr/portal/info/info_certifi_ok.do 페이지를 띄우고, 창크기(가로:최소/세로:최대)를 조절한다. 이때 왼쪽과 위쪽의 윈도우가 완전히 붙지 않고, 간격이 있어야 한다(화살표참조)
2 친환경 인증데이터 받기를 참조하여 받은 엑셀데이터를 실행한 윈도우
3 엑셀파일 생성 A1(국립농산물품질관리원), A2(인증품목정보)를 입력한 윈도우
4 인증번호로 파일생성을 참조하여 만든 파일을 실행한 윈도우
5 인증번호로 만든 파일들이 있는 디렉토리 윈도우

※각 윈도우의 좌표코드는 위 그림의 네모박스 위치를 참고한다.
※캡처화면을 보면, 윈도우 창이 겹쳐지는 것을 볼 수 있다.

실행에 필요한 좌표의 위치는 아래 표와 같다.

1 5번 윈도우 타이틀 위치
2 1번 윈도우 '인증정보' 클릭 위치(위쪽/그림참조)
3 1번 윈도우 '인증정보' 클릭 위치(위쪽/그림참조)
4 3번 윈도우 타이틀 위치
5 4번 윈도우 타이틀 위치
6 3번 윈도우 타이틀 위치(4번과 동일)
7 4번 윈도우 타이틀 위치(5번과 동일)
8 2번 윈도우 타이틀 위치

생산자 상품의 인증번호를 검색하기 위해서는 국립농산물품질관리원 홈페이지(https://www.enviagro.go.kr/portal/info/info_certifi_ok.do?tabIndex=2)에 접속해야 한다. '기본검색' 탭에서 인증번호를 입력해서 등록된 생산자의 정보를 확인할 수 있다.

import pyautogui
import time
time.sleep(10)
 
for i in range(100):
    // 2번 윈도우를 활성화하고, '인증번호' 행을 선택
    pyautogui.press('down')    
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=779, y=377, button='right', clicks=1)   // 1. 5번 윈도우 타이틀 위치
    time.sleep(1)
    pyautogui.hotkey('ctrl','f')
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')
    time.sleep(1)    
    pyautogui.press('down')
    time.sleep(0.3)
    pyautogui.press('down')   
    time.sleep(0.3)
    pyautogui.press('enter')
    time.sleep(4)
    pyautogui.hotkey('win','right')
    time.sleep(1)    
    pyautogui.press('esc')   
    time.sleep(1)   
    pyautogui.click(x=70, y=827, button='right', clicks=1) // 2. 1번 윈도우 '인증정보' 링크 위치
    time.sleep(10)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.05)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)
    pyautogui.press('tab')
    time.sleep(0.03)  
    pyautogui.hotkey('ctrl','v')    
    time.sleep(1)
    pyautogui.press('enter')    
    time.sleep(10) 
    pyautogui.hotkey('ctrl','a')    
    time.sleep(1)    
    pyautogui.hotkey('ctrl','c')
    time.sleep(1) 
    pyautogui.click(x=70, y=366, button='right', clicks=1)  // 3. 1번 윈도우, '인증정보' 링크위치(2번과 동일)
    time.sleep(1)   
    pyautogui.hotkey('alt','tab')
    time.sleep(1)    
    pyautogui.hotkey('ctrl','alt','v')
    time.sleep(1) 
    pyautogui.press('down')   
    time.sleep(1)    
    pyautogui.press('enter')
    time.sleep(1)   
    pyautogui.press('up')
    time.sleep(1)   
    pyautogui.click(x=836, y=28, button='right', clicks=1)  // 4. 3번 윈도우 타이틀 위치
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.click(x=1325, y=17, button='right', clicks=1)  // 5. 4번 윈도우 타이틀 위치
    time.sleep(1)
    pyautogui.hotkey('ctrl','f')
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')    
    time.sleep(1)    
    pyautogui.press('enter')
    time.sleep(1) 
    pyautogui.press('enter')
    time.sleep(1)  
    pyautogui.hotkey('alt','f4')
    time.sleep(1)
    pyautogui.hotkey('ctrl','shift', 'right')
    time.sleep(0.5)
    pyautogui.hotkey('ctrl','shift', 'down')
    time.sleep(0.5)    
    pyautogui.hotkey('ctrl','shift', 'down')
    time.sleep(0.5)
    pyautogui.hotkey('ctrl','shift', 'down')
    time.sleep(0.5)
    pyautogui.hotkey('shift', 'f10')
    time.sleep(1)   
    pyautogui.press('d')      
    time.sleep(1)
    pyautogui.click(x=836, y=28, button='right', clicks=1)  // 6. 3번 윈도우 타이틀 위치
    time.sleep(1)    
    pyautogui.press('down')      
    time.sleep(1)
    pyautogui.hotkey('ctrl','c')
    time.sleep(1)
    pyautogui.press('up')      
    time.sleep(1)
    pyautogui.click(x=1325, y=17, button='right', clicks=1)  // 7. 4번 윈도우 타이틀 위치
    time.sleep(1)
    pyautogui.press('up')      
    time.sleep(1)
    pyautogui.hotkey('ctrl','f')
    time.sleep(1)
    pyautogui.hotkey('ctrl','v')    
    time.sleep(1)
    pyautogui.press('enter')      
    time.sleep(1)
    pyautogui.hotkey('alt','f4')
    time.sleep(1)
    pyautogui.hotkey('ctrl','shift', 'right')
    time.sleep(0.5)
    pyautogui.hotkey('ctrl','shift', 'up')
    time.sleep(0.5)    
    pyautogui.hotkey('ctrl','shift', 'up')
    time.sleep(0.5)
    pyautogui.hotkey('ctrl','shift', 'up')
    time.sleep(0.5)
    pyautogui.hotkey('shift', 'f10')
    time.sleep(1)   
    pyautogui.press('d')      
    time.sleep(1)
    pyautogui.press('up')      
    time.sleep(1)  
    pyautogui.hotkey('ctrl','s')    
    time.sleep(1)
    pyautogui.hotkey('alt','f4')
    time.sleep(1)   
    pyautogui.click(x=646, y=31, button='right', clicks=1)  // 8. 2번 윈도우 타이틀 위치
    time.sleep(1)

쉬프트(Shift) 키가 먹지 않을 때

키보드의 'NumLock' 키를 눌러서 아래의 코드를 다시 실행해보자.

import pyautogui
import time
time.sleep(3)
 
for i in range(1):
    pyautogui.hotkey('ctrl','shift', 'right')
    time.sleep(1)
    pyautogui.hotkey('ctrl','shift', 'down')
    time.sleep(1)    

인증데이터 모으기(업데이트)

아래 코드는 주피터(jupyter)에서 실행한다.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
 
def list_chunk(lst, n):
    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
f = open("C:/gsfood/a.txt", 'r')
 
lines = f.readlines()
for line in lines:
    line =line.strip()
   # print(line)
f.close()
 
nn = len(lines)
print("nn is", nn)
 
number = 0
 
for i in range(1,nn+1):
    line = lines[number].strip()
    number = number + 1
    print(line)
    #url = "http://" + "www" + "daum" + line + "&today"
    url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=" + line + "&tabIndex=1&today_dt=20220217"
    print(url)
    html = urlopen(url)
    bs_obj = BeautifulSoup(html, "html.parser")
    table_tag = bs_obj.find_all("table")
    table_tag01 = table_tag[1].find_all("td")
 
    #print('===================')
    #print(table_tag01)
    #print(table_tag01[0])
    #print('===================')
 
    #BeautifulSoup(table_tag01, "lxml").text
 
 
    #table_tag02 = table_tag01[0].text
    #table_tag03 = table_tag01[1].text
    list_chunked = list_chunk(table_tag01, 4)
    #prd_names=str(list_chunked)
    #prd_names=re.sub('<.+?>', '\'', prd_names, 0).strip()
 
    #print("분할 전 : ", table_tag01)
 
 
    #print("분할 후 : ", prd_names)
 
    #df = pd.DataFrame(list(prd_names))
    #df = pd.DataFrame([prd_names])
    #df = pd.DataFrame(columns=['prd_names'])
 
    #df = pd.DataFrame(list(prd_names.values()), index=prd_names.keys())
 
    #df = pd.DataFrame(prd_names)
 
 
    df = pd.DataFrame(list_chunked)
    df.to_excel("C:/gsfood/" + line + ".xlsx", index=False)
 
#print('=========================')
 
#url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=12100774&tabIndex=1&today_dt=20220216"
#url_t = "http://" + "www" + "daum" + line + "&today"
 
#print('|||||||||||||||')
 
#print(url)
#print(url_t)
 
#html = urlopen(url)
#bs_obj = BeautifulSoup(html, "html.parser")
#table_tag = bs_obj.find_all("table")
#table_tag01 = table_tag[1].find_all("td")
 
 
#def list_chunk(lst, n):
#    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
#list_chunked = list_chunk(table_tag01, 4)
 
#prd_names=str(list_chunked)
#prd_names=re.sub('<.+?>', '', prd_names, 0).strip()
 
 
#print("분할 후 : ", prd_names)
 
#filename = "12345"
 
 
#df = pd.DataFrame(list(prd_names))
#df.to_excel(filename + ".xlsx", index=False)

인증데이터 모으기(업데이트2)

오른쪽 셀에 인증번호 추가되도록 수정했다.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
 
def list_chunk(lst, n):
    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
f = open("C:/gsfood_test/a.txt", 'r')
 
lines = f.readlines()
for line in lines:
    line =line.strip()
   # print(line)
f.close()
 
nn = len(lines)
print("nn is", nn)
 
number = 0
 
for i in range(1,nn+1):
    line = lines[number].strip()
    number = number + 1
    print(line)
    #url = "http://" + "www" + "daum" + line + "&today"
    url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=" + line + "&tabIndex=1&today_dt=20220217"
    print(url)
    html = urlopen(url)
    bs_obj = BeautifulSoup(html, "html.parser")
    table_tag = bs_obj.find_all("table")
    table_tag01 = table_tag[1].find_all("td")
 
    #print('===================')
    #print(table_tag01)
    #print(table_tag01[0])
    #print('===================')
 
    print('====11111111===')
    print(len(table_tag01))
    print(table_tag01)
 
    nnn = len(table_tag01)//4
 
    print(nnn)
    first_n = 4
 
 
    ##############################
 
    for j in range(1, nnn+1):
        table_tag01.insert(first_n, line)
        first_n = first_n + 5
    ####################################    
 
 
 
    #table_tag01.insert(4, line)
    #table_tag01.insert(9, line)
    #table_tag01.insert(14, line)
    #table_tag01.insert(19, line)
    #table_tag01.insert(24, line)
    #table_tag01.insert(29, line)            
    #table_tag01.insert(34, line)
    #table_tag01.insert(39, line)
    #table_tag01.insert(44, line)
 
    #table_tag01.append("test")
 
 
    print('====2222222222=====')
    print(len(table_tag01))
    print(table_tag01)
 
    #BeautifulSoup(table_tag01, "lxml").text
 
 
    #table_tag02 = table_tag01[0].text
    #table_tag03 = table_tag01[1].text
    list_chunked = list_chunk(table_tag01, 5)
    #prd_names=str(list_chunked)
    #prd_names=re.sub('<.+?>', '\'', prd_names, 0).strip()
 
    #print("분할 전 : ", table_tag01)
 
 
    #print("분할 후 : ", prd_names)
 
    #df = pd.DataFrame(list(prd_names))
    #df = pd.DataFrame([prd_names])
    #df = pd.DataFrame(columns=['prd_names'])
 
    #df = pd.DataFrame(list(prd_names.values()), index=prd_names.keys())
 
    #df = pd.DataFrame(prd_names)
 
 
    df = pd.DataFrame(list_chunked)
    df.to_excel("C:/gsfood_test/" + line + ".xlsx", index=False)
 
#print('=========================')
 
#url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=12100774&tabIndex=1&today_dt=20220216"
#url_t = "http://" + "www" + "daum" + line + "&today"
 
#print('|||||||||||||||')
 
#print(url)
#print(url_t)
 
#html = urlopen(url)
#bs_obj = BeautifulSoup(html, "html.parser")
#table_tag = bs_obj.find_all("table")
#table_tag01 = table_tag[1].find_all("td")
 
 
#def list_chunk(lst, n):
#    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
#list_chunked = list_chunk(table_tag01, 4)
 
#prd_names=str(list_chunked)
#prd_names=re.sub('<.+?>', '', prd_names, 0).strip()
 
 
#print("분할 후 : ", prd_names)
 
#filename = "12345"
 
 
#df = pd.DataFrame(list(prd_names))
#df.to_excel(filename + ".xlsx", index=False)

인증데이터 모으기(업데이트3)

인증분류마다 추출되는 데이터가 다르기 때문에 발생하는 문제를 수정했다. 분류 별로 다르게 처리하도록 했다.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
 
def list_chunk(lst, n):
    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
f = open("C:/gsfood_test/a.txt", 'r')
 
lines = f.readlines()
for line in lines:
    line =line.strip()
   # print(line)
f.close()
 
nn = len(lines)
print("nn is", nn)
 
number = 0
 
for i in range(1,nn+1):
    line = lines[number].strip()
    number = number + 1
    print(line)
    #print(line[0])
    #print(line[2])
 
 
    #url = "http://" + "www" + "daum" + line + "&today"
    url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=" + line + "&tabIndex=1&today_dt=20220217"
    print(url)
    html = urlopen(url)
    bs_obj = BeautifulSoup(html, "html.parser")
    table_tag = bs_obj.find_all("table")
    table_tag01 = table_tag[1].find_all("td")
 
 
 
 
 
    print('===================')
    print(table_tag01)
    #print(table_tag01[0])
    #print('===================')
 
    print('====11111111===')
    print(len(table_tag01))
    print(table_tag01)
 
    if line[2] ==  '1' or line[2] == '3' or line[2] == '2' or line[2] == '5':
        nnn = len(table_tag01)//4
        print(nnn)
        first_n = 4
        ##############################
        for j in range(1, nnn+1):
            table_tag01.insert(first_n, line)
            first_n = first_n + 5
            ####################################
 
        print('====2222222222=====')
        print(len(table_tag01))
        print(table_tag01)
        list_chunked = list_chunk(table_tag01, 5)
    elif line[2] == '6':
        nnn = len(table_tag01)//5
        print(nnn)
        first_n = 5
        ##############################
        for j in range(1, nnn+1):
            table_tag01.insert(first_n, line)
            first_n = first_n + 6
            ####################################
 
        print('====2222222222=====')
        print(len(table_tag01))
        print(table_tag01)
        list_chunked = list_chunk(table_tag01, 6)
    elif line[2] == '7' or line[2] =='8':
        nnn = len(table_tag01)//3
        print(nnn)
        first_n = 3
        ##############################
        for j in range(1, nnn+1):
            table_tag01.insert(first_n, line)
            first_n = first_n + 4
            ####################################
 
        print('====2222222222=====')
        print(len(table_tag01))
        print(table_tag01)
        list_chunked = list_chunk(table_tag01, 4)
 
    else:
        list_chunked = list_chunk(table_tag01, 5)
 
    #table_tag01.insert(4, line)
    #table_tag01.insert(9, line)
    #table_tag01.insert(14, line)
    #table_tag01.insert(19, line)
    #table_tag01.insert(24, line)
    #table_tag01.insert(29, line)            
    #table_tag01.insert(34, line)
    #table_tag01.insert(39, line)
    #table_tag01.insert(44, line)
 
    #table_tag01.append("test")
 
 
    #print('====2222222222=====')
    #print(len(table_tag01))
    #print(table_tag01)
 
    #BeautifulSoup(table_tag01, "lxml").text
 
 
    #table_tag02 = table_tag01[0].text
    #table_tag03 = table_tag01[1].text
 
 
    #list_chunked = list_chunk(table_tag01, 5)
 
 
    #prd_names=str(list_chunked)
    #prd_names=re.sub('<.+?>', '\'', prd_names, 0).strip()
 
    #print("분할 전 : ", table_tag01)
 
 
    #print("분할 후 : ", prd_names)
 
    #df = pd.DataFrame(list(prd_names))
    #df = pd.DataFrame([prd_names])
    #df = pd.DataFrame(columns=['prd_names'])
 
    #df = pd.DataFrame(list(prd_names.values()), index=prd_names.keys())
 
    #df = pd.DataFrame(prd_names)
 
 
    df = pd.DataFrame(list_chunked)
    df.to_excel("C:/gsfood_test/" + line + ".xlsx", index=False)
 
#print('=========================')
 
#url = "https://www.enviagro.go.kr/portal/info/Info_certifi_spe.do?s_query_type=1&s_std_cert_no=12100774&tabIndex=1&today_dt=20220216"
#url_t = "http://" + "www" + "daum" + line + "&today"
 
#print('|||||||||||||||')
 
#print(url)
#print(url_t)
 
#html = urlopen(url)
#bs_obj = BeautifulSoup(html, "html.parser")
#table_tag = bs_obj.find_all("table")
#table_tag01 = table_tag[1].find_all("td")
 
 
#def list_chunk(lst, n):
#    return [lst[i:i+n] for i in range(0, len(lst), n)]
 
#list_chunked = list_chunk(table_tag01, 4)
 
#prd_names=str(list_chunked)
#prd_names=re.sub('<.+?>', '', prd_names, 0).strip()
 
 
#print("분할 후 : ", prd_names)
 
#filename = "12345"
 
 
#df = pd.DataFrame(list(prd_names))
#df.to_excel(filename + ".xlsx", index=False)

위 코드에 따르면, C:\gsfood_test 아래에 인증번호로 파일이 생성되어 있을 것이다. 인증종류에 따라 저장되는 데이터 열이 다르다.

  • computer/gsfood/파이썬을_이용한_자동화.txt
  • Last modified: 3 years ago
  • by likewind