- 프로그램명 : XLS2JSON.py
- 제작기간 : '25. 5. 6.(1일)
- 제작자 : REDUCTO
- 사용언어 : Python
- 사용라이브러리 : pandas, tqdm

- 버전 : v1.0


소개

기술사공부를 하다가 평소 gemini AI와의 대화(Live)로 연습을 하는데 얘한테 input source로 제가 공부하고 있는 파일을 주고 싶어서 만들어 보았습니다. exe로 만들까 하다가 cli기반이고, 파라미터들로 직접조정하는게 좋을거 같다는 것과, 어짜피 python을 기반으로 exe를 만들면 너무 느려지기 때문에, 코드로만 배포합니다. 하단에 사용법에 코드 실행방법까지 자세하게 표기하겠습니다.
 

* 무단배포는 금지합니다.(댓글달아주세용)
* 기능에 커스터마이징이 필요하시다면 댓글달아주세용


사용법

# ==============================================================================
# XLS2JSON: Excel to JSON Converter
# ==============================================================================
#
# 설명:
#   이 스크립트는 Excel 파일(.xlsx, .xls)을 읽어 JSON 형식으로 변환하는
#   명령줄 인터페이스(CLI) 도구입니다. 데이터 시작 위치를 자동으로 감지하며,
#   특정 시트 또는 모든 시트를 변환하고, 결과를 콘솔 또는 파일로 출력할 수 있습니다.
#   여러 시트를 처리할 때 진행률 표시줄을 보여줍니다.
#
# 필요한 라이브러리 설치:
#   pip install pandas openpyxl tqdm
#
# 기본 사용법:
#   python xls2json.py <입력_Excel_파일경로> [옵션]
#
# 옵션:
#   <입력_Excel_파일경로> : 변환할 Excel 파일의 경로 (필수)
#
#   -o, --output <출력_파일경로> :
#       변환된 JSON 결과를 저장할 파일 경로입니다.
#       지정하지 않으면 결과가 콘솔(표준 출력)에 표시됩니다.
#       예: -o result.json
#
#   -s, --sheet <시트_이름_또는_인덱스> :
#       변환할 특정 시트의 이름(문자열) 또는 0부터 시작하는 인덱스(숫자)입니다.
#       기본값은 0 (첫 번째 시트)입니다.
#       --all-sheets 옵션이 사용되면 이 옵션은 무시됩니다.
#       예: -s "데이터 시트"
#       예: -s 1  (두 번째 시트를 의미)
#
#   -a, --all-sheets :
#       Excel 파일 내의 모든 시트를 변환합니다.
#       이 옵션을 사용하면 결과 JSON은 각 시트 이름을 키로 가지는 객체 형태가 됩니다.
#       예: {"Sheet1": [...], "Sheet2": [...]}
#
# 실행 예시:
#   # 1. 첫 번째 시트를 콘솔에 출력
#   python xls2json.py data.xlsx
#
#   # 2. '매출데이터' 시트를 result.json 파일로 저장
#   python xls2json.py data.xlsx -s "매출데이터" -o result.json
#
#   # 3. 두 번째 시트(인덱스 1)를 console_output.json 파일로 저장
#   python xls2json.py data.xlsx -s 1 -o console_output.json
#
#   # 4. 모든 시트를 all_sheets.json 파일로 저장 (시트 이름별로 구분됨)
#   python xls2json.py data.xlsx -a -o all_sheets.json
#
# ==============================================================================

import pandas as pd
import argparse
import sys
import json
import os
from tqdm import tqdm

# --- 이하 코드는 이전과 동일 ---

def find_and_process_data(df):
    """
    데이터프레임에서 데이터 시작 위치를 찾아 처리하고,
    첫 행을 헤더로 사용하여 Python 객체 리스트로 변환합니다.
    """
    df_processed = df.dropna(how='all').dropna(how='all', axis=1)
    if df_processed.empty:
        return []
    new_header = df_processed.iloc[0].astype(str)
    df_processed = df_processed[1:]
    df_processed.columns = new_header
    df_processed = df_processed.reset_index(drop=True)
    df_processed = df_processed.where(pd.notnull(df_processed), None)
    return df_processed.to_dict(orient='records')

def convert_single_sheet_to_json(file_path, sheet_name=0):
    """
    Excel 파일의 지정된 단일 시트를 읽어 자동 감지 후 JSON 문자열로 변환합니다.
    """
    try:
        df = pd.read_excel(file_path, sheet_name=sheet_name, header=None, engine='openpyxl')
        processed_data = find_and_process_data(df)
        json_data = json.dumps(processed_data, indent=4, ensure_ascii=False)
        return json_data
    except FileNotFoundError:
        print(f"오류: 파일을 찾을 수 없습니다 - {file_path}", file=sys.stderr)
        return None
    except ValueError as ve:
        print(f"오류: 시트 '{sheet_name}' 처리 중 오류 발생. 시트 이름/인덱스를 확인하세요. 에러: {ve}", file=sys.stderr)
        return None
    except Exception as e:
        print(f"오류: 단일 시트 처리 중 예외 발생 ({type(e).__name__}) - {e}", file=sys.stderr)
        return None


def convert_all_sheets_to_json(file_path):
    """
    Excel 파일의 모든 시트를 읽어 자동 감지 후 시트 이름을 키로 하는 JSON 객체 문자열로 변환합니다.
    """
    try:
        all_sheets_df_map = pd.read_excel(file_path, sheet_name=None, header=None, engine='openpyxl')

        all_sheets_data = {}
        print("시트 처리 중...", file=sys.stderr)
        for sheet_name, df in tqdm(all_sheets_df_map.items(), desc="Processing sheets", unit="sheet", leave=False):
            try:
                processed_data = find_and_process_data(df)
                all_sheets_data[sheet_name] = processed_data
            except Exception as e:
                print(f"\n경고: 시트 '{sheet_name}' 처리 중 오류 발생하여 건너뜁니다 ({type(e).__name__}) - {e}", file=sys.stderr)
                all_sheets_data[sheet_name] = {"error": f"Failed to process sheet: {e}"}

        json_data = json.dumps(all_sheets_data, indent=4, ensure_ascii=False)
        return json_data

    except FileNotFoundError:
        print(f"오류: 파일을 찾을 수 없습니다 - {file_path}", file=sys.stderr)
        return None
    except Exception as e:
        print(f"오류: 모든 시트 처리 중 예외 발생 ({type(e).__name__}) - {e}", file=sys.stderr)
        return None

def save_to_file(data, output_file):
    """
    주어진 데이터를 지정된 파일 경로에 UTF-8 인코딩으로 저장합니다.
    """
    try:
        output_dir = os.path.dirname(output_file)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(data)
        return True
    except IOError as e:
        print(f"오류: 파일 '{output_file}'에 쓰는 중 오류 발생 - {e}", file=sys.stderr)
        return False
    except Exception as e:
        print(f"오류: 파일 저장 중 예기치 않은 오류 발생 ({type(e).__name__}) - {e}", file=sys.stderr)
        return False

def main():
    parser = argparse.ArgumentParser(
        description="XLS2JSON: Excel to JSON Converter with auto-detection and progress bar.",
        epilog="Example: python xls2json.py data.xlsx -a -o output.json" # 에필로그 추가
    )
    parser.add_argument("excel_file", help="Path to the input Excel file.")
    parser.add_argument(
        "-s", "--sheet",
        default=0,
        help="Specify sheet name or 0-based index to convert (default: 0). Ignored if --all-sheets is used."
    )
    parser.add_argument(
        "-a", "--all-sheets",
        action='store_true',
        help="Convert all sheets in the Excel file. Output JSON will be an object with sheet names as keys."
    )
    parser.add_argument(
        "-o", "--output",
        help="Path to the output JSON file. If not specified, output will be printed to the console."
    )

    args = parser.parse_args()

    json_output = None
    action_description = ""

    if args.all_sheets:
        action_description = "Convert all sheets with auto-detection"
        json_output = convert_all_sheets_to_json(args.excel_file)
    else:
        sheet_identifier = args.sheet
        try:
            sheet_identifier_int = int(args.sheet)
            sheet_identifier = sheet_identifier_int
        except ValueError:
            pass
        action_description = f"Convert sheet '{sheet_identifier}' with auto-detection"
        print(f"Processing: {action_description}...", file=sys.stderr)
        json_output = convert_single_sheet_to_json(args.excel_file, sheet_name=sheet_identifier)

    if json_output:
        if args.output:
            print(f"Saving results to '{args.output}'...", file=sys.stderr)
            if save_to_file(json_output, args.output):
                 print(f"Success: {action_description} completed. Results saved to '{args.output}'.", file=sys.stderr)
            else:
                sys.exit(1)
        else:
            print(json_output) # Print JSON to stdout
    else:
        print(f"Error: Failed during '{action_description}'.", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()

 

* 사전준비

 - python이 설치되어있어야합니다.

 - 필자의 환경은 python 3.13.0입니다. 가급적 맞추어주시거나 상위버전을 사용해 주시는게 좋습니다.

 

1. 해당 파일을 xls2json.py로 저장합니다.

2. 아래 requiremets.txt를 다운로드 받습니다.

requirements.txt
0.00MB

 

3. cmd를 켜고(Python 경로 Path에 포함되어있어야합니다) 다음과 같이 입력합니다(requirements.txt가 있는 경로에서)

pip install -r requirements.txt

 

4. 코드 상단에 사용방법과 같이 XLS2JSON을 사용해 주시면 됩니다. 

# ==============================================================================
# XLS2JSON: Excel to JSON Converter
# ==============================================================================
#
# 설명:
#   이 스크립트는 Excel 파일(.xlsx, .xls)을 읽어 JSON 형식으로 변환하는
#   명령줄 인터페이스(CLI) 도구입니다. 데이터 시작 위치를 자동으로 감지하며,
#   특정 시트 또는 모든 시트를 변환하고, 결과를 콘솔 또는 파일로 출력할 수 있습니다.
#   여러 시트를 처리할 때 진행률 표시줄을 보여줍니다.
#
# 필요한 라이브러리 설치:
#   pip install pandas openpyxl tqdm
#
# 기본 사용법:
#   python xls2json.py <입력_Excel_파일경로> [옵션]
#
# 옵션:
#   <입력_Excel_파일경로> : 변환할 Excel 파일의 경로 (필수)
#
#   -o, --output <출력_파일경로> :
#       변환된 JSON 결과를 저장할 파일 경로입니다.
#       지정하지 않으면 결과가 콘솔(표준 출력)에 표시됩니다.
#       예: -o result.json
#
#   -s, --sheet <시트_이름_또는_인덱스> :
#       변환할 특정 시트의 이름(문자열) 또는 0부터 시작하는 인덱스(숫자)입니다.
#       기본값은 0 (첫 번째 시트)입니다.
#       --all-sheets 옵션이 사용되면 이 옵션은 무시됩니다.
#       예: -s "데이터 시트"
#       예: -s 1  (두 번째 시트를 의미)
#
#   -a, --all-sheets :
#       Excel 파일 내의 모든 시트를 변환합니다.
#       이 옵션을 사용하면 결과 JSON은 각 시트 이름을 키로 가지는 객체 형태가 됩니다.
#       예: {"Sheet1": [...], "Sheet2": [...]}
#
# 실행 예시:
#   # 1. 첫 번째 시트를 콘솔에 출력
#   python xls2json.py data.xlsx
#
#   # 2. '매출데이터' 시트를 result.json 파일로 저장
#   python xls2json.py data.xlsx -s "매출데이터" -o result.json
#
#   # 3. 두 번째 시트(인덱스 1)를 console_output.json 파일로 저장
#   python xls2json.py data.xlsx -s 1 -o console_output.json
#
#   # 4. 모든 시트를 all_sheets.json 파일로 저장 (시트 이름별로 구분됨)
#   python xls2json.py data.xlsx -a -o all_sheets.json
#
# ==============================================================================

 

EASY합니다 끝t

PhotoCollage.zip
15.49MB

 

- 프로그램명 : PhotoCollage.exe
- 제작기간 : '25. 4. 17.(1일)
- 제작자 : REDUCTO
- 사용언어 : Python
- 사용라이브러리 : Tkinter

- 버전 : v1.0


소개

문득 집에서 공부하다가 이런 프로그램이 로컬수준으로 있으면 좋을거 같다는 생각이 들어서 만들어보았습니다. python tkinter로 제작하였고, Java로 할라다가 코드가 너무 길어져서 짧게 치려는 느낌으로 만들었습니다.
 

* 무단배포는 금지합니다.(댓글달아주세용)
* 기능에 커스터마이징이 필요하시다면 댓글달아주세용


사용법

 

프로그램의 화면은 위와 같습니다. 사용자는 캔버스 크기를 지정한다음에 이미지 추가로 여러이미지를 캔버스에 배치할 수 있습니다.(그러고 보니 DnD를 구현안했네요) 아무튼 이렇게 불러온 이미지는 캔버스 여러군데에 자유롭게 배치할 수 있습니다. 테두리나 각 사진들의 경계에 가면 자동으로 붙게끔 만들어보았고 배경사진이나 배경색도 선택할 수 있게 만들어 보았습니다.

 

다 된 사진은 캔버스 저장을 통해서 png파일로 저장할 수 있습니다. 

 

아직 구현되지 않은 기능으로 사진 크기조절이랑 음... 또 뭐가 있으면 좋을까는 생각중입니다! 좋은 아이디어 있으신분은 알려주세요! (아이콘은 지정했는데 resource 로딩 오류같습니다. 혹시나 프로그램을 수정할 일이 생기면 반영해서 고치려구요!

 

* 숨겨진 기능인데, Shift를 누르고 여러사진을 한번에 이동시키거나 [Shift]+화살표로 미세이동 할 수 있습니다!

일이 조금 있어서 네이버 카페의 크롤링 코드를 만들어야했다. 여러가지 글을 종합해서 처리할게 있었다. 가장 궁금했던건 어떻게 OTP인증이나 User-Agent가 브라우저가 아닌 요청이 Allow될지 였는데, 역시나 Selenium을 통해서 하면 User의 Action을 구사해서 할 수있었다.(Python 짱짱맨) 아래는 코드이다.

import time
from selenium import webdriver
import pandas as pd
from bs4 import BeautifulSoup as bs
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

if __name__ == "__main__" :

    ### 로그인 프로세스
    login_url='https://nid.naver.com/nidlogin.login'
    user_id="<USER  ID>"
    user_pw="<USER  PW>"

    browser=webdriver.Chrome(ChromeDriverManager().install())
    browser.get(login_url)
    browser.implicitly_wait(2)

    browser.execute_script("document.getElementsByName('id')[0].value=\'"+ user_id + "\'")
    browser.execute_script("document.getElementsByName('pw')[0].value=\'"+ user_pw + "\'")

    browser.find_element(by=By.XPATH,value='//*[@id="log.login"]').click()
    time.sleep(1)

    ### 크롤링 Target Url
    baseurl=''
    browser.get(baseurl)
    
    pageNum = 0

    while(True) :
        
        time.sleep(1)
        
        pageNum +=1 
        print(pageNum)

        browser.get(baseurl +'&search.page='+ str(pageNum))
        
        ### 카페 메인 게시클 화면이 iframe으로 구성되어있음. iframe id가 cafe_main
        browser.switch_to.frame('cafe_main')

        soup = bs(browser.page_source ,'html.parser')
        soup = soup.find_all(class_ = 'article-board m-tcol-c')[1]

        datas = soup.select("#main-area > div:nth-child(4) > table > tbody > tr")

        for data in datas:
            ### article 은 한줄입니다. 원하는 속성 get 후 처리
            article = data.find(class_= "article")
            
    print('Finish')

Python과 다른 언어와의 큰 차이점을 두자면(요즈음 들어서는 많은 언어가 지원하기에 퇴색된 기능이지만) Type으로부터의 자유로움을 손에 꼽을 수 있다.

>>> a=1 >>> b="heyhey" >>> type(a) <class 'int'> >>> type(b) <class 'str'>

위와 같이 다른 언어에서의 변수 선언 시 type을 같이 지정해 주어야 하는 재래식 언어와는 많은 차별점을 둔다.

다만 이런 Python의 장점은 코드의 규모가 커지고 방대해질 수록 많은 문제를 야기하며, 프로그램의 동작상에서 동작하는 Runtime level의 문제라기보다는, 프로그래머 사이 작성되는 코드 혹은 과거의 나와 싸우고 있는 프로그래머들에게 Type의 힌트를 줄 필요성이 생겼다.

<최솟값을 찾는 함수 : JAVA의 경우>

// 최소값을 찾는 JAVA함수, int를 반환하고 ArrayList<int>를 받는다는 것을 함수에서 알 수 있다. public int findMinimumNumber(ArrayList<int> arr){ int result = arr[0]; for(int a : arr) if(result > a) result=a; return result; }

<최솟값을 찾는 함수 : Python의 경우>

### 내장함수 min에 의해 처리될 수 있는 value를 입력으로 받고 그의 원소값을 반환 ### 어떤형의 parameter를 받고 반환하는지 알 수 없다. def find_minimum(value) : return min(value)

위와 같은 문제들을 해결하기 위해 함수에 주석을 달거나 하는 프로그래머 개개인의 노력을 이용했다.

### param : list ret : int def find_minimum(value) : return min(value)

Python도 이 문제를 인식한 듯 Type Annotation을 제공한다. 다음과 같다.

def find_minimum(value : list) -> int : return min(value)

사용법은 간단한다.

  • 변수명 뒤 콜론(:)을 붙이고 type명을 기술 type명에는 클래스도 들어갈 수 있다.
  • 함수의 반환은 화살표(->)을 붙이고 type명을 기술 당연하게도 여기도 클래스가 들어갈 수 있다.

단! 이렇게 적는 type annotation은 주석의 확장으로 밖에 여겨지지 않으며, 인터프리터는 해석 시 type annotation을 염두하지 않는다.

pyautogui는 외장모듈이다. 모듈명 그대로 다운로드 가능하다.

pip3 install pyautogui

역할은 마우스, 키보드의 입력 / 이동을 Python으로 조절하기 위한 모듈이다. 흔히 마우스 마음대로 움직이거나, 키보드가 맘대로 쳐지면 이와 비슷한 모듈이 들어가 있다고 보면 된다.


주요 함수 설명

  • pyautogui.size() : 현재 모니터의 해상도를 (x,y) tuple로 반환한다.
  • pyautogui.onScreen(x,y) : 좌표 x,y의 위치가 모니터 안에서 유효한 좌표인지 bool값으로 반환한다.
  • pyautogui.position() : 현재 마우스의 위치를 반환한다.
  • pyautogui.moveTo(x,y,duration=num_seconds) : duration에 적힌 기간동안 x,y의 좌표로 마우스를 이동한다.
  • pyautogui.moveRel(xoffset,yoffset,duration=num_seconds) : duration에 적힌 기간동안 xoffset, yoffset 만큼 마우스를 이동한다.
  • pyautogui.dragTo(x,y,duration=num_seconds) : duration에 적힌 기간동안 x,y로 마우스를 드래그(클릭 후 이동)한다.
  • pyautogui.dragRel(xoffset,yoffset,duration_num_seconds) : duration에 적힌 기간동안 xoffset, yoffset 만큼 마우스를 드래그(클릭 후 이동)한다.
  • pyautogui.click(x=moveToX,y=moveToY,clickes=num, interval=secs_betweens_clicks,button="left") : 현재위치에서 클릭한다. parameter로는 옆과 같은것을 줄 수 있다.
  • pyautogui.rightClick(x=moveToX,moveToY) : 우클릭
  • pyautogui.middleClick(x=moveToX,moveToY) : 휠클릭
  • pyautogui.doubleClick(x=moveToX,moveToY) : 더블클릭
  • pyautogui.tripleClick(x=moveToX,moveToY) : 세번클릭
  • pyautogui.scroll(amount_to_scroll,x=moveToX,y=moveToY) : 마우스 스크롤 한다. 양수면 위로, 음수면 아래로
  • pyautogui.mouseDown(x=moveToX, y=moveToY, button='left') : 마우스버튼을 "누른다"
  • pyautogui.mouseUp(x=moveToX, y=moveToY, button='left') : 마우스버튼을 "뗀다"
  • pyautogui.typewrite(type_string, interval=secs_between_keys) : type_string을 친다.
  • pyautogui.hotkey(param1, param2...) : 단축키로 쓰인다. 보통 param에 'ctrl', 'shift'등이 쓰인다.
  • pyautogui.keyDown(key_name) : key_name을 '누른다'
  • pyautogui.keyUp(key_name) : key_name을 '누른다'
  • pyautogui.alert(message) : 경고 메시지 박스
  • pyautogui.confirm(message) : 확인 메시지 박스
  • pyautogui.prompt(message) : user Input 처리를 위한 메시지 박스
  • pyautogui.screenshot(region=(x1,y1,x2,y2)) : 스크린샷을 찍는다. PIL.Image 객체를 반환한다.
  • pyautogui.locateOnScreen(Image_name) : 모니터화면에서 Image_name에 해당하는 Image를 찾아서 위치를 반환한다.(웹 개체는 안된다. 로컬개체만)

이거말고도 pixelMatchsColor등 특정 규칙에 맞게 화면의 마우스를 이동시키는 방법도 있다.

 

출처 : https://pyautogui.readthedocs.io/en/latest/index.html

 

Welcome to PyAutoGUI’s documentation! — PyAutoGUI documentation

Welcome to PyAutoGUI’s documentation! PyAutoGUI lets your Python scripts control the mouse and keyboard to automate interactions with other applications. The API is designed to be as simple. PyAutoGUI works on Windows, macOS, and Linux, and runs on Pytho

pyautogui.readthedocs.io

 

* pyautogui.FAILSAFE라는 모듈 설정이 있다. 기본 규칙은 TRUE로 되어있다. 화면끝에 마우스가 부딫히면 잠깐동안 프로그램을 멈추는 기능이다.

CVE_SCRAPPER를 만들고, 다음 목표는 이제 한물간 시장인 비트코인이다. 자동매매 프로그램을 올릴 거냐고? 물론 당연하다. 단 필자는 금융지식이 뛰어난 사람은 아니기 때문에 일단은 할 수 있는 장만 만들어 보려고 한다. 매도/매수 알고리즘은 돌리는 사람이 짜는 걸로 해야 되지 않을까 싶다. 그렇게 만들려면 으흠; 뭐 잘 만들면 되겠지

  • 목표 완성 시기 : '21. 6. 27.(일)
  • 형태 : PE(exe, GUI)
  • 사용언어 : Python
  • 개발툴 : IDLE, PyCharm
  • 사용 라이브러리 : PyUpbit, Requests, Json 등 웹 처리 모듈
  • 주요 기능
    • 현황 비트코인 대시보드
    • 사용자의 조건 지정 
    • 사용자 조건에 따른 매수/매도 동작

+ Recent posts