This commit is contained in:
2025-07-06 21:15:19 +09:00
parent d2018c0143
commit eeb3c2f845
6 changed files with 216 additions and 110 deletions

View File

@@ -7,6 +7,7 @@ using System.Text.RegularExpressions;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
using System.IO;
using System.Runtime.InteropServices;
namespace BokBonCheck
{
@@ -65,6 +66,54 @@ namespace BokBonCheck
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)
{
@@ -92,44 +141,22 @@ namespace BokBonCheck
SearchTime = DateTime.Now
};
IWebDriver driver = null;
ChromeDriverService service = null;
try
{
// ChromeDriverManager에서 설정한 드라이버 경로 사용
var driverPath = ChromeDriverManager.GetDriverPath();
if (string.IsNullOrEmpty(driverPath) || !File.Exists(driverPath))
{
// 드라이버가 없으면 다시 설정
driverPath = await ChromeDriverManager.SetupChromeDriverAsync();
}
if (_driver == null)
throw new InvalidOperationException("드라이버가 시작되지 않았습니다. StartDriver()를 먼저 호출하세요.");
// ChromeDriver 서비스 설정
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);
_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);
@@ -173,7 +200,7 @@ namespace BokBonCheck
}
// 혹시 readonly라면 속성 제거
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].removeAttribute('readonly')", searchBox);
((IJavaScriptExecutor)_driver).ExecuteScript("arguments[0].removeAttribute('readonly')", searchBox);
// 입력 전 clear
searchBox.Clear();
@@ -187,12 +214,11 @@ namespace BokBonCheck
{
"input[type='submit']",
};
//#frm_sch > fieldset > div > div.search_style > div > input
foreach (var selector in buttonSelectors)
{
try
{
searchButton = driver.FindElement(By.CssSelector(selector));
searchButton = _driver.FindElement(By.CssSelector(selector));
break;
}
catch
@@ -217,11 +243,11 @@ namespace BokBonCheck
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.IsSuccess = true;
@@ -232,12 +258,6 @@ namespace BokBonCheck
result.ErrorMessage = ex.Message;
result.BookCount = 0;
}
finally
{
driver?.Quit();
driver?.Dispose();
service?.Dispose();
}
return result;
}
@@ -262,6 +282,34 @@ namespace BokBonCheck
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}");
}
}
}
}