..
This commit is contained in:
		
							
								
								
									
										3
									
								
								BokBonCheck/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								BokBonCheck/.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | { | ||||||
|  |     "dotnet.preferCSharpExtension": true | ||||||
|  | } | ||||||
| @@ -22,6 +22,18 @@ namespace BokBonCheck | |||||||
|             _searchService = new BookSearchService(); |             _searchService = new BookSearchService(); | ||||||
|             InitializeUI(); |             InitializeUI(); | ||||||
|             InitializeChromeDriver(); |             InitializeChromeDriver(); | ||||||
|  |  | ||||||
|  |             //_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_Children()); | ||||||
|  |             //_searchService.AddSearcher(new NamguLibrarySearcher_Hyocheon()); | ||||||
|  |             //_searchService.AddSearcher(new NamguLibrarySearcher_Munhwa()); | ||||||
|  |             _searchService.AddSearcher(new NamguLibrarySearcher_Purungil()); | ||||||
|  |             //_searchService.AddSearcher(new NamguLibrarySearcher_Smart()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async void InitializeChromeDriver() |         private async void InitializeChromeDriver() | ||||||
|   | |||||||
| @@ -23,18 +23,6 @@ namespace BokBonCheck | |||||||
|         { |         { | ||||||
|             _searchers = new List<ILibrarySearcher> |             _searchers = new List<ILibrarySearcher> | ||||||
|             { |             { | ||||||
|                 new KwangjuCityLibrarySearcher_central(), |  | ||||||
|                 new KwangjuCityLibrarySearcher_choisangjun(), |  | ||||||
|                 new KwangjuCityLibrarySearcher_dagachi(), |  | ||||||
|                 new KwangjuCityLibrarySearcher_Indi(), |  | ||||||
|                 new KwangjuCityLibrarySearcher_Student(), |  | ||||||
|                 new KwangjuCityLibrarySearcher_Kumho(), |  | ||||||
|  |  | ||||||
|                 new NamguLibrarySearcher_Children(), |  | ||||||
|                  new NamguLibrarySearcher_Hyocheon(), |  | ||||||
|                   new NamguLibrarySearcher_Munhwa(), |  | ||||||
|                    new NamguLibrarySearcher_Purungil(), |  | ||||||
|                     new NamguLibrarySearcher_Smart(), |  | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -44,8 +32,10 @@ namespace BokBonCheck | |||||||
|  |  | ||||||
|             foreach (var searcher in _searchers) |             foreach (var searcher in _searchers) | ||||||
|             { |             { | ||||||
|  |                 searcher.StartDriver(); | ||||||
|                 var result = await searcher.SearchAsync(searchTerm); |                 var result = await searcher.SearchAsync(searchTerm); | ||||||
|                 results.Add(result); |                 results.Add(result); | ||||||
|  |                 //searcher.StopDriver(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return results; |             return results; | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | using OpenQA.Selenium.Support.UI; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace BokBonCheck | namespace BokBonCheck | ||||||
| @@ -7,5 +8,9 @@ namespace BokBonCheck | |||||||
|         string SiteName { get; } |         string SiteName { get; } | ||||||
|         string SiteUrl { get; } |         string SiteUrl { get; } | ||||||
|         Task<BookSearchResult> SearchAsync(string searchTerm); |         Task<BookSearchResult> SearchAsync(string searchTerm); | ||||||
|  |         void StartDriver(); | ||||||
|  |         void StopDriver(); | ||||||
|  |  | ||||||
|  |         Task WaitForPageChange(WebDriverWait wait); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; | |||||||
| using WebDriverManager; | using WebDriverManager; | ||||||
| using WebDriverManager.DriverConfigs.Impl; | using WebDriverManager.DriverConfigs.Impl; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  |  | ||||||
| namespace BokBonCheck | namespace BokBonCheck | ||||||
| { | { | ||||||
| @@ -65,6 +66,54 @@ namespace BokBonCheck | |||||||
|  |  | ||||||
|         protected string SelectorValue = ""; |         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 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) |         virtual protected void SelectLibrary(WebDriverWait wait) | ||||||
|         { |         { | ||||||
| @@ -92,44 +141,22 @@ namespace BokBonCheck | |||||||
|                 SearchTime = DateTime.Now |                 SearchTime = DateTime.Now | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             IWebDriver driver = null; |  | ||||||
|             ChromeDriverService service = null; |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 // ChromeDriverManager에서 설정한 드라이버 경로 사용 |                 if (_driver == null) | ||||||
|                 var driverPath = ChromeDriverManager.GetDriverPath(); |                    throw new InvalidOperationException("드라이버가 시작되지 않았습니다. StartDriver()를 먼저 호출하세요."); | ||||||
|                 if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) |  | ||||||
|                 { |  | ||||||
|                     // 드라이버가 없으면 다시 설정 |  | ||||||
|                     driverPath = await ChromeDriverManager.SetupChromeDriverAsync(); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 // ChromeDriver 서비스 설정 |                 _driver.Navigate().GoToUrl(SiteUrl); | ||||||
|                 service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); |  | ||||||
|                 service.HideCommandPromptWindow = true; |  | ||||||
|  |  | ||||||
|                 var options = new ChromeOptions(); |  | ||||||
|                 options.AddArgument("--headless"); |  | ||||||
|                 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})"); |  | ||||||
|  |  | ||||||
|                 driver.Navigate().GoToUrl(SiteUrl); |  | ||||||
|  |  | ||||||
|                 // 페이지 로딩 대기 |                 // 페이지 로딩 대기 | ||||||
|                 var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15)); |                 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); |                 SelectLibrary(wait); | ||||||
| @@ -173,7 +200,7 @@ namespace BokBonCheck | |||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // 혹시 readonly라면 속성 제거 |                 // 혹시 readonly라면 속성 제거 | ||||||
|                 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].removeAttribute('readonly')", searchBox); |                 ((IJavaScriptExecutor)_driver).ExecuteScript("arguments[0].removeAttribute('readonly')", searchBox); | ||||||
|  |  | ||||||
|                 // 입력 전 clear |                 // 입력 전 clear | ||||||
|                 searchBox.Clear(); |                 searchBox.Clear(); | ||||||
| @@ -187,12 +214,11 @@ namespace BokBonCheck | |||||||
|                     { |                     { | ||||||
|                         "input[type='submit']", |                         "input[type='submit']", | ||||||
|                     }; |                     }; | ||||||
|                     //#frm_sch > fieldset > div > div.search_style > div > input |  | ||||||
|                     foreach (var selector in buttonSelectors) |                     foreach (var selector in buttonSelectors) | ||||||
|                     { |                     { | ||||||
|                         try |                         try | ||||||
|                         { |                         { | ||||||
|                             searchButton = driver.FindElement(By.CssSelector(selector)); |                             searchButton = _driver.FindElement(By.CssSelector(selector)); | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                         catch |                         catch | ||||||
| @@ -217,11 +243,11 @@ namespace BokBonCheck | |||||||
|                     searchBox.SendKeys(Keys.Enter); |                     searchBox.SendKeys(Keys.Enter); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // 검색 결과 로딩 대기 |                 // 페이지 변경을 감지하는 메서드 | ||||||
|                 await Task.Delay(3000); |                 await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15))); | ||||||
|  |  | ||||||
|                 // 검색 결과 수 추출 |                 // 검색 결과 수 추출 | ||||||
|                 var resultCount = ExtractBookCount(driver); |                 var resultCount = ExtractBookCount(_driver); | ||||||
|  |  | ||||||
|                 result.BookCount = resultCount; |                 result.BookCount = resultCount; | ||||||
|                 result.IsSuccess = true; |                 result.IsSuccess = true; | ||||||
| @@ -232,12 +258,6 @@ namespace BokBonCheck | |||||||
|                 result.ErrorMessage = ex.Message; |                 result.ErrorMessage = ex.Message; | ||||||
|                 result.BookCount = 0; |                 result.BookCount = 0; | ||||||
|             } |             } | ||||||
|             finally |  | ||||||
|             { |  | ||||||
|                 driver?.Quit(); |  | ||||||
|                 driver?.Dispose(); |  | ||||||
|                 service?.Dispose(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return result; |             return result; | ||||||
|         } |         } | ||||||
| @@ -262,6 +282,34 @@ namespace BokBonCheck | |||||||
|                 return 0; |                 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}"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -7,6 +7,7 @@ using System.Text.RegularExpressions; | |||||||
| using WebDriverManager; | using WebDriverManager; | ||||||
| using WebDriverManager.DriverConfigs.Impl; | using WebDriverManager.DriverConfigs.Impl; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  |  | ||||||
| namespace BokBonCheck | namespace BokBonCheck | ||||||
| { | { | ||||||
| @@ -76,7 +77,6 @@ namespace BokBonCheck | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public class NamguLibrarySearcher_Children : NamguLibrarySearcher |     public class NamguLibrarySearcher_Children : NamguLibrarySearcher | ||||||
|     { |     { | ||||||
|         public NamguLibrarySearcher_Children() |         public NamguLibrarySearcher_Children() | ||||||
| @@ -110,7 +110,6 @@ namespace BokBonCheck | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public class NamguLibrarySearcher_Hyocheon : NamguLibrarySearcher |     public class NamguLibrarySearcher_Hyocheon : NamguLibrarySearcher | ||||||
|     { |     { | ||||||
|         public NamguLibrarySearcher_Hyocheon() |         public NamguLibrarySearcher_Hyocheon() | ||||||
| @@ -177,12 +176,61 @@ namespace BokBonCheck | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public class NamguLibrarySearcher : ILibrarySearcher |     public class NamguLibrarySearcher : ILibrarySearcher | ||||||
|     { |     { | ||||||
|         public string SiteName { get; protected set; } = "남구통합도서관(전체)"; |         public string SiteName { get; protected set; } = "남구통합도서관(전체)"; | ||||||
|         public string SiteUrl => "https://lib.namgu.gwangju.kr/main/bookSearch"; |         public string SiteUrl => "https://lib.namgu.gwangju.kr/main/bookSearch"; | ||||||
|  |  | ||||||
|  |         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 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) |         virtual protected void SelectLibrary(WebDriverWait wait) | ||||||
|         { |         { | ||||||
|             IWebElement searchBox = null; |             IWebElement searchBox = null; | ||||||
| @@ -211,44 +259,22 @@ namespace BokBonCheck | |||||||
|                 SearchTime = DateTime.Now |                 SearchTime = DateTime.Now | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             IWebDriver driver = null; |  | ||||||
|             ChromeDriverService service = null; |  | ||||||
|  |  | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 // ChromeDriverManager에서 설정한 드라이버 경로 사용 |                 if (_driver == null) | ||||||
|                 var driverPath = ChromeDriverManager.GetDriverPath(); |                     throw new InvalidOperationException("드라이버가 시작되지 않았습니다. StartDriver()를 먼저 호출하세요."); | ||||||
|                 if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath)) |  | ||||||
|                 { |  | ||||||
|                     // 드라이버가 없으면 다시 설정 |  | ||||||
|                     driverPath = await ChromeDriverManager.SetupChromeDriverAsync(); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 // ChromeDriver 서비스 설정 |                 _driver.Navigate().GoToUrl(SiteUrl); | ||||||
|                 service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(driverPath), Path.GetFileName(driverPath)); |  | ||||||
|                 service.HideCommandPromptWindow = true; |  | ||||||
|  |  | ||||||
|                 var options = new ChromeOptions(); |  | ||||||
|                 options.AddArgument("--headless"); |  | ||||||
|                 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})"); |  | ||||||
|  |  | ||||||
|                 driver.Navigate().GoToUrl(SiteUrl); |  | ||||||
|  |  | ||||||
|                 // 페이지 로딩 대기 |                 // 페이지 로딩 대기 | ||||||
|                 var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15)); |                 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); |                 SelectLibrary(wait); | ||||||
| @@ -312,7 +338,7 @@ namespace BokBonCheck | |||||||
|                     { |                     { | ||||||
|                         try |                         try | ||||||
|                         { |                         { | ||||||
|                             searchButton = driver.FindElement(By.CssSelector(selector)); |                             searchButton = _driver.FindElement(By.CssSelector(selector)); | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                         catch |                         catch | ||||||
| @@ -337,11 +363,11 @@ namespace BokBonCheck | |||||||
|                     searchBox.SendKeys(Keys.Enter); |                     searchBox.SendKeys(Keys.Enter); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // 검색 결과 로딩 대기 |                 // 페이지 변경을 감지하는 메서드 | ||||||
|                 await Task.Delay(3000); |                 await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15))); | ||||||
|  |  | ||||||
|                 // 검색 결과 수 추출 |                 // 검색 결과 수 추출 | ||||||
|                 var resultCount = ExtractBookCount(driver); |                 var resultCount = ExtractBookCount(_driver); | ||||||
|  |  | ||||||
|                 result.BookCount = resultCount; |                 result.BookCount = resultCount; | ||||||
|                 result.IsSuccess = true; |                 result.IsSuccess = true; | ||||||
| @@ -352,12 +378,6 @@ namespace BokBonCheck | |||||||
|                 result.ErrorMessage = ex.Message; |                 result.ErrorMessage = ex.Message; | ||||||
|                 result.BookCount = 0; |                 result.BookCount = 0; | ||||||
|             } |             } | ||||||
|             finally |  | ||||||
|             { |  | ||||||
|                 driver?.Quit(); |  | ||||||
|                 driver?.Dispose(); |  | ||||||
|                 service?.Dispose(); |  | ||||||
|             } |  | ||||||
|          |          | ||||||
|             return result; |             return result; | ||||||
|         } |         } | ||||||
| @@ -382,5 +402,33 @@ namespace BokBonCheck | |||||||
|                 return 0; |                 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}"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user