From b7c6e530ddd82ded2b37b7ea4064c937ce864b0b Mon Sep 17 00:00:00 2001 From: SeungHo Yang Date: Sun, 6 Jul 2025 23:49:08 +0900 Subject: [PATCH] 2025-07-06 19:30~ 21:35, 10:30 ~ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chrome Web Driver 추가(신규 복본검사 로직용) 도서관 검색버튼 추가 도서관 선택없이 검색시작을 누르면 오류 표시 도서관 DB 정보에 신규로직용 식별 키(SearcherNo:int) 추가 - 광주광역시 남구 (문화, 청소년, 스마트, 푸른길) --- unimarc/unimarc/App.config | 34 +- unimarc/unimarc/Main.Designer.cs | 25 +- unimarc/unimarc/Main.cs | 8 + unimarc/unimarc/Program.cs | 6 + unimarc/unimarc/Properties/AssemblyInfo.cs | 4 +- .../unimarc/SearchModel/BookSearchService.cs | 82 ++++ .../SearchModel/ChromeDriverManager.cs | 378 +++++++++++++++ .../SearchModel/DownloadProgressForm.cs | 142 ++++++ .../unimarc/SearchModel/ILibrarySearcher.cs | 17 + .../SearchModel/KwangjuCityLibrarySearcher.cs | 321 +++++++++++++ .../SearchModel/NamguLibrarySearcher.cs | 441 ++++++++++++++++++ unimarc/unimarc/UniMarc.csproj | 74 ++- unimarc/unimarc/UniMarc.csproj.user | 1 + unimarc/unimarc/packages.config | 20 +- .../마크/Check_Copy_Sub_Search.Designer.cs | 12 +- unimarc/unimarc/마크/Check_Copy_Sub_Search.cs | 20 +- .../unimarc/마크/Check_Copy_Sub_Search.resx | 3 + unimarc/unimarc/마크/Check_copy.Designer.cs | 66 ++- unimarc/unimarc/마크/Check_copy.cs | 379 ++++++++++++--- unimarc/unimarc/마크/Check_copy.resx | 3 + 20 files changed, 1906 insertions(+), 130 deletions(-) create mode 100644 unimarc/unimarc/SearchModel/BookSearchService.cs create mode 100644 unimarc/unimarc/SearchModel/ChromeDriverManager.cs create mode 100644 unimarc/unimarc/SearchModel/DownloadProgressForm.cs create mode 100644 unimarc/unimarc/SearchModel/ILibrarySearcher.cs create mode 100644 unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs create mode 100644 unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs diff --git a/unimarc/unimarc/App.config b/unimarc/unimarc/App.config index 938db20..c35a7d9 100644 --- a/unimarc/unimarc/App.config +++ b/unimarc/unimarc/App.config @@ -1,12 +1,12 @@ - + - +
- + @@ -18,19 +18,31 @@ - - + + - - + + + + + + + + + + + + + + + + + + diff --git a/unimarc/unimarc/Main.Designer.cs b/unimarc/unimarc/Main.Designer.cs index 94a22d8..cafc2cd 100644 --- a/unimarc/unimarc/Main.Designer.cs +++ b/unimarc/unimarc/Main.Designer.cs @@ -132,6 +132,7 @@ this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.IPText = new System.Windows.Forms.ToolStripLabel(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.lblStatus = new System.Windows.Forms.ToolStripLabel(); this.menuStrip1.SuspendLayout(); this.panel1.SuspendLayout(); this.toolStrip1.SuspendLayout(); @@ -761,48 +762,48 @@ this.이용자관리ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.신규사업자등록ToolStripMenuItem}); this.이용자관리ToolStripMenuItem.Name = "이용자관리ToolStripMenuItem"; - this.이용자관리ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.이용자관리ToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.이용자관리ToolStripMenuItem.Text = "이용자 관리"; // // 신규사업자등록ToolStripMenuItem // this.신규사업자등록ToolStripMenuItem.Name = "신규사업자등록ToolStripMenuItem"; - this.신규사업자등록ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.신규사업자등록ToolStripMenuItem.Size = new System.Drawing.Size(138, 22); this.신규사업자등록ToolStripMenuItem.Text = "사업자 관리"; this.신규사업자등록ToolStripMenuItem.Click += new System.EventHandler(this.신규사업자등록ToolStripMenuItem_Click); // // 공지발송ToolStripMenuItem1 // this.공지발송ToolStripMenuItem1.Name = "공지발송ToolStripMenuItem1"; - this.공지발송ToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.공지발송ToolStripMenuItem1.Size = new System.Drawing.Size(178, 22); this.공지발송ToolStripMenuItem1.Text = "공지 발송"; this.공지발송ToolStripMenuItem1.Click += new System.EventHandler(this.공지발송ToolStripMenuItem1_Click); // // 매출내역ToolStripMenuItem // this.매출내역ToolStripMenuItem.Name = "매출내역ToolStripMenuItem"; - this.매출내역ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.매출내역ToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.매출내역ToolStripMenuItem.Text = "매출내역"; this.매출내역ToolStripMenuItem.Click += new System.EventHandler(this.매출내역ToolStripMenuItem_Click); // // 이용자거래처조회ToolStripMenuItem // this.이용자거래처조회ToolStripMenuItem.Name = "이용자거래처조회ToolStripMenuItem"; - this.이용자거래처조회ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.이용자거래처조회ToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.이용자거래처조회ToolStripMenuItem.Text = "이용자 거래처 조회"; this.이용자거래처조회ToolStripMenuItem.Click += new System.EventHandler(this.이용자거래처조회ToolStripMenuItem_Click); // // 마크설정ToolStripMenuItem // this.마크설정ToolStripMenuItem.Name = "마크설정ToolStripMenuItem"; - this.마크설정ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.마크설정ToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.마크설정ToolStripMenuItem.Text = "마크설정"; this.마크설정ToolStripMenuItem.Click += new System.EventHandler(this.마크설정ToolStripMenuItem_Click); // // 일괄처리관리ToolStripMenuItem // this.일괄처리관리ToolStripMenuItem.Name = "일괄처리관리ToolStripMenuItem"; - this.일괄처리관리ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.일괄처리관리ToolStripMenuItem.Size = new System.Drawing.Size(178, 22); this.일괄처리관리ToolStripMenuItem.Text = "일괄처리 관리"; this.일괄처리관리ToolStripMenuItem.Click += new System.EventHandler(this.일괄처리관리ToolStripMenuItem_Click); // @@ -1008,7 +1009,8 @@ this.botUserLabel, this.toolStripSeparator2, this.toolStripSeparator3, - this.IPText}); + this.IPText, + this.lblStatus}); this.toolStrip1.Location = new System.Drawing.Point(0, 681); this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Size = new System.Drawing.Size(1259, 25); @@ -1057,6 +1059,12 @@ this.IPText.Size = new System.Drawing.Size(154, 22); this.IPText.Text = "접속 아이피 : 0.000.00.000"; // + // lblStatus + // + this.lblStatus.Name = "lblStatus"; + this.lblStatus.Size = new System.Drawing.Size(27, 22); + this.lblStatus.Text = "WD"; + // // Main // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -1188,5 +1196,6 @@ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; public System.Windows.Forms.ToolStripLabel IPText; + private System.Windows.Forms.ToolStripLabel lblStatus; } } \ No newline at end of file diff --git a/unimarc/unimarc/Main.cs b/unimarc/unimarc/Main.cs index 9bc074a..8e86812 100644 --- a/unimarc/unimarc/Main.cs +++ b/unimarc/unimarc/Main.cs @@ -27,6 +27,7 @@ using UniMarc.마크; using UniMarc.Properties; using UniMarc; + namespace WindowsFormsApp1 { public partial class Main : Form @@ -40,12 +41,17 @@ namespace WindowsFormsApp1 public Main() { InitializeComponent(); + + } public string User_Name { get; internal set; } private void Main_Load(object sender, EventArgs e) { + + + this.Visible = false; // 메인폼을 먼저 숨김 #region "Log setting" @@ -102,6 +108,8 @@ namespace WindowsFormsApp1 } + + #region 즐겨찾기 버튼 세팅 public void SetBtnName() { diff --git a/unimarc/unimarc/Program.cs b/unimarc/unimarc/Program.cs index c35cb1f..20d10a6 100644 --- a/unimarc/unimarc/Program.cs +++ b/unimarc/unimarc/Program.cs @@ -18,9 +18,15 @@ namespace WindowsFormsApp1 Application.SetCompatibleTextRenderingDefault(false); DB_InitSetting(); UpdaterCheck(); + Application.Run(new Main()); } + + + + + /// /// factory client update checkd /// diff --git a/unimarc/unimarc/Properties/AssemblyInfo.cs b/unimarc/unimarc/Properties/AssemblyInfo.cs index 20f14fd..a931ff9 100644 --- a/unimarc/unimarc/Properties/AssemblyInfo.cs +++ b/unimarc/unimarc/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 // 기본값으로 할 수 있습니다. // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.185")] -[assembly: AssemblyFileVersion("1.0.0.185")] +[assembly: AssemblyVersion("1.0.0.186")] +[assembly: AssemblyFileVersion("1.0.0.186")] diff --git a/unimarc/unimarc/SearchModel/BookSearchService.cs b/unimarc/unimarc/SearchModel/BookSearchService.cs new file mode 100644 index 0000000..6debbb7 --- /dev/null +++ b/unimarc/unimarc/SearchModel/BookSearchService.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; + +namespace BokBonCheck +{ + public class BookSearchResult + { + public string SiteName { get; set; } + public int BookCount { get; set; } + public string SearchTerm { get; set; } + public DateTime SearchTime { get; set; } + public string ErrorMessage { get; set; } + public bool IsSuccess { get; set; } + } + + public class BookSearchService + { + private readonly List _searchers; + + public BookSearchService() + { + _searchers = new List + { + }; + } + + public async Task> SearchBooksAsync(string searchTerm) + { + var results = new List(); + + foreach (var searcher in _searchers) + { + searcher.StartDriver(); + var result = await searcher.SearchAsync(searchTerm); + results.Add(result); + //searcher.StopDriver(); + } + + return results; + } + + /// + /// Return Searcher + /// + /// + /// + public ILibrarySearcher Get(int no) + { + return _searchers.Where(t => t.No == no).FirstOrDefault(); + } + public void AddSearcher(ILibrarySearcher searcher) + { + if (!_searchers.Any(s => s.SiteName == searcher.SiteName)) + { + _searchers.Add(searcher); + } + } + + public void RemoveSearcher(string siteName) + { + var searcher = _searchers.FirstOrDefault(s => s.SiteName == siteName); + if (searcher != null) + { + _searchers.Remove(searcher); + } + } + + public List GetAvailableSites() + { + return _searchers.Select(s => s.SiteName).ToList(); + } + + public void ClearSearchers() + { + _searchers.Clear(); + } + + + } +} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/ChromeDriverManager.cs b/unimarc/unimarc/SearchModel/ChromeDriverManager.cs new file mode 100644 index 0000000..a864b52 --- /dev/null +++ b/unimarc/unimarc/SearchModel/ChromeDriverManager.cs @@ -0,0 +1,378 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using WebDriverManager; +using WebDriverManager.DriverConfigs.Impl; +using System.Reflection; +using System.Net.Http; +using System.Threading; +using System.IO.Compression; + +namespace BokBonCheck +{ + public static class ChromeDriverManager + { + private static string _driverPath = null; + + public static async Task SetupChromeDriverAsync(DownloadProgressForm progressForm = null) + { + try + { + // Chrome 버전 확인 + var chromeVersion = GetChromeVersion(); + Console.WriteLine($"설치된 Chrome 버전: {chromeVersion}"); + + if (progressForm != null) + { + progressForm.UpdateProgress(10, $"Chrome 버전 확인 중... ({chromeVersion})"); + } + + // 기존 드라이버 경로 확인 + var existingDriverPath = GetExistingDriverPath(); + if (!string.IsNullOrEmpty(existingDriverPath) && File.Exists(existingDriverPath)) + { + Console.WriteLine($"기존 드라이버 발견: {existingDriverPath}"); + + // 기존 드라이버 테스트 + if (await TestExistingDriver(existingDriverPath)) + { + if (progressForm != null) + { + progressForm.UpdateProgress(100, "기존 드라이버 사용"); + progressForm.SetCompleted("기존 드라이버를 사용합니다."); + } + + _driverPath = existingDriverPath; + Environment.SetEnvironmentVariable("webdriver.chrome.driver", existingDriverPath); + return existingDriverPath; + } + else + { + Console.WriteLine("기존 드라이버 테스트 실패 - 새로 다운로드"); + // 기존 드라이버가 작동하지 않으면 삭제 + try + { + File.Delete(existingDriverPath); + Console.WriteLine("기존 드라이버 삭제됨"); + } + catch (Exception ex) + { + Console.WriteLine($"기존 드라이버 삭제 실패: {ex.Message}"); + } + } + } + + if (progressForm != null) + { + progressForm.UpdateProgress(30, "Chrome 버전에 맞는 드라이버 다운로드 중..."); + } + + // WebDriverManager를 사용하여 설치된 Chrome 버전에 맞는 드라이버 다운로드 + var driverManager = new DriverManager(); + var driverPath = driverManager.SetUpDriver(new ChromeConfig(), "MatchingBrowser"); + + // 다운로드된 드라이버 경로 저장 + _driverPath = driverPath; + + // 환경 변수 설정 + Environment.SetEnvironmentVariable("webdriver.chrome.driver", driverPath); + + if (progressForm != null) + { + progressForm.UpdateProgress(100, "드라이버 다운로드 완료"); + progressForm.SetCompleted("드라이버 다운로드 완료!"); + } + + Console.WriteLine($"ChromeDriver 경로: {driverPath}"); + Console.WriteLine($"환경 변수 설정: webdriver.chrome.driver = {driverPath}"); + + return driverPath; + } + catch (Exception ex) + { + Console.WriteLine($"ChromeDriver 설정 오류: {ex.Message}"); + if (progressForm != null) + { + progressForm.SetError($"설정 오류: {ex.Message}"); + } + throw; + } + } + + private static string GetExistingDriverPath() + { + try + { + // 환경 변수에서 확인 + var envPath = Environment.GetEnvironmentVariable("webdriver.chrome.driver"); + if (!string.IsNullOrEmpty(envPath) && File.Exists(envPath)) + { + return envPath; + } + + // WebDriverManager 캐시 폴더에서 확인 + var cachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + ".cache", "selenium"); + if (Directory.Exists(cachePath)) + { + var chromeDriverFiles = Directory.GetFiles(cachePath, "chromedriver*", SearchOption.AllDirectories); + foreach (var file in chromeDriverFiles) + { + if (file.EndsWith(".exe") || !Path.HasExtension(file)) + { + return file; + } + } + } + + return null; + } + catch + { + return null; + } + } + + public static string GetDriverPath() + { + return _driverPath; + } + + private static string GetChromeVersion() + { + try + { + // Windows에서 Chrome 설치 경로 확인 + var chromePaths = new[] + { + @"C:\Program Files\Google\Chrome\Application\chrome.exe", + @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + @"Google\Chrome\Application\chrome.exe") + }; + + foreach (var path in chromePaths) + { + if (File.Exists(path)) + { + var versionInfo = FileVersionInfo.GetVersionInfo(path); + var version = versionInfo.FileVersion; + Console.WriteLine($"Chrome 버전 감지: {version} (경로: {path})"); + return version; + } + } + + return "알 수 없음"; + } + catch (Exception ex) + { + Console.WriteLine($"Chrome 버전 감지 실패: {ex.Message}"); + return "확인 실패"; + } + } + + public static bool IsChromeInstalled() + { + try + { + var chromePaths = new[] + { + @"C:\Program Files\Google\Chrome\Application\chrome.exe", + @"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + @"Google\Chrome\Application\chrome.exe") + }; + + foreach (var path in chromePaths) + { + if (File.Exists(path)) + { + return true; + } + } + + return false; + } + catch + { + return false; + } + } + + public static async Task TestChromeDriverAsync(DownloadProgressForm progressForm = null) + { + try + { + var driverPath = await SetupChromeDriverAsync(progressForm); + + if (progressForm != null) + { + progressForm.UpdateProgress(50, "드라이버 테스트 중..."); + } + + // ChromeDriver 서비스 설정 + var service = OpenQA.Selenium.Chrome.ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath)); + service.HideCommandPromptWindow = true; + // 간단한 테스트 실행 + var options = new OpenQA.Selenium.Chrome.ChromeOptions(); + options.AddArgument("--headless"); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + options.AddArgument("--disable-gpu"); + options.AddArgument("--remote-debugging-port=0"); + + using (var driver = new OpenQA.Selenium.Chrome.ChromeDriver(service, options)) + { + driver.Navigate().GoToUrl("https://www.google.com"); + var title = driver.Title; + + Console.WriteLine($"드라이버 테스트 성공: {title}"); + + if (progressForm != null) + { + progressForm.UpdateProgress(100, "드라이버 테스트 성공!"); + progressForm.SetCompleted("드라이버 테스트 성공!"); + } + + return !string.IsNullOrEmpty(title); + } + } + catch (Exception ex) + { + Console.WriteLine($"ChromeDriver 테스트 실패: {ex.Message}"); + if (progressForm != null) + { + progressForm.SetError($"테스트 실패: {ex.Message}"); + } + return false; + } + } + + public static void ClearDriverCache() + { + try + { + Console.WriteLine("Chrome 드라이버 캐시 정리 시작..."); + + // WebDriverManager 캐시 폴더 정리 + var cachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + ".cache", "selenium"); + if (Directory.Exists(cachePath)) + { + Directory.Delete(cachePath, true); + Console.WriteLine($"WebDriverManager 캐시 정리됨: {cachePath}"); + } + + // 환경 변수에서 설정된 드라이버 경로도 정리 + var envDriverPath = Environment.GetEnvironmentVariable("webdriver.chrome.driver"); + if (!string.IsNullOrEmpty(envDriverPath) && File.Exists(envDriverPath)) + { + try + { + File.Delete(envDriverPath); + Console.WriteLine($"환경 변수 드라이버 삭제됨: {envDriverPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"환경 변수 드라이버 삭제 실패: {ex.Message}"); + } + } + + // 저장된 드라이버 경로도 정리 + if (!string.IsNullOrEmpty(_driverPath) && File.Exists(_driverPath)) + { + try + { + File.Delete(_driverPath); + Console.WriteLine($"저장된 드라이버 삭제됨: {_driverPath}"); + } + catch (Exception ex) + { + Console.WriteLine($"저장된 드라이버 삭제 실패: {ex.Message}"); + } + } + + _driverPath = null; + Environment.SetEnvironmentVariable("webdriver.chrome.driver", null); + + Console.WriteLine("Chrome 드라이버 캐시 정리 완료"); + } + catch (Exception ex) + { + Console.WriteLine($"캐시 정리 실패: {ex.Message}"); + } + } + + public static bool IsDriverReady() + { + try + { + var driverPath = GetExistingDriverPath(); + if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) + { + Console.WriteLine("기존 드라이버가 없습니다."); + return false; + } + + Console.WriteLine($"드라이버 준비 상태 확인: {driverPath}"); + + // 간단한 테스트 실행 + var service = OpenQA.Selenium.Chrome.ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath)); + service.HideCommandPromptWindow = true; + var options = new OpenQA.Selenium.Chrome.ChromeOptions(); + options.AddArgument("--headless"); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + options.AddArgument("--disable-gpu"); + options.AddArgument("--remote-debugging-port=0"); + + using (var driver = new OpenQA.Selenium.Chrome.ChromeDriver(service, options)) + { + driver.Navigate().GoToUrl("https://www.google.com"); + var result = !string.IsNullOrEmpty(driver.Title); + Console.WriteLine($"드라이버 준비 상태: {(result ? "준비됨" : "실패")}"); + return result; + } + } + catch (Exception ex) + { + Console.WriteLine($"드라이버 준비 상태 확인 실패: {ex.Message}"); + return false; + } + } + + private static async Task TestExistingDriver(string driverPath) + { + try + { + Console.WriteLine($"기존 드라이버 테스트: {driverPath}"); + + // ChromeDriver 서비스 설정 + var service = OpenQA.Selenium.Chrome.ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath)); + service.HideCommandPromptWindow = true; + + // 간단한 테스트 실행 + var options = new OpenQA.Selenium.Chrome.ChromeOptions(); + options.AddArgument("--headless"); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + options.AddArgument("--disable-gpu"); + options.AddArgument("--remote-debugging-port=0"); + + using (var driver = new OpenQA.Selenium.Chrome.ChromeDriver(service, options)) + { + driver.Navigate().GoToUrl("https://www.google.com"); + var title = driver.Title; + Console.WriteLine($"드라이버 테스트 성공: {title}"); + return !string.IsNullOrEmpty(title); + } + } + catch (Exception ex) + { + Console.WriteLine($"기존 드라이버 테스트 실패: {ex.Message}"); + return false; + } + } + } +} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/DownloadProgressForm.cs b/unimarc/unimarc/SearchModel/DownloadProgressForm.cs new file mode 100644 index 0000000..0d54622 --- /dev/null +++ b/unimarc/unimarc/SearchModel/DownloadProgressForm.cs @@ -0,0 +1,142 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Threading.Tasks; + +namespace BokBonCheck +{ + public partial class DownloadProgressForm : Form + { + private ProgressBar progressBar; + private Label lblStatus; + private Label lblProgress; + private Button btnCancel; + private bool isCancelled = false; + + public DownloadProgressForm() + { + InitializeComponent(); + this.StartPosition = FormStartPosition.CenterScreen; + } + + private void InitializeComponent() + { + this.Text = "Chrome 드라이버 다운로드"; + this.Size = new Size(400, 150); + this.StartPosition = FormStartPosition.CenterParent; + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.ControlBox = false; + this.TopMost = true; + + // 상태 라벨 + lblStatus = new Label + { + Text = "Chrome 드라이버를 확인하고 있습니다...", + Location = new Point(20, 20), + Size = new Size(360, 20), + Font = new Font("맑은 고딕", 9), + TextAlign = ContentAlignment.MiddleCenter + }; + + // 진행률 라벨 + lblProgress = new Label + { + Text = "0%", + Location = new Point(20, 50), + Size = new Size(360, 20), + Font = new Font("맑은 고딕", 10, FontStyle.Bold), + TextAlign = ContentAlignment.MiddleCenter, + ForeColor = Color.Blue + }; + + // 프로그레스 바 + progressBar = new ProgressBar + { + Location = new Point(20, 80), + Size = new Size(360, 25), + Style = ProgressBarStyle.Continuous, + Minimum = 0, + Maximum = 100, + Value = 0 + }; + + // 취소 버튼 + btnCancel = new Button + { + Text = "취소", + Location = new Point(150, 115), + Size = new Size(100, 30), + Font = new Font("맑은 고딕", 9), + BackColor = Color.LightCoral + }; + + btnCancel.Click += BtnCancel_Click; + + // 컨트롤 추가 + this.Controls.AddRange(new Control[] + { + lblStatus, lblProgress, progressBar, btnCancel + }); + } + + private void BtnCancel_Click(object sender, EventArgs e) + { + isCancelled = true; + btnCancel.Enabled = false; + lblStatus.Text = "취소 중..."; + } + + public bool IsCancelled => isCancelled; + + public void UpdateProgress(int percentage, string status = null) + { + if (this.InvokeRequired) + { + this.Invoke(new Action(UpdateProgress), percentage, status); + return; + } + + progressBar.Value = Math.Min(percentage, 100); + lblProgress.Text = $"{percentage}%"; + + if (!string.IsNullOrEmpty(status)) + { + lblStatus.Text = status; + } + } + + public void SetCompleted(string message = "다운로드 완료!") + { + if (this.InvokeRequired) + { + this.Invoke(new Action(SetCompleted), message); + return; + } + + progressBar.Value = 100; + lblProgress.Text = "100%"; + lblStatus.Text = message; + btnCancel.Text = "확인"; + btnCancel.BackColor = Color.LightGreen; + btnCancel.Enabled = true; + } + + public void SetError(string errorMessage) + { + if (this.InvokeRequired) + { + this.Invoke(new Action(SetError), errorMessage); + return; + } + + lblStatus.Text = "오류 발생"; + lblProgress.Text = "실패"; + lblProgress.ForeColor = Color.Red; + btnCancel.Text = "확인"; + btnCancel.BackColor = Color.LightCoral; + btnCancel.Enabled = true; + } + } +} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/ILibrarySearcher.cs b/unimarc/unimarc/SearchModel/ILibrarySearcher.cs new file mode 100644 index 0000000..5511a8c --- /dev/null +++ b/unimarc/unimarc/SearchModel/ILibrarySearcher.cs @@ -0,0 +1,17 @@ +using OpenQA.Selenium.Support.UI; +using System.Threading.Tasks; + +namespace BokBonCheck +{ + public interface ILibrarySearcher + { + int No { get; set; } + string SiteName { get; } + string SiteUrl { get; } + Task SearchAsync(string searchTerm); + void StartDriver(); + void StopDriver(); + + Task WaitForPageChange(WebDriverWait wait); + } +} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs b/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs new file mode 100644 index 0000000..ea0dd63 --- /dev/null +++ b/unimarc/unimarc/SearchModel/KwangjuCityLibrarySearcher.cs @@ -0,0 +1,321 @@ +using System; +using System.Threading.Tasks; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Support.UI; +using System.Text.RegularExpressions; +using WebDriverManager; +using WebDriverManager.DriverConfigs.Impl; +using System.IO; +using System.Runtime.InteropServices; + +namespace BokBonCheck +{ + public class KwangjuCityLibrarySearcher_choisangjun : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_choisangjun(int no) : base(no) + { + SelectorValue = "MF"; + SiteName = "광주시교육청통합도서관(분관최상준도서관)"; + } + } + public class KwangjuCityLibrarySearcher_dagachi : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_dagachi(int no) : base(no) + { + SelectorValue = "ME"; + SiteName = "광주시교육청통합도서관(송정다가치문화도서관)"; + } + } + public class KwangjuCityLibrarySearcher_central : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_central(int no) : base(no) + { + SelectorValue = "MD"; + SiteName = "광주시교육청통합도서관(중앙도서관)"; + } + } + public class KwangjuCityLibrarySearcher_Student : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_Student(int no) : base(no) + { + SelectorValue = "MC"; + SiteName = "광주시교육청통합도서관(학생교육문화회관)"; + } + } + public class KwangjuCityLibrarySearcher_Kumho : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_Kumho(int no) : base(no) + { + SelectorValue = "MB"; + SiteName = "광주시교육청통합도서관(금호평생교육관)"; + } + } + public class KwangjuCityLibrarySearcher_Indi : KwangjuCityLibrarySearcher + { + public KwangjuCityLibrarySearcher_Indi(int no) : base(no) + { + SelectorValue = "MA"; + SiteName = "광주시교육청통합도서관(학생독립운동기념회관)"; + } + } + public abstract class KwangjuCityLibrarySearcher : ILibrarySearcher + { + public int No { get; set; } + public string SiteName { get; protected set; } = "광주시교육청통합도서관"; + public string SiteUrl => "https://lib.gen.go.kr/main/site/search/bookSearch.do#simple"; + + protected string SelectorValue = ""; + + private ChromeDriver _driver; + private ChromeDriverService _service; + + [DllImport("user32.dll")] + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + [DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + private const int SW_MINIMIZE = 6; + + public KwangjuCityLibrarySearcher(int no) + { + this.No = no; + } + + public void StartDriver() + { + if (_driver == null) + { + var driverPath = ChromeDriverManager.GetDriverPath(); + if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) + { + driverPath = ChromeDriverManager.SetupChromeDriverAsync().GetAwaiter().GetResult(); + } + _service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); + _service.HideCommandPromptWindow = true; + var options = new ChromeOptions(); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + options.AddArgument("--disable-gpu"); + options.AddArgument("--window-size=1920,1080"); + options.AddArgument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"); + options.AddArgument("--disable-blink-features=AutomationControlled"); + options.AddExcludedArgument("enable-automation"); + options.AddAdditionalOption("useAutomationExtension", false); + _driver = new ChromeDriver(_service, options); + ((IJavaScriptExecutor)_driver).ExecuteScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"); + } + } + + public void StopDriver() + { + if (_driver != null) + { + _driver.Quit(); + _driver.Dispose(); + _driver = null; + } + if (_service != null) + { + _service.Dispose(); + _service = null; + } + } + + virtual protected void SelectLibrary(WebDriverWait wait) + { + try + { + // 콤보박스(select) 요소 찾기 + var selectElement = wait.Until(d => d.FindElement(By.CssSelector("#manage_code"))); + var select = new OpenQA.Selenium.Support.UI.SelectElement(selectElement); + + // value가 "MA"인 옵션 선택 + select.SelectByValue(SelectorValue); + } + catch + { + // 예외 처리 (필요시 로깅 등) + } + } + + public async Task SearchAsync(string searchTerm) + { + var result = new BookSearchResult + { + SiteName = SiteName, + SearchTerm = searchTerm, + SearchTime = DateTime.Now + }; + + try + { + if (_driver == null) + throw new InvalidOperationException("드라이버가 시작되지 않았습니다. StartDriver()를 먼저 호출하세요."); + + _driver.Navigate().GoToUrl(SiteUrl); + + // 페이지 로딩 대기 + var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(15)); + + // 모든 감지 방법이 끝나면 크롬창 최소화 + IntPtr chromeWindow = FindWindow("Chrome_WidgetWin_1", null); + if (chromeWindow != IntPtr.Zero) + { + ShowWindow(chromeWindow, SW_MINIMIZE); + } + + //대상도서관 선택 + SelectLibrary(wait); + + // 검색창 찾기 + IWebElement searchBox = null; + try + { + // 여러 가능한 선택자 시도 + var selectors = new[] + { + "input[id='search_txt']", + "input[type='text']", + }; + + foreach (var selector in selectors) + { + try + { + searchBox = wait.Until(d => + { + var el = d.FindElement(By.CssSelector(selector)); + return (el != null && el.Displayed && el.Enabled) ? el : null; + }); + break; + } + catch + { + continue; + } + } + + if (searchBox == null) + { + throw new Exception("검색창을 찾을 수 없습니다."); + } + } + catch (Exception ex) + { + throw new Exception($"검색창 찾기 실패: {ex.Message}"); + } + + // 혹시 readonly라면 속성 제거 + ((IJavaScriptExecutor)_driver).ExecuteScript("arguments[0].removeAttribute('readonly')", searchBox); + + // 입력 전 clear + searchBox.Clear(); + searchBox.SendKeys(searchTerm); + + // 검색 버튼 클릭 + IWebElement searchButton = null; + try + { + var buttonSelectors = new[] + { + "input[type='submit']", + }; + foreach (var selector in buttonSelectors) + { + try + { + searchButton = _driver.FindElement(By.CssSelector(selector)); + break; + } + catch + { + continue; + } + } + + if (searchButton == null) + { + // Enter 키로 검색 시도 + searchBox.SendKeys(Keys.Enter); + } + else + { + searchButton.Click(); + } + } + catch (Exception ex) + { + // Enter 키로 검색 시도 + searchBox.SendKeys(Keys.Enter); + } + + // 페이지 변경을 감지하는 메서드 + await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15))); + + // 검색 결과 수 추출 + var resultCount = ExtractBookCount(_driver); + + result.BookCount = resultCount; + result.IsSuccess = true; + } + catch (Exception ex) + { + result.IsSuccess = false; + result.ErrorMessage = ex.Message; + result.BookCount = 0; + } + + return result; + } + + private int ExtractBookCount(IWebDriver driver) + { + try + { + // div.search-result 내부의 span에서 '전체 N' 텍스트 추출 + var resultDiv = driver.FindElement(By.CssSelector("div.ndls_result")); + var span = resultDiv.FindElement(By.XPath(".//span[contains(text(),'전체')]")); + string text = span.Text; // 예: "전체 5 " + var match = System.Text.RegularExpressions.Regex.Match(text, @"전체\s*(\d+)"); + if (match.Success) + { + return int.Parse(match.Groups[1].Value); + } + return 0; + } + catch + { + return 0; + } + } + + // 페이지 변경을 감지하는 메서드 + public async Task WaitForPageChange(WebDriverWait wait) + { + try + { + // 방법 4: 페이지 로딩 상태 확인 + wait.Until(d => + { + var readyState = ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState"); + return readyState.Equals("complete"); + }); + + // 방법 5: 특정 텍스트가 페이지에 나타날 때까지 대기 + wait.Until(d => + { + var pageText = d.FindElement(By.TagName("body")).Text; + return pageText.Contains("전체") || pageText.Contains("건") || pageText.Contains("검색결과"); + }); + + + } + catch (Exception ex) + { + // 모든 감지 방법이 실패하면 최소한의 대기 시간 적용 + await Task.Delay(2000); + throw new Exception($"페이지 변경 감지 실패: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs new file mode 100644 index 0000000..0e005f9 --- /dev/null +++ b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs @@ -0,0 +1,441 @@ +using System; +using System.Threading.Tasks; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Support.UI; +using System.Text.RegularExpressions; +using WebDriverManager; +using WebDriverManager.DriverConfigs.Impl; +using System.IO; +using System.Runtime.InteropServices; + +namespace BokBonCheck +{ + public class NamguLibrarySearcher_Munhwa : NamguLibrarySearcher + { + public NamguLibrarySearcher_Munhwa(int no) : base(no) + { + SiteName = "남구통합도서관(문화정보도서관)"; // 문화관 검색기 + } + + protected override void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == true) + { + searchBox.Click(); // 전체체크박스가 체크되어 있으면 클릭해서 해제 + } + else return; + + selector = "#libMA"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 문화관 체크박스 선택 + } + } + catch + { + + } + } + } + public class NamguLibrarySearcher_Purungil : NamguLibrarySearcher + { + public NamguLibrarySearcher_Purungil(int no) : base(no) + { + SiteName = "남구통합도서관(푸른길도서관)"; + } + + protected override void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == true) + { + searchBox.Click(); // 전체체크박스가 체크되어 있으면 클릭해서 해제 + } + else return; + + selector = "#libMB"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 체크박스 선택 + } + } + catch + { + + } + } + } + public class NamguLibrarySearcher_Children : NamguLibrarySearcher + { + public NamguLibrarySearcher_Children(int no) : base(no) + { + SiteName = "남구통합도서관(청소년도서관)"; + } + + protected override void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == true) + { + searchBox.Click(); // 전체체크박스가 체크되어 있으면 클릭해서 해제 + } + else return; + + selector = "#libMC"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 체크박스 선택 + } + } + catch + { + + } + } + } + public class NamguLibrarySearcher_Hyocheon : NamguLibrarySearcher + { + public NamguLibrarySearcher_Hyocheon(int no) : base(no) + { + SiteName = "남구통합도서관(효천어울림도서관)"; + } + + protected override void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == true) + { + searchBox.Click(); // 전체체크박스가 체크되어 있으면 클릭해서 해제 + } + else return; + + selector = "#libSW"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 체크박스 선택 + } + } + catch + { + + } + } + } + public class NamguLibrarySearcher_Smart : NamguLibrarySearcher + { + public NamguLibrarySearcher_Smart(int no) : base(no) + { + SiteName = "남구통합도서관(스마트도서관)"; + } + + protected override void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == true) + { + searchBox.Click(); // 전체체크박스가 체크되어 있으면 클릭해서 해제 + } + else return; + + selector = "#libSQ"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 체크박스 선택 + } + } + catch + { + + } + } + } + public class NamguLibrarySearcher : ILibrarySearcher + { + public string SiteName { get; protected set; } = "남구통합도서관(전체)"; + public string SiteUrl => "https://lib.namgu.gwangju.kr/main/bookSearch"; + + public int No { get; set; } + + private ChromeDriver _driver; + private ChromeDriverService _service; + + [DllImport("user32.dll")] + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + [DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + private const int SW_MINIMIZE = 6; + + public NamguLibrarySearcher(int no) + { + this.No = no; + } + + public void StartDriver() + { + if (_driver == null) + { + var driverPath = ChromeDriverManager.GetDriverPath(); + if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) + { + driverPath = ChromeDriverManager.SetupChromeDriverAsync().GetAwaiter().GetResult(); + } + _service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); + _service.HideCommandPromptWindow = true; + var options = new ChromeOptions(); + options.AddArgument("--no-sandbox"); + options.AddArgument("--disable-dev-shm-usage"); + options.AddArgument("--disable-gpu"); + options.AddArgument("--window-size=1920,1080"); + options.AddArgument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"); + options.AddArgument("--disable-blink-features=AutomationControlled"); + options.AddExcludedArgument("enable-automation"); + options.AddAdditionalOption("useAutomationExtension", false); + _driver = new ChromeDriver(_service, options); + ((IJavaScriptExecutor)_driver).ExecuteScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"); + } + } + + public void StopDriver() + { + if (_driver != null) + { + _driver.Quit(); + _driver.Dispose(); + _driver = null; + } + if (_service != null) + { + _service.Dispose(); + _service = null; + } + } + + + virtual protected void SelectLibrary(WebDriverWait wait) + { + IWebElement searchBox = null; + try + { + var selector = "#clickAll"; + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + if (searchBox != null && searchBox.Selected == false) + { + searchBox.Click(); // 전체체크박스가 해제되어 있으면 클릭해서 선택 + } + else return; + } + catch + { + + } + } + + public async Task SearchAsync(string searchTerm) + { + var result = new BookSearchResult + { + SiteName = SiteName, + SearchTerm = searchTerm, + SearchTime = DateTime.Now + }; + + try + { + if (_driver == null) + throw new InvalidOperationException("드라이버가 시작되지 않았습니다. StartDriver()를 먼저 호출하세요."); + + _driver.Navigate().GoToUrl(SiteUrl); + + // 페이지 로딩 대기 + var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(15)); + + // 모든 감지 방법이 끝나면 크롬창 최소화 + IntPtr chromeWindow = FindWindow("Chrome_WidgetWin_1", null); + if (chromeWindow != IntPtr.Zero) + { + ShowWindow(chromeWindow, SW_MINIMIZE); + } + + //대상도서관 선택 + SelectLibrary(wait); + + // 검색창 찾기 (남구통합도서관 사이트의 특정 선택자 사용) + IWebElement searchBox = null; + try + { + // 여러 가능한 선택자 시도 + var selectors = new[] + { + "input[name='query']", + "input[id='query']", + "input[type='text']", + }; + + foreach (var selector in selectors) + { + try + { + searchBox = wait.Until(d => d.FindElement(By.CssSelector(selector))); + break; + } + catch + { + continue; + } + } + + if (searchBox == null) + { + throw new Exception("검색창을 찾을 수 없습니다."); + } + } + catch (Exception ex) + { + throw new Exception($"검색창 찾기 실패: {ex.Message}"); + } + + // 검색어 입력 + searchBox.Clear(); + searchBox.SendKeys(searchTerm); + + // 검색 버튼 클릭 + IWebElement searchButton = null; + try + { + var buttonSelectors = new[] + { + "button[type='submit']", + "input[type='submit']", + ".search-btn", + ".btn-search", + "button:contains('검색')", + "input[value*='검색']", + "button[class*='search']", + "input[class*='search']" + }; + + foreach (var selector in buttonSelectors) + { + try + { + searchButton = _driver.FindElement(By.CssSelector(selector)); + break; + } + catch + { + continue; + } + } + + if (searchButton == null) + { + // Enter 키로 검색 시도 + searchBox.SendKeys(Keys.Enter); + } + else + { + searchButton.Click(); + } + } + catch (Exception ex) + { + // Enter 키로 검색 시도 + searchBox.SendKeys(Keys.Enter); + } + + // 페이지 변경을 감지하는 메서드 + await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15))); + + // 검색 결과 수 추출 + var resultCount = ExtractBookCount(_driver); + + result.BookCount = resultCount; + result.IsSuccess = true; + } + catch (Exception ex) + { + result.IsSuccess = false; + result.ErrorMessage = ex.Message; + result.BookCount = 0; + } + + return result; + } + + private int ExtractBookCount(IWebDriver driver) + { + try + { + // div.search-result 내부의 span에서 '전체 N' 텍스트 추출 + var resultDiv = driver.FindElement(By.CssSelector("div.search-result")); + var span = resultDiv.FindElement(By.XPath(".//span[contains(text(),'전체')]")); + string text = span.Text; // 예: "전체 5 " + var match = System.Text.RegularExpressions.Regex.Match(text, @"전체\s*(\d+)"); + if (match.Success) + { + return int.Parse(match.Groups[1].Value); + } + return 0; + } + catch + { + return 0; + } + } + + // 페이지 변경을 감지하는 메서드 + public async Task WaitForPageChange(WebDriverWait wait) + { + try + { + // 방법 4: 페이지 로딩 상태 확인 + wait.Until(d => + { + var readyState = ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState"); + return readyState.Equals("complete"); + }); + + // 방법 5: 특정 텍스트가 페이지에 나타날 때까지 대기 + wait.Until(d => + { + var pageText = d.FindElement(By.TagName("body")).Text; + return pageText.Contains("전체") || pageText.Contains("건") || pageText.Contains("검색결과"); + }); + + } + catch (Exception ex) + { + // 모든 감지 방법이 실패하면 최소한의 대기 시간 적용 + await Task.Delay(2000); + throw new Exception($"페이지 변경 감지 실패: {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/unimarc/unimarc/UniMarc.csproj b/unimarc/unimarc/UniMarc.csproj index 0fb9d65..6adf3d5 100644 --- a/unimarc/unimarc/UniMarc.csproj +++ b/unimarc/unimarc/UniMarc.csproj @@ -75,6 +75,9 @@ UniMarc_TemporaryKey.pfx + + ..\packages\AngleSharp.1.0.4\lib\net472\AngleSharp.dll + ..\dll\arCommUtil.dll @@ -87,19 +90,62 @@ ..\dll\CarlosAg.ExcelXmlWriter.dll + + ..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll + - - ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll ..\packages\SSH.NET.2020.0.1\lib\net40\Renci.SshNet.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + + ..\packages\System.Text.Encoding.CodePages.6.0.0\lib\net461\System.Text.Encoding.CodePages.dll + + + ..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + @@ -111,6 +157,15 @@ + + ..\packages\Selenium.WebDriver.4.16.2\lib\netstandard2.0\WebDriver.dll + + + ..\packages\Selenium.Support.4.16.2\lib\netstandard2.0\WebDriver.Support.dll + + + ..\packages\WebDriverManager.2.17.1\lib\net462\WebDriverManager.dll + @@ -125,6 +180,14 @@ Reference.svcmap + + + + Form + + + + Form @@ -1868,4 +1931,11 @@ + + + + 이 프로젝트는 이 컴퓨터에 없는 NuGet 패키지를 참조합니다. 해당 패키지를 다운로드하려면 NuGet 패키지 복원을 사용하십시오. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=322105를 참조하십시오. 누락된 파일은 {0}입니다. + + + \ No newline at end of file diff --git a/unimarc/unimarc/UniMarc.csproj.user b/unimarc/unimarc/UniMarc.csproj.user index ff2aa00..be8df31 100644 --- a/unimarc/unimarc/UniMarc.csproj.user +++ b/unimarc/unimarc/UniMarc.csproj.user @@ -9,6 +9,7 @@ ko-KR false + ProjectFiles false diff --git a/unimarc/unimarc/packages.config b/unimarc/unimarc/packages.config index a6b1cca..e7a4292 100644 --- a/unimarc/unimarc/packages.config +++ b/unimarc/unimarc/packages.config @@ -1,5 +1,23 @@  - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/unimarc/unimarc/마크/Check_Copy_Sub_Search.Designer.cs b/unimarc/unimarc/마크/Check_Copy_Sub_Search.Designer.cs index ff6579f..45429ff 100644 --- a/unimarc/unimarc/마크/Check_Copy_Sub_Search.Designer.cs +++ b/unimarc/unimarc/마크/Check_Copy_Sub_Search.Designer.cs @@ -36,6 +36,7 @@ namespace UniMarc.마크 this.lib_name = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Code = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.URL = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.dvc_searcher = new System.Windows.Forms.DataGridViewTextBoxColumn(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); this.SuspendLayout(); // @@ -58,7 +59,8 @@ namespace UniMarc.마크 this.Area, this.lib_name, this.Code, - this.URL}); + this.URL, + this.dvc_searcher}); this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill; this.dataGridView1.Location = new System.Drawing.Point(0, 0); this.dataGridView1.Name = "dataGridView1"; @@ -105,6 +107,13 @@ namespace UniMarc.마크 this.URL.ReadOnly = true; this.URL.Visible = false; // + // dvc_searcher + // + this.dvc_searcher.HeaderText = "Searcher"; + this.dvc_searcher.Name = "dvc_searcher"; + this.dvc_searcher.ReadOnly = true; + this.dvc_searcher.Visible = false; + // // Check_Copy_Sub_Search // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); @@ -126,5 +135,6 @@ namespace UniMarc.마크 private System.Windows.Forms.DataGridViewTextBoxColumn lib_name; private System.Windows.Forms.DataGridViewTextBoxColumn Code; private System.Windows.Forms.DataGridViewTextBoxColumn URL; + private System.Windows.Forms.DataGridViewTextBoxColumn dvc_searcher; } } \ No newline at end of file diff --git a/unimarc/unimarc/마크/Check_Copy_Sub_Search.cs b/unimarc/unimarc/마크/Check_Copy_Sub_Search.cs index 11d5537..3af8489 100644 --- a/unimarc/unimarc/마크/Check_Copy_Sub_Search.cs +++ b/unimarc/unimarc/마크/Check_Copy_Sub_Search.cs @@ -26,15 +26,17 @@ namespace UniMarc.마크 this.Text = string.Format("검색어 : [{0}]", SearchText); // Province, Area, lib_name, Code - string[] grid = { "", "", "", "", "" }; + string[] grid = { "", "", "", "", "", "" }; for (int a = 0; a < ary.Length; a++) { - if (a % 5 == 0) grid[0] = ary[a]; - if (a % 5 == 1) grid[1] = ary[a]; - if (a % 5 == 2) grid[2] = string.Format("{0}_{1}_{2}", grid[0], grid[1], ary[a]); - if (a % 5 == 3) grid[3] = ary[a]; - if (a % 5 == 4) { - grid[4] = ary[a]; + if (a % 6 == 0) grid[0] = ary[a]; + if (a % 6 == 1) grid[1] = ary[a]; + if (a % 6 == 2) grid[2] = string.Format("{0}_{1}_{2}", grid[0], grid[1], ary[a]); + if (a % 6 == 3) grid[3] = ary[a]; + if (a % 6 == 4) grid[4] = ary[a]; + if (a % 6 == 5) + { + grid[5] = ary[a]; dataGridView1.Rows.Add(grid); } } @@ -73,6 +75,7 @@ namespace UniMarc.마크 string Code = dataGridView1.Rows[row].Cells["Code"].Value.ToString(); string URL = dataGridView1.Rows[row].Cells["URL"].Value.ToString(); string lib_name = dataGridView1.Rows[row].Cells["lib_name"].Value.ToString(); + string searcher = dataGridView1.Rows[row].Cells["dvc_searcher"].Value.ToString(); string lib_Category = string.Format("{0}_{1}", Province, Area); @@ -80,7 +83,8 @@ namespace UniMarc.마크 cc.Code = Code; cc.URL = URL; cc.tb_SearchTarget.Text = lib_name; - + cc.SearcherNo = searcher; + if (lib_name.Contains("Kolasys.net")) { Check_Copy_Login ccl = new Check_Copy_Login(this); diff --git a/unimarc/unimarc/마크/Check_Copy_Sub_Search.resx b/unimarc/unimarc/마크/Check_Copy_Sub_Search.resx index 95816b3..af0800e 100644 --- a/unimarc/unimarc/마크/Check_Copy_Sub_Search.resx +++ b/unimarc/unimarc/마크/Check_Copy_Sub_Search.resx @@ -132,4 +132,7 @@ True + + True + \ No newline at end of file diff --git a/unimarc/unimarc/마크/Check_copy.Designer.cs b/unimarc/unimarc/마크/Check_copy.Designer.cs index 858eace..7fd6bf0 100644 --- a/unimarc/unimarc/마크/Check_copy.Designer.cs +++ b/unimarc/unimarc/마크/Check_copy.Designer.cs @@ -28,7 +28,7 @@ /// private void InitializeComponent() { - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); this.panel1 = new System.Windows.Forms.Panel(); this.rb_isNumber = new System.Windows.Forms.RadioButton(); this.rb_isHave = new System.Windows.Forms.RadioButton(); @@ -39,7 +39,7 @@ this.btn_Close = new System.Windows.Forms.Button(); this.label2 = new System.Windows.Forms.Label(); this.tb_SearchTarget = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); + this.btSearchLibrary = new System.Windows.Forms.Button(); this.panel2 = new System.Windows.Forms.Panel(); this.btn_SiteDenote = new System.Windows.Forms.Button(); this.lbl_PW = new System.Windows.Forms.Label(); @@ -51,6 +51,8 @@ this.btn_ApplyFilter = new System.Windows.Forms.Button(); this.panel3 = new System.Windows.Forms.Panel(); this.panel6 = new System.Windows.Forms.Panel(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.lblStatus = new System.Windows.Forms.ToolStripLabel(); this.panel4 = new System.Windows.Forms.Panel(); this.chk_RemoveBrit = new System.Windows.Forms.CheckBox(); this.btn_ResultEmpty = new System.Windows.Forms.Button(); @@ -65,6 +67,7 @@ ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); this.panel3.SuspendLayout(); this.panel6.SuspendLayout(); + this.statusStrip1.SuspendLayout(); this.panel4.SuspendLayout(); this.panel5.SuspendLayout(); this.SuspendLayout(); @@ -176,14 +179,15 @@ this.tb_SearchTarget.TabIndex = 1; this.tb_SearchTarget.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tb_SearchTarget_KeyDown); // - // label1 + // btSearchLibrary // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(8, 10); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(53, 12); - this.label1.TabIndex = 0; - this.label1.Text = "검색대상"; + this.btSearchLibrary.AutoSize = true; + this.btSearchLibrary.Location = new System.Drawing.Point(3, 5); + this.btSearchLibrary.Name = "btSearchLibrary"; + this.btSearchLibrary.Size = new System.Drawing.Size(63, 23); + this.btSearchLibrary.TabIndex = 0; + this.btSearchLibrary.Text = "검색대상"; + this.btSearchLibrary.Click += new System.EventHandler(this.btSearchLibrary_Click); // // panel2 // @@ -193,7 +197,7 @@ this.panel2.Controls.Add(this.lbl_ID); this.panel2.Controls.Add(this.SearchCount); this.panel2.Controls.Add(this.tb_SearchTarget); - this.panel2.Controls.Add(this.label1); + this.panel2.Controls.Add(this.btSearchLibrary); this.panel2.Controls.Add(this.btn_Close); this.panel2.Controls.Add(this.label2); this.panel2.Dock = System.Windows.Forms.DockStyle.Top; @@ -236,14 +240,14 @@ this.dataGridView1.BackgroundColor = System.Drawing.SystemColors.Control; this.dataGridView1.BorderStyle = System.Windows.Forms.BorderStyle.None; this.dataGridView1.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; - dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; - dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle2.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); - dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2; + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; + dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control; + dataGridViewCellStyle1.Font = new System.Drawing.Font("굴림", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.book_name, @@ -253,7 +257,7 @@ this.dataGridView1.Location = new System.Drawing.Point(0, 0); this.dataGridView1.Name = "dataGridView1"; this.dataGridView1.RowTemplate.Height = 23; - this.dataGridView1.Size = new System.Drawing.Size(629, 636); + this.dataGridView1.Size = new System.Drawing.Size(629, 614); this.dataGridView1.TabIndex = 1; this.dataGridView1.RowPostPaint += new System.Windows.Forms.DataGridViewRowPostPaintEventHandler(this.dataGridView1_RowPostPaint); this.dataGridView1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.dataGridView1_KeyDown); @@ -304,12 +308,29 @@ // panel6 // this.panel6.Controls.Add(this.dataGridView1); + this.panel6.Controls.Add(this.statusStrip1); this.panel6.Dock = System.Windows.Forms.DockStyle.Fill; this.panel6.Location = new System.Drawing.Point(0, 102); this.panel6.Name = "panel6"; this.panel6.Size = new System.Drawing.Size(629, 636); this.panel6.TabIndex = 3; // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.lblStatus}); + this.statusStrip1.Location = new System.Drawing.Point(0, 614); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(629, 22); + this.statusStrip1.TabIndex = 2; + this.statusStrip1.Text = "statusStrip1"; + // + // lblStatus + // + this.lblStatus.Name = "lblStatus"; + this.lblStatus.Size = new System.Drawing.Size(27, 20); + this.lblStatus.Text = "WD"; + // // panel4 // this.panel4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; @@ -413,6 +434,9 @@ ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); this.panel3.ResumeLayout(false); this.panel6.ResumeLayout(false); + this.panel6.PerformLayout(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); this.panel4.ResumeLayout(false); this.panel4.PerformLayout(); this.panel5.ResumeLayout(false); @@ -423,7 +447,7 @@ #endregion private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button btSearchLibrary; private System.Windows.Forms.Label label2; private System.Windows.Forms.Panel panel2; private System.Windows.Forms.Button btn_Close; @@ -452,5 +476,7 @@ public System.Windows.Forms.Label lbl_ID; private System.Windows.Forms.Button btn_SiteDenote; private System.Windows.Forms.WebBrowser webBrowser1; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripLabel lblStatus; } } \ No newline at end of file diff --git a/unimarc/unimarc/마크/Check_copy.cs b/unimarc/unimarc/마크/Check_copy.cs index 68f2e72..447fcfd 100644 --- a/unimarc/unimarc/마크/Check_copy.cs +++ b/unimarc/unimarc/마크/Check_copy.cs @@ -6,6 +6,8 @@ using System.Text.RegularExpressions; using System.Web; using System.Windows.Forms; using UniMarc.마크; +using BokBonCheck; +using AR; namespace WindowsFormsApp1.Mac { @@ -15,6 +17,7 @@ namespace WindowsFormsApp1.Mac public string URL; public string lib_Category; public string Code; + public string SearcherNo; private bool isStop = false; Main main; public Check_copy(Main _main) @@ -22,6 +25,20 @@ namespace WindowsFormsApp1.Mac InitializeComponent(); main = _main; db.DBcon(); + + //도서검색(크롤링) + _searchService = new BookSearchService(); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_central()); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_choisangjun()); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_dagachi()); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_Indi()); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_Student()); + //_searchService.AddSearcher(new KwangjuCityLibrarySearcher_Kumho()); + _searchService.AddSearcher(new NamguLibrarySearcher_Munhwa(1)); + _searchService.AddSearcher(new NamguLibrarySearcher_Children(2)); + _searchService.AddSearcher(new NamguLibrarySearcher_Smart(3)); + _searchService.AddSearcher(new NamguLibrarySearcher_Purungil(4)); + _searchService.AddSearcher(new NamguLibrarySearcher_Hyocheon(5)); } private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) @@ -30,22 +47,126 @@ namespace WindowsFormsApp1.Mac sg.Print_Grid_Num(sender, e); } + private void Check_copy_Load(object sender, EventArgs e) + { + string[] Grid = { "----- 빈칸으로 놔주세요 -----", "빈칸", "" }; + dataGridView1.Rows.Add(Grid); + + this.Show(); + Application.DoEvents(); + + //크롤링 + InitializeChromeDriver(); + } + + + #region 크롤링 + + private readonly BookSearchService _searchService; + private bool _isSearching = false; + private bool _isDriverReady = false; + + private async void InitializeChromeDriver() + { + var lblStatus = this.lblStatus;// (Label)this.Controls["lblStatus"]; + lblStatus.Text = "WebDriver:Chrome 드라이버 확인 중..."; + lblStatus.ForeColor = Color.Blue; + + try + { + // Chrome 설치 확인 + if (!ChromeDriverManager.IsChromeInstalled()) + { + MessageBox.Show("Google Chrome이 설치되어 있지 않습니다. Chrome을 설치한 후 프로그램을 다시 실행해주세요.", + "Chrome 필요", MessageBoxButtons.OK, MessageBoxIcon.Warning); + lblStatus.Text = "WebDriver:Chrome이 설치되지 않음"; + lblStatus.ForeColor = Color.Red; + return; + } + + // 기존 드라이버가 준비되어 있는지 확인 + if (ChromeDriverManager.IsDriverReady()) + { + lblStatus.Text = "WebDriver:Ready"; + lblStatus.ForeColor = Color.Green; + _isDriverReady = true; + return; + } + + // 드라이버가 없거나 작동하지 않으면 다운로드 진행 창 표시 + using (var progressForm = new DownloadProgressForm()) + { + progressForm.Show(); + + try + { + // ChromeDriver 설정 + await ChromeDriverManager.SetupChromeDriverAsync(progressForm); + + // 드라이버 테스트 + var isWorking = await ChromeDriverManager.TestChromeDriverAsync(progressForm); + + if (isWorking) + { + _isDriverReady = true; + lblStatus.Text = "WebDriver:Ready"; + lblStatus.ForeColor = Color.Green; + } + else + { + lblStatus.Text = "WebDriver:Chrome 드라이버 테스트 실패"; + lblStatus.ForeColor = Color.Red; + MessageBox.Show("Chrome 드라이버 테스트에 실패했습니다. 인터넷 연결을 확인하고 프로그램을 다시 실행해주세요.", + "드라이버 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + catch (OperationCanceledException) + { + lblStatus.Text = "WebDriver:드라이버 다운로드가 취소되었습니다."; + lblStatus.ForeColor = Color.Orange; + return; + } + catch (Exception ex) + { + lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; + lblStatus.ForeColor = Color.Red; + MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", + "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + } + } + catch (Exception ex) + { + lblStatus.Text = "WebDriver:Chrome 드라이버 설정 실패"; + lblStatus.ForeColor = Color.Red; + MessageBox.Show($"Chrome 드라이버 설정 중 오류가 발생했습니다: {ex.Message}", + "설정 오류", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + #endregion + + private void tb_SearchTarget_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { - string Target = tb_SearchTarget.Text; - // if (Target == "") { MessageBox.Show("도서관명이 비어있습니다."); return; } - - string area = "`Province`, `Area`, `LibName`, `Code`, `URL`"; - string cmd = string.Format("SELECT {0} FROM `lib_CopyCheck` WHERE CONCAT( province , '_' , AREA , '_' , libname) LIKE '%{1}%';", area, Target); - string data = db.self_Made_Cmd(cmd); - string[] ary = data.Split('|'); - Check_Copy_Sub_Search ccs = new Check_Copy_Sub_Search(this); - ccs.Init(ary, Target); - ccs.Show(); + SearchLibrary(); } } + void SearchLibrary() + { + string Target = tb_SearchTarget.Text; + // if (Target == "") { MessageBox.Show("도서관명이 비어있습니다."); return; } + + string area = "`Province`, `Area`, `LibName`, `Code`, `URL`, `SearcherNo`"; + string cmd = string.Format("SELECT {0} FROM `lib_CopyCheck` WHERE CONCAT( province , '_' , AREA , '_' , libname) LIKE '%{1}%';", area, Target); + string data = db.self_Made_Cmd(cmd); + string[] ary = data.Split('|'); + Check_Copy_Sub_Search ccs = new Check_Copy_Sub_Search(this); + ccs.Init(ary, Target); + ccs.Show(); + } private void btn_SearchList_Click(object sender, EventArgs e) { @@ -61,17 +182,26 @@ namespace WindowsFormsApp1.Mac SearchCount.Value = dataGridView1.Rows.Count; } - private void btn_Start_Click(object sender, EventArgs e) + async private void btn_Start_Click(object sender, EventArgs e) { - if (tb_SearchTarget.Text.Contains("Kolasys.net")) + var libraryName = tb_SearchTarget.Text.Trim(); + if (libraryName.isEmpty()) + { + tb_SearchTarget.Focus(); + UTIL.MsgE("도서관을 선택하세요"); + return; + } + if (libraryName.Contains("Kolasys.net")) { if (lbl_ID.Text == " " || lbl_PW.Text == " ") { - MessageBox.Show("해당 도서관은 로그인정보가 필요합니다.\n복본조사 창을 껏다켜주세요."); + UTIL.MsgE("해당 도서관은 로그인정보가 필요합니다.\n복본조사 창을 껏다켜주세요."); return; } } + + isIksanClick = false; isJBEClick = false; isJNLClick = false; @@ -85,66 +215,168 @@ namespace WindowsFormsApp1.Mac dataGridView1.CurrentCell = dataGridView1.Rows[0].Cells[0]; - webBrowser1.Navigate(""); - int SCount = Convert.ToInt32(SearchCount.Value); - if (URL is null) + if (SearcherNo.toInt() < 1) { - webBrowser1.DocumentCompleted -= this.webBrowser1_DocumentCompleted; - return; - } - else if (URL.IndexOf("lib.jeonnam.go.kr") > -1) - { - for (int a = 0; a < SCount; a++) + //legacy + webBrowser1.Visible = true; + webBrowser1.Navigate(""); + if (URL is null) { - if (dataGridView1.Rows[a].Cells["book_name"].Value == null) - continue; - - if (dataGridView1.Rows[a].Cells["book_name"].Value.ToString() == "") - continue; - - if (isStop) - break; - - string BookSearchCount = CopyCount(dataGridView1.Rows[a].Cells["book_name"].Value.ToString()); - - if (BookSearchCount == "false") - { - MessageBox.Show("검색대상이 설정되지않았습니다!"); - return; - } - - if (BookSearchCount == "0" || BookSearchCount == "" || BookSearchCount == "미소장") - { - dataGridView1.Rows[a].DefaultCellStyle.BackColor = Color.LightGray; - dataGridView1.Rows[a].DefaultCellStyle.ForeColor = Color.Red; - BookSearchCount = ""; - } - else - { - dataGridView1.Rows[a].DefaultCellStyle.BackColor = Color.Yellow; - dataGridView1.Rows[a].DefaultCellStyle.ForeColor = Color.Blue; - } - - int tmp = RowCount - 1; - if (tmp < 0) tmp = 0; - - BookSearchCount = IsHave(BookSearchCount, tmp); - dataGridView1.Rows[a].Cells["Count"].Value = BookSearchCount; + webBrowser1.DocumentCompleted -= this.webBrowser1_DocumentCompleted; + return; } + else if (URL.IndexOf("lib.jeonnam.go.kr") > -1) + { + for (int a = 0; a < SCount; a++) + { + if (dataGridView1.Rows[a].Cells["book_name"].Value == null) + continue; + + if (dataGridView1.Rows[a].Cells["book_name"].Value.ToString() == "") + continue; + + if (isStop) + break; + + string BookSearchCount = CopyCount(dataGridView1.Rows[a].Cells["book_name"].Value.ToString()); + + if (BookSearchCount == "false") + { + MessageBox.Show("검색대상이 설정되지않았습니다!"); + return; + } + + if (BookSearchCount == "0" || BookSearchCount == "" || BookSearchCount == "미소장") + { + dataGridView1.Rows[a].DefaultCellStyle.BackColor = Color.LightGray; + dataGridView1.Rows[a].DefaultCellStyle.ForeColor = Color.Red; + BookSearchCount = ""; + } + else + { + dataGridView1.Rows[a].DefaultCellStyle.BackColor = Color.Yellow; + dataGridView1.Rows[a].DefaultCellStyle.ForeColor = Color.Blue; + } + + int tmp = RowCount - 1; + if (tmp < 0) tmp = 0; + + BookSearchCount = IsHave(BookSearchCount, tmp); + dataGridView1.Rows[a].Cells["Count"].Value = BookSearchCount; + } + } + else + { + if (URL.IndexOf("218.157.123.2:9996/kcms/Main") > -1) + webBrowser1.Navigate(URL + "/" + Code); + + else + webBrowser1.Navigate(URL); + + webBrowser1.DocumentCompleted += this.webBrowser1_DocumentCompleted; + return; + } + } else { - if (URL.IndexOf("218.157.123.2:9996/kcms/Main") > -1) - webBrowser1.Navigate(URL + "/" + Code); + if(DateTime.Now > new DateTime(2025,08,31)) + { + UTIL.MsgE("테스트 기간이 종료되었습니다\n개발자 문의 하세요"); + return; + } + + if (this._isDriverReady == false) + { + UTIL.MsgE("웹드라이버가 초기화되지 않았습니다\n1.크롬브라우즈가 설치되어있는지 확인하세요\n\n2.개발자 문의하세요"); + return; + } + + try + { + //chrome web driver + webBrowser1.Visible = false; + var searcher = this._searchService.Get(this.SearcherNo.toInt()); + if (searcher == null) + { + UTIL.MsgE($"검색서비스가 존재하지 않습니다. 개발자에 문의 하세요\n검색서비스번호:{SearcherNo}"); + return; + } + + this._isSearching = true; + btn_Start.Enabled = false; + btn_Stop.Enabled = false; + searcher.StartDriver(); + foreach (DataGridViewRow drow in this.dataGridView1.Rows) + { + if (this._isSearching == false) + { + drow.Cells["Count"].Value = "SKIP"; + continue; + } + + dataGridView1.CurrentCell = drow.Cells[0]; + //var vBookName = drow.Cells["book_name"].Value; + var bookName = drow.Cells["book_name"].Value?.ToString() ?? string.Empty; + if (bookName.isEmpty()) + { + drow.DefaultCellStyle.BackColor = Color.HotPink; + drow.DefaultCellStyle.ForeColor = Color.Blue; + continue; + } + + var cntValue = drow.Cells["Count"].Value?.ToString() ?? string.Empty; + if (cntValue.Equals("SKIP")) + { + drow.DefaultCellStyle.BackColor = Color.LightSkyBlue; + drow.DefaultCellStyle.ForeColor = Color.Black; + continue; + } + + + var rlt = await searcher.SearchAsync(bookName); + if (rlt.IsSuccess) + { + drow.Cells["Count"].Value = $"{rlt.BookCount}"; + if (rlt.BookCount == 0) + { + drow.DefaultCellStyle.BackColor = Color.LightGray; + drow.DefaultCellStyle.ForeColor = Color.Red; + } + else + { + drow.DefaultCellStyle.BackColor = Color.Yellow; + drow.DefaultCellStyle.ForeColor = Color.Blue; + } + } + else + { + drow.DefaultCellStyle.BackColor = Color.HotPink; + drow.DefaultCellStyle.ForeColor = Color.Blue; + } + + + } + searcher.StopDriver(); + UTIL.MsgI("검색 완료"); + } + catch (Exception ex) + { + UTIL.MsgE("Web Driver Error\n"+ex.Message); + } + finally + { + btn_Stop.Enabled = true; + btn_Start.Enabled = true; + this._isSearching = false; + } - else - webBrowser1.Navigate(URL); - webBrowser1.DocumentCompleted += this.webBrowser1_DocumentCompleted; - return; } + + } int RowCount = 0; @@ -195,7 +427,7 @@ namespace WindowsFormsApp1.Mac break; } } - if(searchform != null) + if (searchform != null) { BookCount = 광주남구결과(); } @@ -470,7 +702,7 @@ namespace WindowsFormsApp1.Mac foreach (HtmlElement Btn in searchform.GetElementsByTagName("button")) { - if (Btn.GetAttribute("type").IndexOf("submit") >-1)//.IndexOf("btn btn-search") > -1) + if (Btn.GetAttribute("type").IndexOf("submit") > -1)//.IndexOf("btn btn-search") > -1) Btn.InvokeMember("click"); } } @@ -1348,6 +1580,7 @@ namespace WindowsFormsApp1.Mac private void btn_Stop_Click(object sender, EventArgs e) { + _isSearching = false; webBrowser1.Stop(); webBrowser1.DocumentCompleted -= this.webBrowser1_DocumentCompleted; } @@ -1592,11 +1825,6 @@ namespace WindowsFormsApp1.Mac this.Close(); } - private void Check_copy_Load(object sender, EventArgs e) - { - string[] Grid = { "----- 빈칸으로 놔주세요 -----", "빈칸", "" }; - dataGridView1.Rows.Add(Grid); - } private void Check_copy_FormClosing(object sender, FormClosingEventArgs e) { @@ -1607,15 +1835,12 @@ namespace WindowsFormsApp1.Mac private void btn_SiteDenote_Click(object sender, EventArgs e) { if (URL == null) return; - try - { - System.Diagnostics.Process.Start(URL); - } - catch - { - - } + AR.UTIL.RunExplorer(URL); + } + private void btSearchLibrary_Click(object sender, EventArgs e) + { + SearchLibrary(); } } } diff --git a/unimarc/unimarc/마크/Check_copy.resx b/unimarc/unimarc/마크/Check_copy.resx index e5d7bca..feaaebf 100644 --- a/unimarc/unimarc/마크/Check_copy.resx +++ b/unimarc/unimarc/마크/Check_copy.resx @@ -126,4 +126,7 @@ True + + 17, 17 + \ No newline at end of file