/// <summary> /// <seealso cref="EpisodeInfo"/>의 새 인스턴스를 초기화합니다. /// </summary> /// <param name="title">회차 제목</param> /// <param name="episodeNo">에피소드 번호</param> /// <param name="imageUrls"></param> /// <param name="date">웹툰 등록일</param> public EpisodeInfo(EpisodeKey episodeKey, string title, string[] imageUrls, string date) { EpisodeTitle = title; EpisodeNo = episodeKey.EpisodeNo; EpisodeImageUrls = imageUrls; EpisodeDate = date; }
/// <summary> /// episodeKey가 지정하는 회차의 폴더 이름을 정의된 포맷 형식(<seealso cref="Config.EpisodeDirectoryNameFormat"/>)에 따라 생성합니다. /// </summary> /// <param name="episodeKey"></param> /// <returns></returns> private static string BuildEpisodeDirectoryName(WebtoonInfo webtoonInfo, EpisodeKey episodeKey) { string titleId = episodeKey.TitleId; int episodeNo = episodeKey.EpisodeNo; string date = webtoonInfo.Episodes[episodeKey.EpisodeNo].EpisodeDate; string webtoonTitle = webtoonInfo.WebtoonTitle; string episodeTitle = webtoonInfo.Episodes[episodeKey.EpisodeNo].EpisodeTitle; return(string.Format(config.EpisodeDirectoryNameFormat, titleId, episodeNo, date, ReplaceFolderName(webtoonTitle), ReplaceFolderName(episodeTitle))); }
/// <summary> /// episodeKey가 지정하는 회차의 폴더 이름을 정의된 포맷 형식(<seealso cref="Config.EpisodeDirectoryNameFormat"/>)에 따라 생성합니다. /// </summary> /// <param name="episodeKey"></param> /// <returns></returns> public string BuildEpisodeDirectoryName(EpisodeKey episodeKey) { string titleId = episodeKey.TitleId; int episodeNo = episodeKey.EpisodeNo; string date = webtoonInfo.Episodes[episodeKey.EpisodeNo].EpisodeDate; string webtoonTitle = webtoonInfo.WebtoonTitle; string episodeTitle = webtoonInfo.Episodes[episodeKey.EpisodeNo].EpisodeTitle; string webtoonWriter = webtoonInfo.WebtoonWriter; return(string.Format(ReplaceFolderName(config.EpisodeDirectoryNameFormat), titleId, episodeNo, date, ReplaceFolderName(webtoonTitle), ReplaceFolderName(episodeTitle), ReplaceFolderName(webtoonWriter))); }
/// <summary> /// "{0}({1}) [{2}/{3}] ({4:P}) [{5}]" /// <code>{0}:웹툰 제목</code> /// <code>{1}:웹툰 아이디</code> /// <code>{2}:현재 포지션</code> /// <code>{3}:총 작업수</code> /// <code>{4}:퍼센트</code> /// <code>{5}:회차 날짜</code> /// </summary> /// <param name="webtoonInfo"></param> /// <param name="ProgressTextFormat"></param> public static void UpdateWebtoonInfo(WebtoonInfo webtoonInfo, string ProgressTextFormat) { Agent agent = Agent.Instance; Parser.Parser parser = Parser.Parser.Instance; WebtoonKey webtoonKey = new WebtoonKey(webtoonInfo.WebtoonTitleId); //comic.naver.com에서 최신 회차의 EpisodeNo를 불러옵니다. agent.LoadPage(webtoonKey.BuildUrl()); int latestEpisodeNo = int.Parse(parser.GetLatestEpisodeNo()); //webtoonInfo중 가장 마지막 회차의 EpisodeNo를 불러옵니다. int lastEpisodeNo = webtoonInfo.GetLastEpisodeNo(); //웹툰 정보를 업데이트합니다. for (int episodeNo = lastEpisodeNo + 1; episodeNo <= latestEpisodeNo; episodeNo++) { EpisodeKey episodeKey = new EpisodeKey(webtoonKey.TitleId, episodeNo); agent.LoadPage(episodeKey.BuildUrl()); string currentEpisodeNo = parser.GetCurrentEpisodeNo(); if (!currentEpisodeNo.Equals(episodeNo.ToString())) { //비어있는 번호 건너뛰기 continue; } string episodeTitle = parser.GetEpisodeTitle(); string episodeDate = parser.GetEpisodeDate(); string[] imageUrls = parser.GetComicContentImageUrls(); webtoonInfo.Episodes.Add(episodeNo, new EpisodeInfo(episodeKey, episodeTitle, imageUrls, episodeDate)); ProgressChangedEvent(string.Format(ProgressTextFormat, webtoonInfo.WebtoonTitle, webtoonInfo.WebtoonTitleId, (episodeNo).ToString("D" + latestEpisodeNo.ToString().Length.ToString()), latestEpisodeNo, (decimal)(episodeNo) / latestEpisodeNo, webtoonInfo.Episodes[episodeNo].EpisodeDate, webtoonInfo.Episodes[episodeNo].EpisodeTitle)); } Console.WriteLine(); }
/// <summary> /// "{0}({1}) [{2}/{3}] ({4:P}) [{5}]" /// <code>{0}:웹툰 제목</code> /// <code>{1}:웹툰 아이디</code> /// <code>{2}:현재 포지션</code> /// <code>{3}:총 작업수</code> /// <code>{4}:퍼센트</code> /// <code>{5}:회차 날짜</code> /// </summary> /// <param name="webtoonInfo"></param> /// <param name="ProgressTextFormat"></param> public void UpdateWebtoonInfo(string ProgressTextFormat, IProgress <string> progress) { WebtoonKey webtoonKey = new WebtoonKey(webtoonInfo.WebtoonTitleId); //comic.naver.com에서 최신 회차의 EpisodeNo를 불러옵니다. agent.LoadPage(webtoonKey.BuildUrl()); int latestEpisodeNo = int.Parse(parser.GetLatestEpisodeNo()); //webtoonInfo중 가장 마지막 회차의 EpisodeNo를 불러옵니다. int lastEpisodeNo = webtoonInfo.GetLastEpisodeNo(); //웹툰 정보를 업데이트합니다. for (int episodeNo = lastEpisodeNo + 1; episodeNo <= latestEpisodeNo; episodeNo++) { EpisodeKey episodeKey = new EpisodeKey(webtoonKey.TitleId, episodeNo); agent.LoadPage(episodeKey.BuildUrl()); string currentEpisodeNo = parser.GetCurrentEpisodeNo(); if (!currentEpisodeNo.Equals(episodeNo.ToString())) { //비어있는 번호 건너뛰기 continue; } string episodeTitle = parser.GetEpisodeTitle(); string episodeDate = parser.GetEpisodeDate(); string[] imageUrls = parser.GetComicContentImageUrls(); webtoonInfo.Episodes.Add(episodeNo, new EpisodeInfo(episodeKey, episodeTitle, imageUrls, episodeDate)); progress.Report(string.Format(ProgressTextFormat, webtoonInfo.WebtoonTitle, webtoonInfo.WebtoonTitleId, (episodeNo).ToString("D" + latestEpisodeNo.ToString().Length.ToString()), latestEpisodeNo, (decimal)(episodeNo) / latestEpisodeNo, webtoonInfo.Episodes[episodeNo].EpisodeDate, webtoonInfo.Episodes[episodeNo].EpisodeTitle)); } Thread.Sleep(500); }
/// <summary> /// <code>{0}:웹툰 제목</code> /// <code>{1}:웹툰 아이디</code> /// <code>{2}:현재 포지션</code> /// <code>{3}:총 작업수</code> /// <code>{4}:퍼센트</code> /// <code>{5}:회차 날짜</code> /// <code>{6}:회차 제목</code> /// <code>{7}:이미지 인덱스</code> /// <code>{8}:이미지 파일명</code> /// <code>{9}:다운받은 메가바이트 용량</code> /// </summary> /// <param name="webtoonInfo"></param> /// <param name="imageKeys"></param> /// <param name="ProgressTextFormat"></param> public static void Download(WebtoonInfo webtoonInfo, ImageKey[] imageKeys, string ProgressTextFormat) { IO.taskEnd = false; Task t = new Task(new Action(() => { IO.SaveFileAsync(); })); Agent agent = Agent.Instance; long size = 0; t.Start(); for (int i = 0; i < imageKeys.Length; i++) { EpisodeKey episodeKey = new EpisodeKey(imageKeys[i].TitleId, imageKeys[i].EpisodeNo); agent.SetHeader("Referer", episodeKey.BuildUrl()); byte[] buff = agent.DownloadData(webtoonInfo.Episodes[imageKeys[i].EpisodeNo].EpisodeImageUrls[imageKeys[i].ImageIndex]); IO.WriteAllBytes( BuildImageFileFullDirectory(webtoonInfo, imageKeys[i]), BuildImageFileName(webtoonInfo, imageKeys[i]), buff); size += buff.Length; ProgressChangedEvent(string.Format(ProgressTextFormat, webtoonInfo.WebtoonTitle, webtoonInfo.WebtoonTitleId, i + 1, imageKeys.Length, (double)(i + 1) / imageKeys.Length, webtoonInfo.Episodes[imageKeys[i].EpisodeNo].EpisodeDate, webtoonInfo.Episodes[imageKeys[i].EpisodeNo].EpisodeTitle, imageKeys[i].ImageIndex, BuildImageFileName(webtoonInfo, imageKeys[i]), (double)size / 1048576 )); } IO.taskEnd = true; t.Wait(); Console.WriteLine(); }
public override void Start(params string[] args) { if (args.Length == 0) { IO.PrintError("titleId를 입력해주세요"); return; } List <WebtoonKey> keys = new List <WebtoonKey>(); List <string> titles = new List <string>(); for (int i = 0; i < args.Length; i++) { if (!int.TryParse(args[i], out _)) { IO.PrintError("titleId는 숫자입니다. : " + args[i]); return; } agent.LoadPage(string.Format("https://comic.naver.com/webtoon/list.nhn?titleId={0}", args[i])); string title = parser.GetWebtoonTitle(); if (title == "네이버 웹툰") { IO.PrintError("존재하지 않는 titleId입니다. : " + args[i]); return; } IO.Print(string.Format("{2}. {1}($${0}$cyan$) 대기..", args[i], title, i + 1), true, true); keys.Add(new WebtoonKey(args[i])); titles.Add(title); } for (int i = 0; i < keys.Count; i++) { Downloader downloader; IO.Print(""); WebtoonInfo webtoonInfo; if (IO.Exists("Cache", keys[i].TitleId + ".json")) { webtoonInfo = JsonConvert.DeserializeObject <WebtoonInfo>(IO.ReadTextFile("Cache", keys[i].TitleId + ".json")); downloader = new Downloader(webtoonInfo, config); int latest = int.Parse(parser.GetLatestEpisodeNo()); int last = webtoonInfo.GetLastEpisodeNo(); IO.Print(string.Format("{2}. {0}($${1}$cyan$) URl 캐시를 불러왔습니다.", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); IO.Print(string.Format("{2}. {0}($${1}$cyan$) 업데이트된 회차를 확인합니다.. ", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); if (latest != last) { IO.Print(string.Format("{4}. {0}($${1}$cyan$) URl 캐시를 업데이트합니다.. [no($${2}$cyan$) ~ no($${3}$cyan$)]", webtoonInfo.WebtoonTitle, keys[i].TitleId, last + 1, latest, i + 1), true, true); downloader.UpdateWebtoonInfo((i + 1).ToString() + ". {0}($${1}$cyan$) [{2}/{3}] ($${4:P}$green$) [{5}]", progress); Console.WriteLine(); IO.Print(string.Format("{2}. {0}($${1}$cyan$) URl 캐시에 업데이트된 회차를 추가하였습니다.", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); } else { IO.Print(string.Format("{2}. {0}($${1}$cyan$) 업데이트된 회차가 없습니다. ", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); } if (string.IsNullOrWhiteSpace(webtoonInfo.WebtoonWriter)) { EpisodeKey episodeKey = new EpisodeKey(keys[i].TitleId, 1); agent.LoadPage(episodeKey.BuildUrl()); string webtoonWriter = parser.GetWebtoonWriter(); webtoonInfo.WebtoonWriter = webtoonWriter; } var tuple = downloader.GetDownloadedImagesInformation(); if (tuple.downloadedImageCount != 0) { IO.Print(string.Format("{4}. {0}($${1}$cyan$) 이미 다운로드된 이미지 $${2}$cyan$장 ($${3:0.00}$blue$ MB) ", webtoonInfo.WebtoonTitle, keys[i].TitleId, tuple.downloadedImageCount, (double)tuple.downloadedImagesSize / 1048576, i + 1), true, true); } } else { webtoonInfo = new WebtoonInfo(keys[i], titles[i]); downloader = new Downloader(webtoonInfo, config); IO.Print(string.Format("{2}. {0}($${1}$cyan$) URl 캐시를 생성합니다.", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); downloader.UpdateWebtoonInfo((i + 1).ToString() + ". {0}($${1}$cyan$) [{2}/{3}] ($${4:P}$green$) [{5}]", progress); Console.WriteLine(""); IO.Print(string.Format("{2}. {0}($${1}$cyan$) URl 캐시를 생성하였습니다..", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); } if (string.IsNullOrWhiteSpace(webtoonInfo.WebtoonWriter)) { EpisodeKey episodeKey = new EpisodeKey(keys[i].TitleId, 1); agent.LoadPage(episodeKey.BuildUrl()); string webtoonWriter = parser.GetWebtoonWriter(); webtoonInfo.WebtoonWriter = webtoonWriter; } IO.WriteTextFile("Cache", keys[i].TitleId + ".json", JsonConvert.SerializeObject(webtoonInfo)); ImageKey[] imageKeys = downloader.BuildImageKeysToDown(); if (imageKeys.Length == 0) { IO.Print(string.Format("{2}. {0}($${1}$cyan$) 모든 이미지가 다운로드되었습니다..추가로 다운로드할 이미지가 존재하지 않습니다.", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); return; } IO.Print(string.Format("{2}. {0}($${1}$cyan$) 다운로드를 시작합니다. ", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); var task = Task.Run(() => downloader.DownloadAsync(imageKeys, (i + 1).ToString() + ". {0}($${1}$cyan$) [{2}/{3}] ($${9:0.00}$blue$ MB) ($${4:P}$green$) [{5}]", progress)); task.Wait(); Console.WriteLine(); IO.Print(string.Format("{2}. {0}($${1}$cyan$) 다운로드 완료", webtoonInfo.WebtoonTitle, keys[i].TitleId, i + 1), true, true); } }