본문 바로가기

❤25기/25기 세미나

[25기 세미나] BeautifulSoup와 tkinter로 웹툰 뷰어 만들기(2)

 

Canvas 이해하기

① Canvas란?

 

Canvas란 무엇일까요? 무언가 그릴 수 있는 공간이라고 생각하셨다면 정답입니다!
Canvas는 Tkinter 라는 Python 내장 라이브러리와 연동되어 Tkinter의 함수들을 이용해 화면에 다양한 요소들을 그릴수 있게 도와줍니다. 1차 세미나(1)에서 웹 크롤링에 대해 배웠다면 이번에는 Tkinter 라이브러리를 사용해 도형을 Canvas에 그려보겠습니다.

 


 

② tkinter 라이브러리와 주석

 

모듈을 불러오는 방법에는 크게 두 가지 방법이 있습니다.

 

import <모듈 이름> #첫번째 방법 
from <모듈 이름> import <변수나 함수 이름> #두번째 방법 

#예시 
import tkinter 
from tkinter import *

 

첫 번째는 모듈 전체를 불러오는 것이고

두 번째는 모듈 중 일부 함수나 변수를 콕 집어서 불러오는 것을 의미합니다.

두 번째 방법에서 사용된 '*' 기호는 '모든 것' 이라는 표현으로 프로그래밍에서 전반적으로 사용되는 표현입니다.

 

tkinter는 기본적으로 python이 지원해주는 기능이기 때문에 따로 설치 하지 않아도 사용할 수 있습니다.

그러면 tkinter 라이브러리를 불러와 볼까요?

위치는 지난 강의에서 불러온 os 라이브러리를 import 한 구문 아래에 입력해 주세요.

from bs4 import BeautifulSoup 
import requests 
import shutil import os 

#아래를 추가해 주세요!
from tkinter import *

 

Tip!
python2 에서는 Tkinter를 불러와야 하고 python3 에서는 tkinter을 불러와야 합니다.
첫글자의 대문자와 소문자 차이이지만 우리의 파이썬 버전은 3.x.x 이기 때문에 소문자인 tkinter을 사용합니다.

 


 

잘 import 하셨나요? 좋습니다!

앗 잠깐! 우리가 전 강의에서 했던 코드는 주석 처리를 해서 그림 그리기에 영향을 주지 않도록 해볼까요?

주석은 코드의 역할이나 기능을 적어 코드가 좀 더 이해하기 쉽게 도와주는 역할을 합니다. 

 

python에서 주석은 2가지 종류가 있습니다!

한 줄 주석과, 여러줄 주석입니다. 

# 파이썬의 한 줄 주석입니다. 

""" 파이썬의 여러 줄 주석입니다. 
큰 따옴표 3개를 연달아 씁니다.  """

''' 파이썬의 여러 줄 주석입니다.  
작은 따옴표 3개를 연달아 씁니다. '''

 

여러줄 주석의 차이점은 큰 따옴표와 작은 따옴표 인데요. 둘 중에 아무거나 쓰면 되지만 꼭 같은 종류의 따옴표로 주석을 끝내 주셔야 합니다! 

자 그럼! 여러줄 주석으로 기존 코드를 주석 처리 해 볼까요?

 

from bs4 import BeautifulSoup
import requests
import shutil
import os

from tkinter import *

"""
req = requests.get('https://comic.naver.com/webtoon/detail.nhn?titleId=715772&no=81&weekday=thu')
html = req.text

soup = BeautifulSoup(html, 'html.parser')

...

    if r.status_code == 200:
        with open('./img/'+img_name+'.png', 'wb') as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)
"""

이제 그림 그릴 준비가 끝났습니다! 어서 빨리 그려봐요!!

 

Tip!
흔히 말하는 * 기호는 애스터리스크(Asterisk) 라고 읽습니다.
흔히는 곱하기 연산자로 쓰이지만 C의 pointer 연산자로 쓰이기도 합니다.

 

 


 

함수 이해하기

 

① 도형그려보기

 

Tk 클래스라는 객체를 생성해서 Canvas를 만들어 봅시다!

master = Tk()  # tkinter 내부의 Tk 클래스를 master라는 변수로 생성해 줍니다

canvas_width = 300  # 캔버스의 가로를 미리 변수에 저장해 줍니다.
canvas_height = 200  # 캔버스의 세로를 미리 변수에 저장해 줍니다.

# Canvas 함수에 Tk 클래스와 width = 가로값, height= 세로값 을 인자값으로 넣어줍니다.
# 바로 값을 넣어도 좋지만 변수를 사용해 봅시다:)
canvas = Canvas(master, width=canvas_width, height=canvas_height)

# pack 함수는 캔버스의 불필요한 공간을 없애 포장해 주는 역할을 합니다.
canvas.pack()

# tk GUI를 실행합니다.
master.mainloop()

 

실행화면

저렇게 생긴 회색 창 하나가 뜬다면 성공입니다!

이제 그릴 수 있는 캔버스를 만들었으니 이제는 도형을 그려 봅시다!

도형은 create_<도형> 이라는 함수로 캔버스에 그릴 수 있습니다!

  • option
    • fill : 배경 색상
    • outline : 두께 색상
    • width : 두께
    • fill : 배경 색상
    • anchor : 위치 지정
    • 이외에도 여러 option이 존재함.

 

Canvas에 무언가를 그리기 위해서는 각 꼭짓점에 대한 좌표가 필요합니다!

사각형의 경우는 4개의 (x,y) 좌표가 필요하겠죠??

(50, 50)            (100, 50) 

(50, 100)          (100, 100)

이런 좌표의 사각형을 그려봅시다!

polygon = canvas.create_polygon(50, 50, 100, 50, 100, 100, 50, 100,  fill="yellow")

 

위 코드를 master. mainloop() 윗 부분에 추가하여 노란색 사각형이 그려지는지 확인해 보세요!

앞으로 우리가 사용할 캔버스 관련 코드는 mainloop() 위에 위치할 겁니다.  mainloop()을 잘 기억해 주세요!😊

 

Tip!
좌표는 왼쪽 상단부터 시계방향으로 입력하면 됩니다!

 


 

② 글씨 써보기

 

이제 그림도 그려봤으니! 글씨가 써보고 싶어졌어요😆

여러분도 궁금하지 않나요? 글자는 어떻게 쓸 수 있을까요??

 

우리 방금 전 도형을 그렸을 때 어떤 함수를 사용했는지 기억나나요?

바로 create_<도형>() 이라는 함수였습니다!

그렇다면 글씨를 그려주는 함수는 어떤 함수 일까요? 예상이 가시나요?

 

맞습니다! 바로 create_text() 라는 함수를 사용해서 글씨를 쓸 수 있습니다!

바로 한번 써볼까요?

text = canvas.create_text(canvas_width, canvas_height, text="연습")

 

create_text() 함수는 글씨가 그려질 x 좌표와 y좌표, 그리고 내용을 필요로 합니다.

여기서 사용한 canvas_width와 canvas_height 변수는 canvas를 생성 할 때 사용했던 캔버스의 가로와 세로 입니다.

 

한번 실행해 봅시다!

 

엇 문제가 생긴 것 같습니다! 글씨가 잘려서 제대로 보이지 않아요! 어떻게 된거죠??

 

모든 요소가 시작하는 기준 위치는 '왼쪽 상단 끝' 입니다.

즉 우리가 설정한 좌표는 캔버스의 사이즈 범위를 벗어났기 때문에 글씨가 잘린 것이죠.

 

그림을 보니 canvas_width의 1/2과 canvas_height의 1/2 으로 좌표를 설정하면 글씨가 딱! 캔버스의 가운데에 위치할 것 같습니다!

한번 해볼까요? 아까의 코드를 아래처럼 변경해 다시 실행해 봅시다!

 

text = canvas.create_text(canvas_width/2, canvas_height/2, text="연습")

 

이제 글씨가 제대로 나오네요! 우리는 이제 Tk의 캔버스를 대부분 다룬 것 같습니다!

이제 우리가 지난 강의에서 가져왔던 웹툰 이미지를 캔버스에 그릴 수 있을 것 같아요!

 


 

Canvas에 웹툰 띄우기

 

① Pillow 라이브러리

 

우리는 도형을 그리기 위해 create_<도형>() 이라는 함수를 글씨를 쓰기 위해 create_text()라는 함수를 사용했습니다.

이번에도 이미지를 가져오기 위해서는 create_image()라는 함수를 사용해야 할까요??

 

좋은 접근입니다! 대부분의 개발자들은 기능이 비슷한 함수들의 이름을 비슷하게 짓는 버릇이 있기 때문이죠!

이번에는 create_image() 함수와 새로운 라이브러리를 불러와 함께 써보겠습니다!

 

Pillow 라이브러리 설치하기

  • Pillow 혹은 PIL 라이브러리는 Python Image Library의 약자로 이름처럼 파이썬에서 Image 편집 관련 라이브러리 입니다!
  • 하지만 더이상 업데이트가 되지 않고 있기에 PIL을 계승한 Pillow 라이브러리를 사용하겠습니다.
  • PIL와 Pillow는 거의 동일시 되고 있습니다. import 하는 부분도 PIL을 사용하기 때문에 Pillow = PIL의 버젼 업! 이라고 생각하시면 편합니다.

 

외부 라이브러리이기 때문에 bs4를 설치한 것 처럼 새롭게 설치해 주어야 합니다!

 


 

  1. PyCharm의 메뉴 바에서 File -> Settings를 클릭합니다. (macOS의 경우 상단 바의 PyCharm -> preferences)
  2. Project: Practice -> Project interpreter에서 패키지 리스트 아래의 + 버튼을 클릭합니다.
  3. Available Packages 창에서 Pillow를 검색한 후 install package를 눌러 설치해줍니다.

설치가 끝났다면 이제 Pillow 라이브러리를 불러와야 겠죠?

위에서 말한 것 처럼 Pillow 라이브러리는 PIL 로 불러옵니다! 


from tkinter import * #아래를 추가해 주세요! from PIL import ImageTk, Image # PIL에서 ImageTk와 Image 기능만 불러옵니다.

from tkinter import *

#아래를 추가해 주세요!
from PIL import ImageTk, Image # PIL에서 ImageTk와 Image 기능만 불러옵니다.

 

우리는 PIL에서 ImageTk와 Image 기능만 사용할 것이기 때문에 이 두개를 콕 집어서 가져올게요!

위치는 tkinter 라이브러리를 불러온 구문 아래에 작성해 주세요!

 

 


 

② Canvas에 이미지 그리기

이제부터는 지난 챕터에서 배웠던 것들을 활용해서 이번 세미나의 목표였던 웹툰 뷰어를 만들어 보겠습니다.

 

먼저 새로운 걸 그리기 위해 캔버스를 깨끗하게 비워볼까요??

도형을 그렸던 부분과 글씨를 썼던 부분의 코드를 지워주세요!

 

자 이제 우리가 지난시간에 가져온 웹툰 이미지를 캔버스에 그려 봅시다!

PIL 라이브러리의  PhotoImage() 라는 함수는 Image 파일을 tkinter을 이용한 GUI 프로그램에서 사용가능한 객체로 바꿔주는 기능을 가지고 있습니다.

쉽게 말해 웹툰 이미지 파일을 우리가 만들었던 canvas에 사용할 수 있게 해주는 함수 입니다!

 

여러분은 이제 이렇게 생각할 수 있을 것입니다.

"PhotoImage() 함수로 이미지를 불러와서 create_image() 함수로 canvas에 그리면 되겠구나!"

 

이 생각을 실현하기 위해 아래 처럼 입력해서 한번 이미지를 불러와 볼까요?

img = ImageTk.PhotoImage(file="./img/0pic.png") canvas.create_image(0, 0, anchor=NW, image=img)

 

아래 처럼 이미지가 불러와 졌습니다!

딱 하나 아쉬운게 있다면 canvas의 크기가 이미지의 크기보다 작아서 이미지가 잘 안보이네요!

 

우리의 아쉬움을 해소 시켜줄 기능을 우리는 이미 불러왔습니다!

바로 PIL의 Image 인데요!  이 기능으로 이미지의 크기를 가져올 수 있습니다!

canvas의 크기를 불러온 이미지의 크기보다 살짝 크게 설정해 주면 우리는 불편함 없이 웹툰을 볼 수 있을 것 같아요!

 


 

③ 이미지 크기 만큼 캔버스 키우기

우리는 이미지의 크기를 얻어와서 캔버스의 크기를 변경하려고 합니다.

하지만 만약 이미지의 크기가 제각각이라 다음 이미지를 불러올 때 이미지가 제대로 보이지 않는다면 어떻게 하죠??

지금 바로 img 폴더에 가서 이미지의 크기를 비교해 보아요!

다행이도 우리가 가져온 이미지는 크기가 다 똑같은 것 같아요! 

놀랍게도 이런 발상으로 우리는 불필요한 코드를 줄였습니다! 이런 소소한 발상이 코드를 줄여주니 코드를 짜기 전에 한번 더 생각해 보는 자세가 필요합니다!

프로그래밍도 일종의 노동이니까요! 노동을 최소화 합니다!

자 그렇다면 처음 캔버스를 생성하는 부분에 이미지 크기를 넣어주면 캔버스가 자동으로 이미지 사이즈 만큼 커질 것 같군요!

해봅시다!

master = Tk()  # tkinter 내부의 Tk 클래스를 master라는 변수로 생성해 줍니다

img_size = Image.open("./img/0pic.png") # 이미지를 불러옵니다. 저는 가장 첫 번째로 불러왔습니다.

canvas_width, canvas_height = img_size.size  # 이미지의 사이즈를 가져와 가로, 세로에 저장합니다.

 

기존에는 숫자로 직접 캔버스의 사이즈를 저장했는데요! 이 부분을 아래 처럼 바꿔 이미지 사이즈에 맞춰줍니다!

master = Tk()  # tkinter 내부의 Tk 클래스를 master라는 변수로 생성해 줍니다

canvas_width = 300  # 캔버스의 가로를 미리 변수에 저장해 줍니다.
canvas_height = 200  # 캔버스의 세로를 미리 변수에 저장해 줍니다.

 

기존에는 숫자로 직접 캔버스의 사이즈를 저장했는데요! 이 부분을 아래 처럼 바꿔 이미지 사이즈에 맞춰줍니다!

master = Tk()  # tkinter 내부의 Tk 클래스를 master라는 변수로 생성해 줍니다

img_size = Image.open("./img/0pic.png") # 이미지를 불러옵니다. 저는 가장 첫 번째로 불러왔습니다.

canvas_width, canvas_height = img_size.size  # 이미지의 사이즈를 가져와 가로, 세로에 저장합니다.

여기서 잠깐! 아래 구문은 우리가 잘 모르는 것 같습니다. 변수 2개를 한번에 저장할 수도 있나요??

canvas_width, canvas_height = img.size # 캔버스의 세로를 미리 변수에 저장해 줍니다. 

 

네! 가능합니다! 왜냐하면 img.size 는 튜플을 반환해 주기 때문입니다!

 

튜플이 뭔가요??

튜플은 python의 자료형 중 하나로 (690, 1600)  이렇게 괄호에 둘러 쌓인 형태를 가지게 되는데요!

canvas_width에 690이 저장되고, canvas_height에 1600이 각각 저장 됩니다!

여러분이 2주차 스터디에서 배울 내용이기 때문에 지금은 튜플은 이런거구나~ 하고 넘어가 주시기 바랍니다!

 

자! 이제 실행해 보겠습니다~!

 

 

canvas의 사이즈가 커졌네요! 성공입니다!

 


 

인터페이스 꾸미기

① 총 몇개의 이미지를 저장했는지 찾아보기

 

방금 우리가 웹툰의 이미지를 캔버스에 그리는 것을 성공했다면! 이제는 연속적으로 이미지를 볼 수 있으면 더 좋을 것 같습니다.

먼저 우리가 평소에 웹툰을 어떻게 보고 있는지 생각해 볼까요?

 

저는 웹툰을 볼때 크게 2가지 방식으로 보는 것 같습니다.

  1. 위/아래 스크롤 형식
  2. 다음 페이지로 이동하는 방식

 

우리는 2번 방법 처럼 버튼을 눌러 다음 페이지가 이동되는 웹툰뷰어를 만들어 보겠습니다.

그 전에 img 폴더 안에 있는 이미지들을 모두 가져와 볼까요?

 

 

우리는 지난 강의에서 '반복문'을 통해 웹툰의 이미지를 숫자+'pic.png' 라는 이름으로 img 폴더에 저장했습니다.

위의 파일처럼 저장되어 있을 것입니다!

 

잠시만요! 여러분!!

이미지 파일의 이름에 있는 '숫자'를 통해 저장된 이미지를 순서대로 가져올 수 있을 것 같지 않나요?

맞아요! 우리가 이미지를 저장할 때 반복문이 숫자를 증가시키면서 이미지를 저장했으니 그 반대로 숫자로 이미지를 가져올 수도 있습니다~

 

우리가 몇 개의 이미지를 가져왔는지를 알 수 있는 코드는 지난 강의를 집중해서 수강했다면 바로 알 수 있을 것입니다~

 

바로 len(my_titles) 로 우리가 몇개의 이미지를  가져왔는지 알 수 있습니다!

아까 주석처리를 했던 부분을 주석을 풀어서 우리가 원하는 값이 맞는지 확인해 봅시다!

from bs4 import BeautifulSoup
import requests
import shutil
import os

from tkinter import *
from PIL import ImageTk, Image

"""(주석을 지워 봅시다!)
req = requests.get('https://comic.naver.com/webtoon/detail.nhn?titleId=715772&no=81&weekday=thu')
html = req.text

soup = BeautifulSoup(html, 'html.parser')

...

    if r.status_code == 200:
        with open('./img/'+img_name+'.png', 'wb') as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)
"""(주석을 지워 봅시다!)

print(len(my_titles)) # len(my_titles)을 출력해 우리가 가져온 이미지가 몇개 인지 확인합니다.
#print()문은 mainloop() 함수 위에 써주세요

# tk GUI를 실행합니다.
master.mainloop()

잘 작동 되나요? 저는 좀 느려지긴 했지만 잘 돌아가는 것 같습니다~!

저는 총  43  개가  출력되네요! 여러분도 그런가요??

 

좋아요! 이제  43 이라는 숫자를 가지고 다시 반복문으로 이미지를 가져와 봅시다!

 


 

② 반복문으로 모든 이미지를 배열에 넣기

 

저번 챕터에서 Pillow 라이브러리를 사용해 img를 캔버스에 그린 과정을 기억하나요??

img = ImageTk.PhotoImage(file="./img/0pic.png") 
canvas.create_image(0, 0, anchor=NW, image=img)

바로 이 코드였죠!  지난 챕터에서 사용한 이 코드를 43번 반복해서 이미지를 캔버스에 그려 보겠습니다!

위의 코드는 지워주세요! 그리고 그 자리에 아래 코드를 다시 작성해 주세요!

my_images = [] #my_images라는 바구니(배열)를 일단 만들어 둡니다.
my_image_number = 0

# 이미지를 가져와 my_images 바구니(배열)에 잠시 보관하는 것을 43번 반복합니다.
for i in range(0, len(my_titles)):
        img = Image.open("./img/"+str(i)+"pic.png")
        my_images.append(ImageTk.PhotoImage(img)) 
        

# 가장 처음 보여질 이미지를 그려줍니다~
image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=my_images[my_image_number])

 

짜잔~! 처음으로 배열이라는 개념이 등장했습니다!

이미지를 43개는 너무 많아서 어딘가에 잠시 보관해 둘 필요가 있습니다.

그럴 때 사용하는 것이 '배열'이라는 일종의 바구니 입니다! 

자세한 것은 2주차 스터디에서 배우니 그렇구나~ 하고 넘어가시면 됩니다!

 

이제 위의 코드를 더 자세히 살펴 볼까요?

my_images = [] #my_images라는 바구니(배열)를 일단 만들어 둡니다.
my_image_number = 0

# 이미지를 가져와 my_images 바구니(배열)에 잠시 보관하는 것을 43번 반복합니다.
for i in range(0, len(my_titles)):
        img = Image.open("./img/"+str(i)+"pic.png")
        my_images.append(ImageTk.PhotoImage(img)) 

이 코드는 이전 챕터에서도 사용했었죠! 이미지를 가져오는 코드입니다.

위의 코드로 이미지를 먼저 가져와서 my_images 라는 바구니에 넣어줍니다.

다만 바구니에 넣을 때는 다시 꺼낼때 tkinter가 바로바로 인식하기 쉽게 형식을 PhotoImage()라는 함수로 바꿔서 넣어줍니다!

 

이렇게 보니 별거 아니네요! 다음 코드로 넘어가서 살펴봅시다😉


# 가장 처음 보여질 이미지를 그려줍니다~

# 가장 처음 보여질 이미지를 그려줍니다~
image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=my_images[my_image_number])

create_image()는 우리에게 익숙해 보입니다!

이전 챕터에서도 사용했던 함수이죠! 이 함수는 canvas에 이미지를 띄어주는 코드입니다!

 

다만 못보던게 생겼죠! my_image_number 라는 친구는 

우리가 실제로 보고 있을 웹툰 이미지의 번호를 나타내 줍니다~

지금은 0으로 설정되어있기 때문에 첫 이미지를 불러와 주는 역할을 하고 있습니다! 

우리가 다음 이미지를 보고 싶다면 my_image_number 친구에게 더하기 1을 해주면 되는 거죠!!

 

자! 어려운 코드를 자세히 보니까 꽤 쉽네요~

그렇지만 저 코드만으로는 우리가 가져온 43개의 이미지를 한번에 다 볼 수 없습니다.

지금은 첫 번째 화면만 보여주고 있으니까요..! 다음 페이지를 보려면 my_image_number 친구를 증가 시켜주는 버튼이 있어야 할 것 같습니다!


③ "다음" 버튼 만들어 이동하기

우리 페이지를 이동시켜 줄 버튼을 만들기 전에 우리가 보고 있는 canvas의 크기를 약간 줄여 봅시다!

제 생각에는 1/2 정도면 적당한 것 같아요! 아래처럼 다시 사이즈를 줄여서 저장해 줍시다!

canvas_width, canvas_height = img_size.size  # 이미지의 사이즈를 가져와 가로, 세로에 저장합니다.

#사이즈 조정
canvas_width = int(canvas_width/2) # 다시 실행해도 너무 크다면 숫자 2를 3으로 변경합니다.
canvas_height = int(canvas_height/2) #여기 숫자도요..!

 

다시 실행해도 canvas의 크기가 너무 크다면 숫자 2 를 3 으로 변경해 주세요!

1/2가 아닌 1/3으로 줄이면 조금 더 작아질 겁니다!

 

이미지 사이즈로 canvas의 크기를 정해줬던 코드아래에 # 사이즈 조정 아래 부분을 넣어주세요! 

캔버스가 줄어들었다면 우리가 볼 이미지의 크기도 줄어들어야 겠죠??

 

my_images = [] #my_images라는 바구니(배열)를 일단 만들어 둡니다.
my_image_number = 0

# 이미지를 가져와 my_images 바구니(배열)에 잠시 보관하는 것을 43번 반복합니다.
for i in range(0, len(my_titles)):
        img = Image.open("./img/"+str(i)+"pic.png")
        # 이부분을 추가해 주세요~
        img = img.resize((canvas_width, canvas_height), Image.ANTIALIAS)
    
        my_images.append(ImageTk.PhotoImage(img)) 

우리 방금 만들었던 반복문 안에 # 이 부분을 추가해 주세요  밑의 코드를 넣어주세요!

윗 코드에서 canvas_width, canvas_height의 자체를 1/2 로 줄였으니 이제 이미지도 더 작게 나올거에요!

 

 

 

어때요? 줄어들었나요? 저는 한눈에 내용을 볼 수 있어서 이게 더 마음에 듭니다~!

큰 화면이 좋다면 변경하지 않아도 좋아요~

 


 

이제 버튼을 만들어 봅시다! # 다음 버튼 생성 아래 구문을 create_image() 아래에 입력해 줍시다!


# 가장 처음 보여질 이미지를 그려줍니다~ image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=my_images[my_image_number]) # 다음 버튼 생성 button = Button(master, text="다음") button.pack(side="bottom")

# 가장 처음 보여질 이미지를 그려줍니다~
image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=my_images[my_image_number])

# 다음 버튼 생성
button = Button(master, text="다음")
button.pack(side="bottom")

지금 까지의 코드는 모두 mainloop() 위에 작성되고 있다는 점을 잊지 않으셨죠??

 

좋습니다! 이제 실행해 볼까요?? 입력한 대로 버튼이 잘 나와 줬으면 좋겠습니다!

 

 

짜잔~! 버튼이 생겼어요!! 하지만 아무리 눌러도 화면이 이동되지 않습니다. 아직 기능을 넣지 않아서 인데요!

버튼을 누르면 생겨야 하는 기능들을 정리해 볼까요?

  1. 현재 보고 있는 페이지 번호가 한 페이지 더 증가가 되어야 합니다.
  2. 다음 페이지 번호의 이미지를 불러 와야 합니다.
  3. 모든 페이지를 봤는데 또 '다음' 버튼을 누른다면 오류가 생기지 않게 첫 번째 화면으로 돌아가야 합니다.

 

좋습니다! 그렇다면 이 기능들을 수행하는 onButton() 함수를 추가해 볼까요?

create_image() 아래 부분 부터 우리가 방금 전에 적었던 # 다음 버튼 생성 아래 내용인 button.pack() 까지 아래 코드로 바꿔 주세요.

# 다음 페이지 이동 기능
def onButton():
        global my_image_number, my_images, image_on_canvas
        
        my_image_number += 1 # 현재 페이지 번호를 다음 페이지 번호로 변경합니다

        if( my_image_number == len(my_images)): # 마지막 페이지라면 첫 화면으로 이동합니다
            my_image_number = 0
                
        canvas.itemconfig(image_on_canvas, image = my_images[my_image_number]) # 이미지를 다음 페이지의 이미지로 변경해 줍니다.
    

# 다음 버튼 생성
button = Button(master, text="다음", command=onButton) # command속성은 버튼에 onButton() 기능을 연결해 줍니다.
button.pack(side="bottom")

잘 바꾸셨나요?? 

그렇다면 실행해 봅시다! 우리가 생각 했던 대로 페이지가 잘 넘어 가나요??

'다음' 버튼을 눌러 페이지가 잘 넘어 가는지 확인해 봅시다!!

 

 

와~ 잘 넘어가는 것을 확인 할 수 있네요!!

축하합니다~! 우리는 파이썬으로 웹툰 뷰어를 완성했어요~!!!!😆

 

길고 긴 여정이었네요! 이것도 일종에 프로젝트가 될 수 있습니다!

처음으로 여러분은 프로젝트를 완성하셨네요!! 이 뿌듯함을 잊지 않으셨으면 좋겠습니다!

 

세미나를 끝까지 따라와 주셔서 감사합니다💛


전체코드

from bs4 import BeautifulSoup
import requests
import shutil
import os

from tkinter import *
from PIL import ImageTk, Image

req = requests.get('https://comic.naver.com/webtoon/detail.nhn?titleId=715772&no=81&weekday=thu')
html = req.text

soup = BeautifulSoup(html, 'html.parser')
my_titles = soup.select('#comic_view_area > div.wt_viewer > img')


directory = os.path.dirname('./img/')
if not os.path.exists(directory):
    os.makedirs(directory)

for i in range(len(my_titles)):
    img = soup.find("img", {"id": "content_image_" + str(i)})
    img_src = img.get("src")
    img_name = str(i) + "pic"
    r = requests.get(img_src, stream=True, headers={'User-agent': 'Mozilla/5.0'})

    if r.status_code == 200:
        with open('./img/'+img_name+'.png', 'wb') as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)


master = Tk()

img_size = Image.open("./img/0pic.png")
canvas_width, canvas_height = img_size.size 

#사이즈 조정
canvas_width = int(canvas_width/2)
canvas_height = int(canvas_height/2)

canvas = Canvas(master, width=canvas_width, height=canvas_height)

canvas.pack()

my_images = []
my_image_number = 0
for i in range(0, len(my_titles)):
    img = Image.open("./img/"+str(i)+"pic.png")
    img = img.resize((canvas_width, canvas_height), Image.ANTIALIAS)
    my_images.append(ImageTk.PhotoImage(img))

image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=my_images[my_image_number])


def onButton():
    global my_image_number, my_images, image_on_canvas
    my_image_number += 1
    if( my_image_number == len(my_images)):
        my_image_number = 0
    canvas.itemconfig(image_on_canvas, image = my_images[my_image_number])

button = Button(master, text="다음", command=onButton)
button.pack(side="bottom")

master.mainloop()