파이썬 Selenium으로 카카오페이지 웹툰 이미지 저장하기

 저번에 셀레니움을 이용해서 카카페 소설을 다운 받는 데에 성공했는데요. 이번엔 웹툰을 시도해봤습니다. 한 번 하고 나니까 쉽네요. 저번에 작성했던 코드에서 몇 가지만 수정하면 됩니다. 지난글은 아래 링크에서 확인하세요.
->파이썬 Selenium으로 카카오페이지 웹소설 다운 받기
파이썬 크롤링 연습 - Selenium 사용하기.

 Selenium으로 크롤링할 때는 실제로 브라우저창이 뜹니다. 직접 사이트를 이용할 때처럼 버튼을 누르고, 키보드를 누르는 걸 프로그램으로 작성하는 겁니다. 조금만 공부하면 크롤링할 때 자주 사용되는 또 다른 모듈, bs4보다 쉬우실 겁니다. 다만 하다 보면 제한이 있긴 합니다. 이건 모든 프로그램이 마찬가지예요. 실력이 좋다면 더 많은 걸 할 수 있겠죠.

※저장한 데이터를 배포할 경우 법적으로 처벌 받을 수 있습니다. 절대 공유하지 마시고 웬만하면 연습하신 뒤에 삭제하시길 바랍니다.

 일단 지난 글처럼 Selenium 패키지 설치하시고, 아래 블로그로 가서 브라우저에 맞는 selenium webdriver를 다운 받으세요. 목차 중에 'Install'에 있습니다. 설명에 나온 대로 다운 받으시면 됩니다.

 모듈을 불러오고 무료 웹툰 중에 아무거나 들어가서 1화의 링크를 변수에 집어 넣습니다.
->카카오페이지 홈:  https://page.kakao.com/main

import selenium
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import urllib
import urllib.request

URL = 'https://page.kakao.com/viewer?productId=00000000'

driver = webdriver.Chrome(executable_path='chromedriver')
driver.implicitly_wait(time_to_wait=1)
driver.get(URL)
 웹툰도 웹소설처럼 링크 뒷부분의 productId만 다릅니다. 반드시 1화로 들어간 후에 링크를 복사해서 붙여 넣으세요.
 이번에도 처음 1화를 눌렀을 때 나오는 '스크롤' 안내문을 클릭해서 없애야 합니다. 브라우저의 개발자 도구를 열어서 해당 요소를 찾아 xpath를 복사해주세요. 크롬의 개발자 도구 단축키는 F12입니다.

개발자 도구로 html 요소의 XPath를 복사하는 방법입니다.
[마우스 우클릭-Copy-Copy XPath]를 선택하시면 됩니다.

first = driver.find_element_by_xpath('붙여 넣는 곳')
first.click()
 click()함수는 해당 요소를 클릭한다는 의미입니다.

 웹툰과 웹소설의 다른 점은, 웹소설의 경우 여러 장의 페이지를 넘기면서 저장해야 하지만, 웹툰은 한 페이지에 전부 나온다는 것입니다. 우리는 스크롤을 천천히 내리면서 보기 때문에 쭉 이어져 있다고 생각할 수 있지만 실제로는 여러 장으로 분리되어 있습니다. 생각보다 엄청 많이 쪼개져 있어요.

'class'에 'disableImageSave'라고 쓰여 있는 게 전부 이미지입니다.
한 에피소드당 이미지 수는 모두 다릅니다.

 첫 번째 줄부터 XPath를 복사해 보시면, 맨 뒤 div[1]의 숫자만 변한다는 사실을 알 수 있습니다.
//*[@id="root"]/div[3]/div/div/div/div[1]/div[2]/img
//*[@id="root"]/div[3]/div/div/div/div[1]/div[3]/img
//*[@id="root"]/div[3]/div/div/div/div[1]/div[4]/img
...
 div[변수]로 코드를 작성하면 됩니다. 웹툰마다, 한 가지 웹툰 안에서도 에피소드마다 이미지 수가 다르기 때문에 무한 반복문을 사용한 뒤에 특정 조건에서 빠져나갈 수 있게 할 것입니다.
 조건은 오류 메시지인 'NoSuchElementException'으로 할 겁니다. 한 번 해보시면 알겠지만 만약 이미지가 40장까지 있을 경우, div[41]에서 'NoSuchElementException'이라는 오류가 뜨면서 멈추기 때문입니다. 오류 메시지에 예외를 두고 싶은 경우, 모듈을 하나 더 가져와야 합니다.
from selenium.common.exceptions import NoSuchElementException
 그래서 이미지를 저장하는 코드는 다음과 같이 작성하게 됩니다. 이제 요소를 찾지 못해도 프로그램이 멈추지 않고 반복문을 빠져나갑니다.
img_num = 1
  while True:
      try:
          img = driver.find_element_by_xpath('//*[@id="root"]/div[3]/div/div/div/div[1]/div[' + str(img_num) + ']/img')
          src = img.get_attribute('src')
          urllib.request.urlretrieve(src,'이미지 이름_%03d.png'%(img_num))
      except NoSuchElementException:  #마지막 이미지 저장 후 반복문을 빠져나감.
          break
      img_num = img_num+1
 try, except문을 사용했습니다. str(img_num)이라고 하는 이유는 img_num이 정수형 변수인데, 해당 함수에는 문자열만 입력할 수 있기 때문입니다. str()함수를 사용해 해당 코드에서만 숫자를 문자열로 바꿔줍니다.
 print함수로 숫자를 출력할 때, %03d라고 쓰면 숫자가 세 자리로 나옵니다. 예를 들어 1이면 001, 20이면 020으로 출력됩니다. 데이터를 저장할 때 유용한 방법이니 기억해두시길 바랍니다.
 이미지 파일의 확장자는 PNG, GIF, JPG 등 아무거나 편한 걸로 하시면 됩니다. 들여쓰기를 틀리지 않도록 주의하세요. 파이썬은 들여쓰기를 맞추는 것이 중요합니다.

 다음편으로 넘어가는 코드는 지난번과 동일합니다. 개발자 도구로 '다음편' 버튼의 XPath를 복사해 아래 코드에 붙여 넣으면 됩니다.
next_ep = driver.find_element_by_xpath('붙여 넣는 곳')
next_ep.click()
 이제 원하는 만큼 한 번에 다운로드할 수 있도록 코드 전체에 반복문을 씌웁니다. 완성한 코드는 다음과 같습니다. 직접 작성하면서 연습해 보세요!


import selenium
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException
import urllib
import urllib.request

URL = 'https://page.kakao.com/viewer?productId=00000000'

driver = webdriver.Chrome(executable_path='chromedriver')
driver.implicitly_wait(time_to_wait=1)
driver.get(URL)

name = '이미지 이름'
ep_num = 3    #몇 화까지 받을 것인가.

for ep in range(0, ep_num):
    #안내문 없애기
    try:
        first = driver.find_element_by_xpath('/html/body/div[3]/div/div/div')
        first.click()
    except NoSuchElementException:    #에피소드마다 XPath가 다른 경우가 있음.
        first = driver.find_element_by_xpath('/html/body/div[2]/div/div/div')
        first.click()
        
    #이미지 다운로드
    img_num = 1

    while True:
        try:
            img = driver.find_element_by_xpath('//*[@id="root"]/div[3]/div/div/div/div[1]/div[' + str(img_num) + ']/img')
            src = img.get_attribute('src')
            urllib.request.urlretrieve(src,'%s%03d_%03d.png'%(name,ep+1,img_num))
        except NoSuchElementException:  #마지막 이미지 저장 후 반복문을 빠져나감.
            break
        img_num = img_num+1
        
    #다음편 클릭
    next_ep = driver.find_element_by_xpath('붙여 넣는 곳')
    next_ep.click()


 실행하면 '이름001_001.png', '이름001_002.png', '이름001_003.png', ...로 저장됩니다. 카카페 웹소설은 한 에피소드당 100장이 넘는 경우가 없는데 웹툰은 이미지를 많이 쪼개기 때문에 100장이 넘어가는 경우가 있어서 저장할 때 숫자를 세 자리까지 표기되도록 했습니다. 이미지가 워낙 많아서 실행할 때 웹소설보다 시간이 좀 걸릴 겁니다. 문제가 된다면 완성된 코드는 내리겠습니다.

댓글 쓰기

0 댓글