본문 바로가기

파이썬 프로그래밍/파이썬 크롤링

[Python] Pillow 이미지 붙이기 예제. 웹툰 전부 붙이기

본 게시글은 먼저 이미지 붙이기를 선행학습 하셔야 이해하기 수월합니다.


[Python] Pillow를 활용한 이미지 썸네일/다운로드 처리 크롤링 <- 바로가기 (Pillow 설치부터 개념까지 게시되어 있습니다)


문제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import requests
from bs4 import BeautifulSoup
from IPython.display import Image
 
ep_url = 'http://comic.naver.com/webtoon/detail.nhn?titleId=20853&no=1093&weekday=tue'
html = requests.get(ep_url).text
soup = BeautifulSoup(html, 'html.parser')
 
for tag in soup.select('.wt_viewer img'):
    img_url = tag['src']
    img_name = os.path.basename(img_url)
    headers = {'Referer': ep_url}
    img_data = requests.get(img_url, headers=headers).content
    
    with open(img_name, 'wb') as f:
        f.write(img_data)
cs

여기서 이어가시면 됩니다.

이것은 딱봐도 잘려있는 이미지를 반복문을 사용해서 전부 다운받아오는 코드입니다.


이해가 안가시는분은 여기로-> [Python] requests 기초와 beautiful soup를 활용한 크롤링, [크롤링 준비]



풀이

1. 다운로드가 잘되었나 확인해보기

코드
1
Image(filename='20170529163407_0ed8a697d896451fee4bc3642fb46db8_IMAG01_1.jpg')
cs

확인

잘 나오네요. 따로 파일이름을 지정해주지 않았기 때문에 원본의 이미지이름 그대로 다운받아 왔습니다.


그럼 이미지 이름은 제가 어떻게 알았을까요?



개발자도구 모드에서 따라가서 찾아냈습니다.


혹은

이렇게 열어보면 가장 마지막에 다운된 사진을 확인할 수 있습니다.


2. 다운받은 이미지들이 반복문에서 써질때마다 저장한후 모아주기

이미 문제에서 반복문이 돌때마다 img_name을 열어서 img_data로 써주고 있습니다.
이 부분을 제가 약간 다르고 쉽고 규칙성이 있는 네이밍을 줘서 저장을 다시 하고 싶은데요
그렇게 해보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import os
import requests
from bs4 import BeautifulSoup
from IPython.display import Image
from PIL import Image as PILImage
 
 
ep_url = 'http://comic.naver.com/webtoon/detail.nhn?titleId=20853&no=1093&weekday=tue'
html = requests.get(ep_url).text
soup = BeautifulSoup(html, 'html.parser')
 
#차례대로 이미지를 저장할 리스트 생성
image_list = []
 
#반복문이 돌때마다 값을 누적시킬 변수
full_width, full_height = 00
 
 
for tag in soup.select('.wt_viewer img'):
    img_url = tag['src']
    img_name = os.path.basename(img_url)
    headers = {'Referer': ep_url}
    img_data = requests.get(img_url, headers=headers).content
    
    #파일 읽기/쓰기
    with open(img_name, 'wb') as f:
        #데이터를 써주기
        f.write(img_data)
        
        #지금 이미지를 im에 넣기
        im = PILImage.open(img_name)
        
        #가로, 세로 size를 지금 들러온 im에 맞춘다
        width, height = im.size
        
        #작업을 마친 이미지를 미리선언한 list에 차례대로 저장
        image_list.append(im)
        
        #최대 가로길이 설정. 가로의 x축0, y축은 im.size에서 수정한 가로너비
        full_width = max(full_width, width)
        
        #세로길이는 이미지가 누적될수록 계속 길어지므로 길이를 기존길이에서 더함
        full_height += height
cs

추가된 코드는 13번째줄 부터입니다.


주석으로 한줄한줄 설명 달아놨습니다

list를 사용한 이유?

- 이미지는 반복문이 한번 돌때마다 하나씩 들어오는 루프입니다.

그럴때마다 list에 하나씩 차곡차곡 저장하고, 나중에 캔버스에 사용할때 하나씩 빼서 캔버스에 저장하면 편할것 이라고 생각했습니다.


3. 캔버스 만들고 캔버스에 저장하기

이미지를 차례대로 설정하고 list에 저장하는 것은 2번에서 마쳤으니 이번엔 캔버스를 만들고 거기에 list의 값을 순서대로 차곡 차곡 정 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import os
import requests
from bs4 import BeautifulSoup
from IPython.display import Image
from PIL import Image as PILImage
 
 
ep_url = 'http://comic.naver.com/webtoon/detail.nhn?titleId=20853&no=1093&weekday=tue'
html = requests.get(ep_url).text
soup = BeautifulSoup(html, 'html.parser')
 
#차례대로 이미지를 저장할 리스트 생성
image_list = []
 
#반복문이 돌때마다 값을 누적시킬 변수
full_width, full_height = 00
 
 
for tag in soup.select('.wt_viewer img'):
    img_url = tag['src']
    img_name = os.path.basename(img_url)
    headers = {'Referer': ep_url}
    img_data = requests.get(img_url, headers=headers).content
    
    #파일 읽기/쓰기
    with open(img_name, 'wb') as f:
        #데이터를 써주기
        f.write(img_data)
        
        #지금 이미지를 im에 넣기
        im = PILImage.open(img_name)
        
        #가로, 세로 size를 지금 들러온 im에 맞춘다
        width, height = im.size
        
        #작업을 마친 이미지를 미리선언한 list에 차례대로 저장
        image_list.append(im)
        
        #최대 가로길이 설정. 가로의 x축0, y축은 im.size에서 수정한 가로너비
        full_width = max(full_width, width)
        
        #세로길이는 이미지가 누적될수록 계속 길어지므로 길이를 기존길이에서 더함
        full_height += height
                
#캔버스 설정. 배경은 흰색
canvas = PILImage.new('RGB', (full_width, full_height), 'white')
 
output_height = 0
 
#리스트에 있는 이미지를 캔버스에 덮어씌우기
for im in image_list:#이미지 하나하나, img_list는 im을 모아놓은 리스트
    #현재 이미지의 사이즈를 가로세로 변수에 넣는다
    width, height = im.size
    
    #캔버스에 현재 이미지를 붙여넣고(x축0, y축누적높이)
    canvas.paste(im, (0, output_height))
    
    #세로로 이미지를 붙이기 때문에 높이값을 누적시켜줘야 함
    output_height += height
 
#반복문을 돌면 저장!
canvas.save('merged.jpg')
cs

추가된 부분은 46번째 줄부터 입니다.

설명은 주석으로 달아놓았습니다.


full_height는 이미 최대크기로 올라가 있기 때문에

output_height로 바꿔서 사용했습니다.



결과확인

스크롤 막대가 엄청 작아지고 잘 붙은것을 확인하실 수 있습니다.



주석없앤 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import os
import requests
from bs4 import BeautifulSoup
from IPython.display import Image
from PIL import Image as PILImage
 
 
ep_url = 'http://comic.naver.com/webtoon/detail.nhn?titleId=20853&no=1093&weekday=tue'
html = requests.get(ep_url).text
soup = BeautifulSoup(html, 'html.parser')
 
image_list = []
full_width, full_height = 00
 
 
for tag in soup.select('.wt_viewer img'):
    img_url = tag['src']
    img_name = os.path.basename(img_url)
    headers = {'Referer': ep_url}
    img_data = requests.get(img_url, headers=headers).content
 
    with open(img_name, 'wb') as f:
        f.write(img_data)
        im = PILImage.open(img_name)
        width, height = im.size
        image_list.append(im)
        full_width = max(full_width, width)
        full_height += height
                
canvas = PILImage.new('RGB', (full_width, full_height), 'white')
output_height = 0
 
for im in image_list:
    width, height = im.size
    canvas.paste(im, (0, output_height))
    output_height += height
 
canvas.save('merged.jpg')
cs




피드백 혹은 틀린내용이나 그외 질문사항 댓글로 달아주시면 감사하겠습니다