본문 바로가기
코딩 연습/코딩배우기

파이썬 GUI 모듈 tkinter 연습(쿠팡 파트너스 상품 링크 관리 프로그램 만들기)

by good4me 2022. 4. 7.

goodthings4me.tistory.com

파이썬 GUI 프로그램 작성용 tkinter 모듈을 이용하여 쿠팡 파트너스에서 생성한 간편 링크인 쿠팡 단축 URL을 관리하는 프로그램을 만들어보는 예제 소스코드

 

 

파이썬 tkinter로 쿠팡 파트너스 링크 관리 프로그램 만들기

여러 카페나 블로그 등의 웹 페이지에 삽입한 쿠팡 파트너스 간편 링크(단축 URL)를 어떻게 관리할 때 엑셀이나 구글 스프레드시트 시트로 관리해도 되고 메모장이나 워드 등의 프로그램을 이용할 수도 있다.

하지만 파이썬으로 코딩 연습을 하다보니 GUI 프로그램 만들 수 있는 tkinter를 사용하여 이를 한번 만들어보는 것도 좋을 것 같아 도전해보았다.

 
쿠팡 파트너스 상품 링크 데이터 입력 부분은

  1. 상품품 입력
  2. 쿠팡 파트너스의 상품 링크(단축 URL) 또는 쿠팡에서 상품 링크를 가져와 쿠팡 파트너스의 간편 링크로 생성한 쿠팡 단축 URL을 입력
  3. 해당 쿠팡 단축 URL을 삽입한 웹 페이지(블로그 등) URL 입력


위 기능을 통해 입력된 데이터는 텍스트 파일을 생성하여 관리한다.  


입력된 데이터 검색, 삭제하는 부분은

  1. 상품명 찾기어(단어) 입력 후 검색
  2. 검색 결과, 상품명, 단축 URL, 웹 페이지 URL 등 표시
  3. 입력된 상품명 데이터 삭제

이렇게 기능을 구현해보았다.

 

프로그램 소스 코드

from tkinter import *
from tkinter import messagebox


root = Tk()
root.title('쿠팡 파트너스 간편 링크 관리')
root.geometry('600x570+500+100')
root.resizable(False, False)
root.option_add('*Font','맑은고딕 12')


def data_save():
    prd = product_entry1.get().strip()
    url = url_entry1.get().strip()
    p_url = paste_entry1.get().strip()

    if len(prd) == 0 or len(url) == 0 or len(p_url) == 0:
        messagebox.showinfo(title='저장', message='상품명, 간편링크, 등록 URL를 입력하세요!')
    else:
        # 동일한 등록 상품명이 있는지 확인
        with open('coupang_link.txt', 'r', encoding='utf-8') as f:
            for data in f:
                if prd in data:
                    messagebox.showinfo(title='저장', message='동일한 상품명이 있습니다.')
                    return False

        with open('coupang_link.txt', 'a', encoding='utf-8') as f:
            f.write(f'{prd}_${url}_${p_url}\n')

        messagebox.showinfo(title='저장', message=f'"{prd}"\n\n저장 완료!')
        product_entry1.delete(0, END)
        url_entry1.delete(0, END)
        paste_entry1.delete(0, END)


def data_search():
    word = product_entry2.get()
    if not word:
        messagebox.showinfo(title='오류!', message='"상품명 검색"란에 검색어를 입력하세요!')
        return False

    with open('coupang_link.txt', 'r', encoding='utf-8') as f:
        # 검색 결과에 몇개의 상품명이 나오는지 확인하여 2개 이상인 경우에는 팝업창에서 보여주고,
        # 정확한 상품명 또는 찾고자 하는 단어를 재 입력하도록 함
        word_list = []  # 상품명 2개 이상일 때 추가하는 리스트
        for data in f:
            if word in data:
                word_list.append(data.split('_$')[0])
        if len(word_list) > 1:
            prd_str = ''
            for w in word_list:
                prd_str += w + '\n'
            messagebox.showinfo(title='찾기', message=f'찾은 데이터가 {len(word_list)}개입니다.\n\n{prd_str}\n\n상품을 구분할 수 있는 상품명을 다시 입력하세요!')
            return False

        f.seek(0)  # 첫 포인트로 이동시킨다
        cnt = 0
        for data in f:
            print(data)
            if word in data:
                cnt += 1
                w, m, p = data.split('_$')
                product_entry2.delete(0, END)
                product_entry2.insert(0, w)
                url_entry2.delete(0, END)
                url_entry2.insert(0, m)
                paste_entry2.delete(0, END)
                paste_entry2.insert(0, p)
        if not cnt:
            messagebox.showinfo(title='찾기', message='찾는 데이터가 없습니다!')


def data_delete():
    word = product_entry2.get()
    url = url_entry2.get()
    p_url = paste_entry2.get()

    if not word:
        messagebox.showinfo(title='삭제', message='삭제할 "상품명 검색" 전체를 정확히 입력하세요!')
        return False
    elif not url:
        messagebox.showinfo(title='삭제', message='삭제할 "간편링크"를 정확히 입력하세요!')
        return False

    elif not p_url:
        messagebox.showinfo(title='삭제', message='삭제할 "등록 URL"를 정확히 입력하세요!')
        return False
    
    del_word = word + '_$' + url + '_$' + p_url

    with open('coupang_link.txt', 'r+', encoding='utf-8') as f:
        new_f = f.readlines()
        f.seek(0)
        cnt = 0
        del_prd = ''  # messagebox 삭제 알림용
        for line in new_f:
            if del_word in line:  # messagebox 팝업 처리용 cnt 증가
                del_prd = line.split('_$')[0]
                cnt += 1
                if messagebox.askyesno('삭제', '정말 삭제하시겠습니까?'):
                    continue
                else:
                    return False
            if del_word not in line:  # 찾는 검색어가 없는 line은 쓰기 실행
                f.write(line)
        f.truncate()  # 현 위치까지만 남기고 나머지는 삭제

        if cnt:
            messagebox.showinfo(title='삭제', message=f'검색 상품명\n\n{del_prd}\n\n삭제 완료!')
            product_entry2.delete(0, END)
            url_entry2.delete(0, END)
            paste_entry2.delete(0, END)
        else:
            messagebox.showinfo(title='삭제', message='삭제할 데이터가 없습니다!')


def set_default():
    product_entry1.delete(0, END)
    url_entry1.delete(0, END)
    paste_entry1.delete(0, END)


def search_set_default():
    product_entry2.delete(0, END)
    url_entry2.delete(0, END)
    paste_entry2.delete(0, END)


## 타이틀
title_lbl = Label(root, text='쿠팡파트너스 간편 링크 관리', font=('맑은고딕', 18, 'bold'))
title_lbl.grid(row=1, column=0, columnspan=3, pady=20)

## 상품 입력 프레임
product_lbl_frame = LabelFrame(root, text='입력')
product_lbl_frame.grid(row=2, column=0, columnspan=3, padx=10)

## 상품명 입력
product_lbl1 = Label(product_lbl_frame, text='상품명 입력', width=10, font=('맑은고딕', 13))
product_lbl1.grid(row=2, column=0, padx=10, pady=5)

product_entry1 = Entry(product_lbl_frame, width=55, bg='powderblue')
product_entry1.grid(row=2, column=1, sticky='w', padx=7, ipady=3)

## 간편링크
url_lbl1 = Label(product_lbl_frame, text='간편링크', width=8, font=('맑은고딕', 13))
url_lbl1.grid(row=3, column=0, padx=10, pady=10)

url_entry1 = Entry(product_lbl_frame, width=50, bg='powderblue', fg='red')
url_entry1.grid(row=3, column=1, pady=10, sticky='w', padx=7, ipady=3)

## 등록 페이지
paste_lbl1 = Label(product_lbl_frame, text='등록 URL', width=8, font=('맑은고딕', 13))
paste_lbl1.grid(row=4, column=0, padx=10, pady=10)

paste_entry1 = Entry(product_lbl_frame, width=55, bg='powderblue', fg='blue')
paste_entry1.grid(row=4, column=1, pady=10, sticky='w', padx=7, ipady=3)

## 버튼
btn_frame1 = Frame(product_lbl_frame)
btn_frame1.grid(row=5, column=0, columnspan=3, padx=10)

btn_save1 = Button(btn_frame1, text='저장하기', width=10, font=('명조', 11), bg='lightblue', command=data_save)
btn_save1.grid(row=5, column=0, pady=20, padx=5)

btn_set_default = Button(btn_frame1, text='입력초기화', width=10, font=('명조', 11), bg='lightblue', command=set_default)
btn_set_default.grid(row=5, column=1, pady=20, padx=5)


## 저장 및 검색 결과 표시 사용하고 싶을 경우에 사용
result_lbl = Label(root, wraplength=400)  # wraplength=300 줄바꿈 처리
result_lbl.grid(row=6, column=0, columnspan=3, ipady=10)

######### 검색 ##########

## 상품 검색 프레임
prd_search_lbl_frame = LabelFrame(root, text='검색')
prd_search_lbl_frame.grid(row=7, column=0, columnspan=3, padx=10)

## 상품명 검색
product_lbl2 = Label(prd_search_lbl_frame, text='상품명 검색', width=10, font=('맑은고딕', 13))
product_lbl2.grid(row=7, column=0, padx=10, pady=5)

product_entry2 = Entry(prd_search_lbl_frame, width=55, bg='powderblue')
product_entry2.grid(row=7, column=1, sticky='w', padx=7, ipady=3)

## 간편링크
url_lbl2 = Label(prd_search_lbl_frame, text='간편링크', width=8, font=('맑은고딕', 13))
url_lbl2.grid(row=8, column=0, padx=10, pady=10)

url_entry2 = Entry(prd_search_lbl_frame, width=50, bg='white', fg='red')
url_entry2.grid(row=8, column=1, pady=10, sticky='w', padx=7, ipady=3)

## 등록 페이지
paste_lbl2 = Label(prd_search_lbl_frame, text='등록 URL', width=8, font=('맑은고딕', 13))
paste_lbl2.grid(row=9, column=0, padx=10, pady=10)

paste_entry2 = Entry(prd_search_lbl_frame, width=55, bg='white', fg='blue')
paste_entry2.grid(row=9, column=1, pady=10, sticky='w', padx=7, ipady=3)

## 버튼
btn_frame2 = Frame(prd_search_lbl_frame)
btn_frame2.grid(row=10, column=0, columnspan=3, padx=10)

btn_find = Button(btn_frame2, text='검색하기', width=10, font=('명조', 11), bg='darkgray', command=data_search)
btn_find.grid(row=10, column=0, pady=20, padx=5)

btn_set_default2 = Button(btn_frame2, text='검색초기화', width=10, font=('명조', 11), bg='darkgray', command=search_set_default)
btn_set_default2.grid(row=10, column=1, pady=20, padx=5)

btn_del = Button(btn_frame2, text='데이터삭제', width=10, font=('명조', 11), bg='darkgray', command=data_delete)
btn_del.grid(row=10, column=3, pady=20, padx=5)


root.mainloop()

- 상품명 등의 입력 부분은 빈란일 경우 경고 팝업창이 표시되고, 입력 초기화를 통해 오입력 부분을 바로 삭제시킬 수 있으며, 동일한 상품명으로 입력 시 상품명이 있다는 팝업창이 표시됨

- 검색 함수 data_search()에서는 상품명 검색어(단어 등)로 둘 이상의 상품명이 검색될 때 이를 표시하는 팝업창이 노출되고 이를 통해 특정 상품명을 다시 검색하면 하나의 상품명만 검색되어 전체 내용이 표시되도로 하였음

- 데이터 삭제 함수는 open() 함수 mode를 읽기와 쓰기인 'r+'로 하여 readlines()을 새 변수에 저장하고, f.seek(0)로 포인터를 처음으로 보낸 후 새 변수를 for 문으로 순환시켜 상품명 검색어가 없으면 원본 파일에 다시 쓰고(f.write()), 마지막으로 truncate() 함수로 현재 이후의 나머지는 삭제하는 절차를 수행토록 함

 

good4me.co.kr

 

본 프로그램으로 일반적인 단축 URL 관리도 가능할 것으로 보이며, 

이후 더 보강해 볼 기능으로는

  • sqlite3을 활용하여 데이터 관리가 보다 더 잘 되도록 하는 것과
  • 입력된 내용 전체 보기와 수정 기능도 필요할 것으로 보이며,
  • 더 나아가 간혹 쿠팡 파트너스 또는 쿠팡의 상품 페이지에서 등록한 상품이 삭제되는 경우가 있어서 이를 관리하는 기능도 필요할 것으로 생각됨

 

구현된 기능의 GUI 보기

상품명 등 입력하지 않고 저장할 경우 팝업창 메시지
상품명 등 입력하지 않고 저장할 경우 팝업창 메시지

 

데이터 입력
데이터 입력

 

검색 시 찾은 데이터 개수가 2개 이상일 경우
검색 시 찾은 데이터 개수가 2개 이상일 경우

 

검색 상품명을 다시 특정하여 검색
검색 상품명을 다시 특정하여 검색

 

검색 결과, 전체 내용 표시
검색 결과, 전체 내용 표시

 

하나의 상품명 데이터 삭제
하나의 상품명 데이터 삭제

 

 

파이썬 tkinter 기본 배워보기>>

 

파이썬 Tkinter 처음부터 차근차근 따라 하면서 배워보기

파이썬 Tkinter는 파이썬으로 gui 프로그램을 만들 수 있도록 여러 컨테이너를 제공하는 라이브러리로 이를 배워두면 PC에서 실행할 수 있는 여러 응용 프로그램을 만들 수 있다. 그리고 tkinter는 bu

goodthings4me.tistory.com

 

 

댓글