웹툰 플랫폼은 다시 말해 웹툰 제공처입니다. 네이버 웹툰, 레진코믹스같이 웹툰 플랫폼으로 나온 플랫폼이 있는가 하면 네이버 블로그나 티스토리처럼 웹툰만은 위한 플랫폼은 아니지만 일부 사용자들이 웹툰도 올리는 식으로 사용되는 플랫폼들도 있습니다.
단순하게 웹툰 ID만 알면 다운로드 가능한 형태의 플랫폼도 있고, 로그인같은 특별한 방식을 사용해야 하는 경우도 있습니다.
하지만 반대로 이야기하면 이 플랫폼들은 로그인이 필요한 유료 회차나 3다무, 매일+ 다운로드 등을 지원하지 않는다는 이야기이기도 합니다. 이는 지원이 실질적으로 불가능한 경우도 있고, 단순히 아직까지 제작이 시도되지 않아서일수도 있습니다.
네이버의 경우 가장 단순한 자연수 기반의 웹툰 ID를 사용하지만 모든 웹툰 플랫폼이 그렇지는 않습니다. 아래에는 웹툰 플랫폼별로 사용하는 타입이 정리되어 있습니다. 추가 인증 요구 여부와 플랫폼 코드는 후술합니다.
플랫폼 이름
플랫폼 코드
플랫폼 코드 축약형
스크래퍼 이름
웹툰 ID로 사용되는 타입
예시
추가 인증 요구 여부
네이버 웹툰
'naver_webtoon'
nw
NaverWebtoonScraper
int
809590
아니오
webtoons.com
'webtoons_dotcom'
wd
WebtoonsDotcomScraper
int
5291
아니오
버프툰
'bufftoon'
bt
BufftoonScraper
int
1001216
예
네이버 포스트
'naver_post'
np
NaverPostScraper
tuple[int, int]
(597061, 19803452)
아니오
네이버 게임
'naver_game'
ng
NaverGameScraper
int
5
아니오
레진코믹스
'lezhin_comics'
lc
LezhinComicsScraper
str
"dr_hearthstone"
예
카카오페이지
'kakaopage'
kp
KakaopageScraper
int
53397318
아니오
네이버 블로그
'naver_blog'
nb
NaverBlogScraper
tuple[str, int]
("bkid4", 55)
아니오
티스토리
'tistory'
ti
TistoryScraper
tuple[str, str]
("doldistudio", "진돌만화")
아니오
카카오 웹툰
'kakao_webtoon'
kw
KakaoWebtoonScraper
int
1180
아니오
CLI 사용 방법
WebtoonScraper를 다운로드하면 webtoon 명령어를 사용할 수 있습니다.
c:\Users>webtoon -husage: Download or merge webtoons in CLIDownload webtoons with ease!...
만약 해당 명령어가 작동하지 않을 경우 python -m WebtoonScraper 명령어를 사용하세요.
c:\Users>python -m WebtoonScraper -husage: Download or merge webtoons in CLIDownload webtoons with ease!...
이 뒤부터는 webtoon 명령어를 사용합니다. 만약 오류가 난다면 모든 webtoon를 python -m WebtoonScraper로 바꿔서 진행하세요. 그래도 오류가 반복된다면 path를 포함한 파이썬 설치가 제대로 되었는지, 패키지 설치가 제대로 되었는지, 가상 환경 내에서만 설치된 것은 아닌지 확인하세요.
download 커맨드
웹툰을 다운로드하려면 플랫폼에 따라 2~3 가지가 필요합니다.
웹툰 플랫폼
웹툰 ID 혹은 URL
일부 로그인이 필요한 플랫폼이 경우 cookie또는 bearer를 필요로 할 수 있습니다.
기본적으로는 베스트 댓글을 대댓글 없이 다운로드하고 댓글을 불러오는 데에 실패했을 때 다운로드를 중단하지 않도록 설정되어 있습니다.
만약 이러한 기본 설정을 바꾸고 싶을 경우 옵션 뒤에 몇 가지 인자를 덧붙여줄 수 있습니다.
댓글을 전체 댓글을 다운로드받고 싶은 경우 all을 붙여 사용할 수 있습니다.
webtoon download "https://comic.naver.com/webtoon/list?titleId=819217" -c all
대댓글까지 다운로드하고 싶은 경우 reply를 붙여 사용할 수 있습니다.
이 인자들은 여려 개가 한번에 올 수 있으며 순서는 고려되지 않습니다.
webtoon download "https://comic.naver.com/webtoon/list?titleId=819217" -c all replywebtoon download "https://comic.naver.com/webtoon/list?titleId=819217" -c reply all
[!WARNING] 댓글 다운로드 기능은 현재 네이버 웹툰에서만 지원됩니다. 향후 더 다양한 플랫폼에서 지원을 확대할 예정입니다. 또한 웹툰 플랫폼에 따라 일부 댓글 옵션은 사용할 수 없을 수 있습니다. 현재 유일하게 지원되는 네이버 웹툰에서는 all 옵션과 reply 옵션 모두 지원하지 않으며 향후 지원을 확대할 예정입니다.
merge 커맨드
merge 커맨드는 웹툰 모아서 보기를 지원하기 위한 기능입니다.
다음과 같은 커맨드는 webtoon 디렉토리에 있는 웹툰 디렉토리들이 모두 리스팅되고 그중에서 번호를 선택해 고르면 merge가 진행됩니다.
webtoon merge webtoon
선택된 웹툰이 일반 웹툰 디렉토리라면 묶어지고, 이미 묶인 디렉토리라면 원래 상태로 복구됩니다.
이 과정에서 webtoon.html이 다시 제작됩니다.
실행 파일로 사용
실행 파일로 사용 시에는 CLI와 같은 명령어를 사용합니다.
설치 가이드에 설명된 방식으로 설치 후 실행한 뒤 CLI 사용 방법 가이드에 나와 있는 데로 사용하면 됩니다.
usage: Download or merge webtoons in CLIDownload webtoons with ease!...Welcome to WebtoonScraper shell!Type 'exit' to quit>>> (여기에 CLI 명령어를 입력하세요)
파이썬으로 사용
파이썬으로 접근해 더욱 다양한 이 패키지의 기능들을 사용하고 싶다면 WebtoonScraper.scrapers에 있는 여러 스크래퍼 클래스를 사용할 수 있습니다.
우선 스크래퍼를 다운로드하려면 WebtoonScraper.scrapers에서 자신이 원하는 스크래퍼를 import하면 됩니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper
그다음, 다음과 같은 코드를 통해 웹툰을 다운로드할 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraperscraper =NaverWebtoonScraper(809590)scraper.download_webtoon()
모든 스크래퍼에서 사용할 수 있는 기능이나 특징은 다음과 같습니다.
import
모든 스크래퍼는 WebtoonScraper.scrapers 안에 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper
스크래퍼 이름은 위의 표에 나와 있습니다.
초기화
스크래퍼들은 기본적으로 웹툰 ID를 첫 번째 인자로 받습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.download_webtoon()
이 값의 타입은 스크래퍼마다 차이가 있는데, 일반적으로는 int이지만, str이거나 tuple인 경우도 있습니다. 자세한 내용은 웹툰 플랫폼 파트에 있는 표에서 확인하실 수 있습니다.
from WebtoonScraper.scrapers import NaverBlogScraper# 예시 웹툰 URL: https://m.blog.naver.com/bkid4?categoryNo=55scraper =NaverBlogScraper(("bkid4", 55))# 특이한 형태의 타입의 예시scraper.download_webtoon()
혹은 Scraper.from_url을 통해 URL로부터 Scraper를 initialize할 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraperscraper = NaverWebtoonScraper.from_url("https://comic.naver.com/webtoon/list?titleId=809590")scraper.download_webtoon()
아래의 레진코믹스 예시처럼 별도의 인증을 요구하는 스크래퍼의 경우 특별한 인증 키가 필요한 경우가 있습니다.
from WebtoonScraper.scrapers import LezhinComicsScraperbearer ="YOUR BEARER HERE bearer를 여기에 위치시키세요\"cookie ="YOUR COOKIE HERE 쿠키를 여기에 위치시키세요\"# 예시 웹툰 URL: https://www.lezhin.com/ko/comic/dr_hearthstonescraper =LezhinComicsScraper("dr_hearthstone", bearer=bearer, cookie=cookie)scraper.download_webtoon()
다운로드
Scraper.download_webtoon()을 이용해 다운로드할 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.download_webtoon()
이때 async로 다운로드하고 싶다면 Scraper.async_download_webtoon()을 사용할 수도 있습니다.
다운로드 시, merge_number 파라미터를 이용해 회차 범위를 설정해 다운로드할 수 있습니다.
이때 범위는 다음과 같은 타입들로 할 수 있습니다.
특정 안 함(None): 모든 에피소드를 다운로드합니다.
int: 해당 에피소드 하나만 다운로드합니다.
(start, stop): start(int)부터 시작해서 stop(int)까지(stop을 포함합니다.) 다운로드합니다. 예를 들어 (2, 10)이면 2화부터 10화까지 10화를 포함하여 다운로드합니다.
(None, stop): (1, stop)과 동일합니다.
(start, None): start(int)부터 끝까지 다운로드합니다. 예를 들어 총 30화인 웹툰을 (3, None)으로 다운로드하면 (3, 30)과 동일하게 3화부터 30화까지 30화를 포함하여 다운로드합니다.
slice: slice 객체를 값으로 보낼 수도 있습니다. 예를 들어 slice(2, 11, 3)으로 다운로드하면 2, 5, 8화가 다운로드됩니다. 이때 마지막 인덱스에 해당하는 화(이 예시에서는 11화)는 포함되지 않는다는 것에 주의하세요.
tuple이 아닌 iterable: tuple이 아닌 iterable이라면 해당 iterable의 값에 맞추어 다운로드됩니다. 예를 들어 [3, 4, 6, 8]을 다운로드하면 3, 4, 6, 8화를 다운로드합니다. 이때 회차에서 벗어나는 값은 제외됩니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.download_webtoon(episode_no_range=(2, None))# 2화부터 끝까지 다운로드함.
웹툰 모아서 보기 설정하기
웹툰 모아서 보기는 다운로드와는 별개의 기능이지만 편리한 다운로드를 Scraper.download_webtoon()의 인자로도 제공됩니다.
merge_number를 None 이외의 값으로 설정하면 웹툰 디렉토리가 모아서 보기 형식으로 변환됩니다. 모아서 보기에 대한 자세한 내용에 대해서는 웹툰 모아서 보기 문서를 확인하세요.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.download_webtoon(merge_number=5)
웹툰 관련 모든 정보 불러오기
스크래퍼는 웹툰을 다운로드하는 데에 필요한 몇 가지 정보를 불러옵니다. 이때 공통적으로 다음과 같은 정보를 불러옵니다.
Scraper.fetch_webtoon_information()을 이용해 불러오는 정보들:
Scraper.webtoon_thumbnail_url: 웹툰 썸네일 URL
Scraper.title: 제목
Scraper.fetch_episode_information()을 이용해 불러오는 정보들:
Scraper.episode_titles: 각 에피소드의 제목
Scraper.episode_ids: 각 에피소드의 ID.
이때 Scraper.fetch_webtoon_information()와 Scraper.fetch_episode_information()를 구분하지 않고 다운로드하고 싶을 경우 Scraper.fetch_all을 사용할 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.fetch_all()# fetch_webtoon_information에서 가져온 정보와 fetch_episode_information 모두를 사용할 수 있음.print(scraper.title)print(scraper.episode_titles)
이때 Scraper.fetch_all()은 캐시되기 때문에 여러 번 실행하더라도 요청은 한 번만 보냅니다.
만약 이러한 캐시되는 것을 원하지 않는다면 reload=True로 두어 캐싱하지 않을 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)...scraper.fetch_all(reload=True)# 기존에 이미 불러와졌었더라도 다시 불러옴.
레진코믹스와 기타 몇몇 스크래퍼의 경우 추가적인 정보를 불러오기도 합니다. 이와 관련된 정보는 해당 스크래퍼에 대한 설명을 참고하세요.
에피소드 리스트화하기
에피소드는 리스트화해 정보를 눈으로 확인해볼 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.list_episodes()
웹툰을 볼 수 있는 HTML 페이지인 webtoon.html는 기본적으로 웹툰 디렉토리에 추가됩니다. 컴퓨터에서 이를 이용해 쉽게 웹툰을 볼 수 있습니다.
from WebtoonScraper.scrapers import NaverWebtoonScraper# 예시 웹툰 URL: https://comic.naver.com/webtoon/list?titleId=819217scraper =NaverWebtoonScraper(819217)scraper.download_webtoon(add_webtoon_viewer=True)
파이썬으로 모아서 보기
모아서 보기는 웹툰의 여러 회차를 한 데에 묶습니다. 예를 들어 5화씩 모아서 보기를 설정한다면 5화치 웹툰이 한 폴더를 사용하게 됩니다.
WebtoonScraper.directory_merger.merge_webtoon와 WebtoonScraper.directory_merger.restore_webtoon를 사용하면 됩니다.
from pathlib import Pathfrom WebtoonScraper.directory_merger import merge_webtoon, restore_webtoonsource_webtoon_directory =Path("webtoon/킬더킹(670145)")# 모아서 보기에 사용할 수 있도록 묶음.merge_webtoon(source_webtoon_directory)# 모아서 보기로 묶인 디렉토리 원 상태로 되돌림.restore_webtoon(source_webtoon_directory)
디렉토리/파일 상태
상태명
부모 디렉토리 상태
NORMAL_IMAGE
NORMAL_EPISODE_DIRECTORY
NORMAL_EPISODE_DIRECTORY
NORMAL_WEBTOON_DIRECTORY
MERGED_IMAGE
MERGED_EPISODE_DIRECTORY
MERGED_EPISODE_DIRECTORY
MERGED_WEBTOON_DIRECTORY
WEBTOON_DIRECTORY
WEBTOON_DIRECTORY_CONTAINER
플랫폼별 다운로드 방법 및 예시
플랫폼마다 다른 점이 아닌 공통적인 기능을 알고 싶은 경우 문서의 상단 부분을 확인하세요.
from WebtoonScraper.scrapers import BufftoonScrapercookie ="YOUR COOKIE HERE 쿠키를 여기에 위치시키세요.\"# 예시 웹툰 URL: https://bufftoon.plaync.com/series/1007888scraper =BufftoonScraper(1001216, cookie=cookie)scraper.download_webtoon()
from WebtoonScraper.scrapers import BufftoonScrapercookie ="YOUR COOKIE HERE 쿠키를 여기에 위치시키세요.\"scraper = BufftoonScraper.from_url("https://bufftoon.plaync.com/series/1007888", cookie=cookie)scraper.download_webtoon()
버프툰 쿠키 얻기
로그인하지 않으면 cookie를 얻을 수 없는데, 이 경우 다운로드할 수는 있지만 약 3화 정도로 다운로드받을 수 있는 웹툰이 폭이 심하게 제한됩니다. 그럼에도 쿠키 없이 다운로드하고 싶다면 아래 튜토리얼에서 쿠키와 관련된 부분을 무시하고 쿠키 인자는 넘기지 마세요.
이 과정은 PC를 기준으로 설명합니다. 만약 모바일이라면 Kiwi Browser 등을 통해 다음의 과정을 수행할 수 있습니다.
ID 복사
웹툰 페이지에 들어가 주소창의 맨 마지막 수를 복사합니다. 이 예시에서는 1007888입니다.
cookie 찾기
로그인을 한 후 f12를 누르고 네트워크 창을 연 뒤 웹툰 페이지에 들어갑니다.
새로고침을 한 뒤 '이름'에 있는 favicon.ico 요청을 클릭하고 나온 창에 '헤더' 탭을 엽니다.
내려서 Cookie: 라고 되어 있는 모든 내용을 복사합니다.
버프툰 다운로드 시 주의사항
download_webtoon에서 cookie를 입력하면 자동으로 버프툰으로 인식합니다.
favicon.ico가 요청에 뜨지 않는다면 ctrl+R을 해보고, 그래도 없다면 필터에서 모두로 설정되어 있는지 다시 확인하세요.
from WebtoonScraper.scrapers import LezhinComicsScraper
bearer = "YOUR BEARER HERE bearer를 여기에 위치시키세요"
cookie = None # 성인 웹툰을 다운로드받을 경우 설정할 것.
# 예시 웹툰 URL: https://www.lezhin.com/ko/comic/dr_hearthstone
scraper = LezhinComicsScraper("dr_hearthstone", bearer=bearer, cookie=cookie)
scraper.download_webtoon()
from WebtoonScraper.scrapers import LezhinComicsScraper
bearer = "YOUR BEARER HERE bearer를 여기에 위치시키세요"
cookie = None # 성인 웹툰을 다운로드받을 경우 설정할 것.
scraper = LezhinComicsScraper.from_url(
"https://www.lezhin.com/ko/comic/dr_hearthstone",
bearer=bearer,
cookie=cookie,
)
scraper.download_webtoon()
bearer 가져오기
bearer가 없는 경우 경우 다운로드할 수는 있지만 약 1~2화 정도로 다운로드받을 수 있는 웹툰이 폭이 심하게 제한됩니다.
이 과정은 PC를 기준으로 설명합니다. 만약 모바일이라면 Kiwi Browser 등을 통해 다음의 과정을 수행할 수 있습니다.
레진코믹스에 로그인합니다.
해당 웹툰의 페이지에 들어가 주소창의 맨 마지막 문자열을 복사합니다.
f12를 누르고 네트워크 창을 연 뒤 웹툰 페이지에 들어갑니다.
새로고침을 한 뒤 좌측 상단에 있는 검색창에 'balance'라고 검색한 뒤 balance 혹은 balance?lezhinObjectId...이라고(둘 중 무엇을 골라도 상관은 없습니다.) 되어 있는 요청을 클릭하고 나온 창에 '헤더' 탭을 엽니다.
"request headers"(혹은 "요청 헤더") 부분까지 내려서 Authorization: 이라고 되어 있는 부분을 찾고 "Bearer ..."라고 되어 있는 부분을 'Bearer'를 포함하여 모든 내용을 복사합니다.
from WebtoonScraper import Webtoon as wt
if __name__ == "__main__":
bearer = '두 번째로 복사했던 문자를 여기에다 붙여넣으세요.' # Bearer ...
wt.download_webtoon('dr_hearthstone', wt.L, bearer=bearer) # 첫 번째로 복사했던 수를 dr_hearthstone의 위치에 붙여넣으세요.
로그인하면 볼 수 있는 모든 에피소드가 다운로드됩니다.
bearer를 환경 변수로 설정
bearer는 직접 넘기는 대신 환경 변수를 통해 설정할 수도 있습니다. 만약 bearer를 넘기지 않거나 None으로 넘길 경우에 LEZHIN_BEARER 환경 변수가 설정되어 있다면 해당 환경 변수에 맞추어 설정됩니다.