(_libraryDelaySettings);
+ }
+
+ ///
+ /// 특정 도서관의 지연시간 설정을 제거
+ ///
+ /// 도서관 이름
+ public void RemoveDelay(string libraryName)
+ {
+ if (string.IsNullOrEmpty(libraryName))
+ return;
+
+ if (_libraryDelaySettings.ContainsKey(libraryName))
+ {
+ _libraryDelaySettings.Remove(libraryName);
+ SaveSettings();
+ Console.WriteLine($"도서관 지연시간 설정 제거: {libraryName}");
+ }
+ }
+
+ ///
+ /// 모든 지연시간 설정을 초기화
+ ///
+ public void ClearAllSettings()
+ {
+ _libraryDelaySettings.Clear();
+ SaveSettings();
+ Console.WriteLine("모든 도서관 지연시간 설정 초기화");
+ }
+ }
+}
\ No newline at end of file
diff --git a/unimarc/unimarc/Program.cs b/unimarc/unimarc/Program.cs
index b501d02..354aae5 100644
--- a/unimarc/unimarc/Program.cs
+++ b/unimarc/unimarc/Program.cs
@@ -30,14 +30,9 @@ namespace WindowsFormsApp1
Application.Run(new Main());
}
-
-
-
-
-
static void DB_InitSetting()
{
- UniMarc.Properties.Settings.Default.IP = ConvertIP(UniMarc.Properties.Settings.Default.IP);
+ UniMarc.Properties.Settings.Default.IP = ConvertIP(UniMarc.Properties.Settings.Default.IP);
UniMarc.Properties.Settings.Default.Port = Convert2to10(UniMarc.Properties.Settings.Default.Port);
UniMarc.Properties.Settings.Default.Uid = ConvertAscii(UniMarc.Properties.Settings.Default.Uid);
UniMarc.Properties.Settings.Default.pwd = ConvertAscii(UniMarc.Properties.Settings.Default.pwd);
diff --git a/unimarc/unimarc/Properties/AssemblyInfo.cs b/unimarc/unimarc/Properties/AssemblyInfo.cs
index d620c5a..7b74652 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("2025.09.03.2030")]
-[assembly: AssemblyFileVersion("2025.09.03.2030")]
+[assembly: AssemblyVersion("2025.09.16.0000")]
+[assembly: AssemblyFileVersion("2025.09.16.0000")]
diff --git a/unimarc/unimarc/SearchModel/AnsanLibSearcher.cs b/unimarc/unimarc/SearchModel/AnsanLibSearcher.cs
index 395368d..bb5b7e3 100644
--- a/unimarc/unimarc/SearchModel/AnsanLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/AnsanLibSearcher.cs
@@ -397,8 +397,10 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ // SearchAsync에서 PageSource 가져오기
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -423,128 +425,40 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
-
- if (driver.Url.EndsWith("DetailSearchResult") == false)
- {
- errmessage = "결과페이지가아님";
- return -1;
- }
-
+ resulthtml = string.Empty;
try
{
- // 1. 검색결과가 없는 경우 확인
- try
+ // 검색 결과가 없다는 메시지 확인
+ var noResultPatterns = new[]
{
- var noResultElements = driver.FindElements(By.XPath("//*[contains(text(), '검색결과가 없습니다') or contains(text(), '검색된 자료가 없습니다')]"));
- if (noResultElements.Count > 0)
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다",
+ @"총 0 건",
+ @"총 0건"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
{
errmessage = "검색결과없음";
- return 0;
- }
- }
- catch
- {
- // 검색결과가 있는 경우로 진행
- }
-
-
- RetryPoint:
- bool retry = false;
- // 2. 안산시 도서관 특화: span.count.gothic em 요소에서 직접 추출
- try
- {
-
-
- var countElement = driver.FindElement(By.CssSelector("span.count.gothic em"));
- if (countElement != null)
- {
- // Text 대신 InnerHtml이나 GetAttribute 사용해보기
- var countText = countElement.Text.Trim();
- var innerHTML = countElement.GetAttribute("innerHTML");
- var outerHTML = countElement.GetAttribute("outerHTML");
-
- Console.WriteLine($"count 요소 .Text: '{countText}'");
- Console.WriteLine($"count 요소 innerHTML: '{innerHTML}'");
- Console.WriteLine($"count 요소 outerHTML: '{outerHTML}'");
-
- // innerHTML이나 outerHTML에서 텍스트 추출 시도
- string textToUse = !string.IsNullOrEmpty(countText) ? countText : innerHTML;
- if (string.IsNullOrEmpty(textToUse))
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
{
- textToUse = outerHTML;
- }
-
- Console.WriteLine($"추출할 텍스트: '{textToUse}'");
-
- // "총 0 건 " 형태에서 숫자 추출
- var match = Regex.Match(textToUse, @"총\s*(\d+)\s*건", RegexOptions.IgnoreCase);
- if (match.Success && int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- Console.WriteLine("검색 결과: 0건");
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- Console.WriteLine($"검색 결과: {count}건");
- return count;
+ resulthtml = ExtractResultContext(htmlContent, match);
}
else
{
- Console.WriteLine($"정규식 매칭 실패: '{textToUse}'");
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
}
+ return 0;
}
}
- catch (Exception ex1)
- {
- Console.WriteLine($"span.count.gothic em 요소 추출 실패: {ex1.Message}");
- }
-
- // 3. span.count 전체에서 추출 시도
- try
- {
- var countSpan = driver.FindElement(By.CssSelector("span.count"));
- if (countSpan != null)
- {
- var fullText = countSpan.Text.Trim();
- Console.WriteLine($"count span 전체 텍스트: '{fullText}'");
-
- var match = Regex.Match(fullText, @"총\s*(\d+)\s*건", RegexOptions.IgnoreCase);
- if (match.Success && int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
- }
- }
- catch (Exception ex2)
- {
- Console.WriteLine($"span.count 요소 추출 실패: {ex2.Message}");
- }
-
- // 3. 페이지 소스에서 정규식으로 추출 시도
- var pageSource = driver.PageSource;
-
- // 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다") ||
- pageSource.Contains("자료가 없습니다") ||
- pageSource.Contains("총 0 건") ||
- pageSource.Contains("총 0건"))
- {
- errmessage = "검색결과없음";
- return 0;
- }
// HTML에서 다양한 패턴 찾기 (안산시 도서관 특화)
var htmlPatterns = new[]
@@ -560,11 +474,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -576,28 +493,81 @@ namespace BokBonCheck
}
}
- if (retry == false)
- {
- Console.WriteLine( "결과를 찾을 수 없어 재시도");
- retry = true;
- Task.Delay(1000);
- goto RetryPoint;
- }
- else
- {
- errmessage = "결과수량을찾을수없음";
- return -1;
- }
-
+ errmessage = "결과수량을찾을수없음";
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/BookSearchService.cs b/unimarc/unimarc/SearchModel/BookSearchService.cs
index 94634b7..4d85522 100644
--- a/unimarc/unimarc/SearchModel/BookSearchService.cs
+++ b/unimarc/unimarc/SearchModel/BookSearchService.cs
@@ -13,6 +13,8 @@ namespace BokBonCheck
public DateTime SearchTime { get; set; }
public string ErrorMessage { get; set; }
public bool IsSuccess { get; set; }
+
+ public string Resulthtml { get; set; }
}
public class BookSearchService
diff --git a/unimarc/unimarc/SearchModel/BukguLibSearcher.cs b/unimarc/unimarc/SearchModel/BukguLibSearcher.cs
index 76d7430..43a3da0 100644
--- a/unimarc/unimarc/SearchModel/BukguLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/BukguLibSearcher.cs
@@ -244,8 +244,9 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -270,73 +271,39 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
+
try
{
- // 1. totalCount 요소에서 직접 추출 시도
- try
+ // 검색 결과가 없다는 메시지 확인
+ var noResultPatterns = new[]
{
- var totalCountElement = driver.FindElement(By.CssSelector("p.totalCount"));
- if (totalCountElement != null)
- {
- // strong 태그에서 직접 숫자 추출 시도
- try
- {
- var strongElement = totalCountElement.FindElement(By.TagName("strong"));
- if (strongElement != null)
- {
- var countText = strongElement.Text.Trim();
- if (int.TryParse(countText, out int strongCount))
- {
- if (strongCount == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({strongCount}권)";
- return strongCount;
- }
- }
- }
- catch { }
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다",
+ @"전체 0 건"
+ };
- // 전체 텍스트에서 정규식으로 추출
- var totalCountText = totalCountElement.Text;
- var match = Regex.Match(totalCountText, @"전체\s*(\d+)\s*건", RegexOptions.IgnoreCase);
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
+ {
+ errmessage = "검색결과없음";
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
if (match.Success)
{
- if (int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
+ resulthtml = ExtractResultContext(htmlContent, match);
}
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ return 0;
}
}
- catch (Exception ex)
- {
- Console.WriteLine($"totalCount 요소 검색 중 오류: {ex.Message}");
- }
-
- // 2. 페이지 소스에서 정규식으로 추출 시도
- var pageSource = driver.PageSource;
-
- // 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다") ||
- pageSource.Contains("자료가 없습니다") ||
- pageSource.Contains("전체 0 건"))
- {
- errmessage = "검색결과없음";
- return 0;
- }
// HTML에서 다양한 패턴 찾기
var htmlPatterns = new[]
@@ -350,11 +317,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -367,16 +337,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/ChosunTechLibSearcher.cs b/unimarc/unimarc/SearchModel/ChosunTechLibSearcher.cs
index 8d1c14f..73d04a0 100644
--- a/unimarc/unimarc/SearchModel/ChosunTechLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/ChosunTechLibSearcher.cs
@@ -69,7 +69,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -84,7 +84,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -112,19 +113,21 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
// 1. 검색 결과가 없는 경우 확인
if (htmlContent.Contains("검색결과가 없습니다") ||
htmlContent.Contains("검색된 자료가 없습니다") ||
- htmlContent.Contains("자료가 없습니다") ||
+ htmlContent.Contains("자룼가 없습니다") ||
htmlContent.Contains("0 Results:"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -147,8 +150,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"조선이공대학교도서관 검색 결과: {count}건");
return count;
@@ -173,22 +179,27 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"조선이공대학교도서관 검색 결과: {count}건");
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
errorMessage = "검색결과 패턴을 찾을 수 없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
Console.WriteLine("조선이공대학교도서관 검색결과 패턴을 찾을 수 없음");
return -1;
}
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "결과 분석 오류: " + ex.Message;
return -1;
}
}
@@ -197,5 +208,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/ChosunUnivLibSearcher.cs b/unimarc/unimarc/SearchModel/ChosunUnivLibSearcher.cs
index d9c7536..2f27496 100644
--- a/unimarc/unimarc/SearchModel/ChosunUnivLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/ChosunUnivLibSearcher.cs
@@ -69,7 +69,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -84,7 +84,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -112,9 +113,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -125,6 +127,7 @@ namespace BokBonCheck
htmlContent.Contains("총 0건"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -147,8 +150,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"조선대학교중앙도서관 검색 결과: {count}건");
return count;
@@ -173,22 +179,28 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"조선대학교중앙도서관 검색 결과: {count}건");
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
errorMessage = "검색결과 패턴을 찾을 수 없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
Console.WriteLine("조선대학교중앙도서관 검색결과 패턴을 찾을 수 없음");
return -1;
}
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "결과 분석 오류: " + ex.Message;
return -1;
}
}
@@ -197,5 +209,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/GochangLibSearcher.cs b/unimarc/unimarc/SearchModel/GochangLibSearcher.cs
index 90fb781..6be35f1 100644
--- a/unimarc/unimarc/SearchModel/GochangLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GochangLibSearcher.cs
@@ -148,7 +148,10 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ // SearchAsync에서 PageSource 가져오기
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -173,60 +176,54 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
+
try
{
- try
+ var noResultPatterns = new[]
{
- var noResultElement = driver.FindElement(By.XPath("//*[contains(text(), '검색된 도서가 없습니다') or contains(text(), '검색결과가 없습니다')]"));
- if (noResultElement != null)
+ @"검색된 도서가 없습니다",
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
{
errmessage = "검색결과없음";
- return 0;
- }
- }
- catch
- {
- }
-
- try
- {
- var resultElement = driver.FindElement(By.CssSelector(".subTapContWrap.on p"));
- if (resultElement != null)
- {
- var resultText = resultElement.Text;
- var match = Regex.Match(resultText, @"총\s*(\d+)건", RegexOptions.IgnoreCase);
- if (match.Success)
+ // 검색결과 없음 메시지를 포함한 HTML 조각 추출
+ var index = htmlContent.IndexOf(pattern);
+ if (index >= 0)
{
- if (int.TryParse(match.Groups[1].Value, out int count))
+ var startIndex = Math.Max(0, index - 100);
+ var endIndex = Math.Min(htmlContent.Length, index + pattern.Length + 100);
+ resulthtml = htmlContent.Substring(startIndex, endIndex - startIndex);
+
+ // 상위 태그 찾기 시도
+ try
{
- if (count == 0)
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
{
- errmessage = "검색결과없음";
- return 0;
+ resulthtml = ExtractResultContext(htmlContent, match);
}
- errmessage = $"검색성공({count}권)";
- return count;
+ }
+ catch
+ {
+ // 실패시 기본 추출 결과 사용
}
}
+ else
+ {
+ resulthtml = pattern;
+ }
+ return 0;
}
}
- catch (Exception ex)
- {
- Console.WriteLine($"결과 요소 검색 중 오류: {ex.Message}");
- }
-
- var pageSource = driver.PageSource;
-
- if (pageSource.Contains("검색된 도서가 없습니다") ||
- pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다"))
- {
- errmessage = "검색결과없음";
- return 0;
- }
var htmlPatterns = new[]
{
@@ -237,11 +234,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -254,16 +254,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = "결과수량을찾을수없음";
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "ExtractBookCount 오류: " + ex.Message;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
public async Task WaitForPageChange(WebDriverWait wait)
{
try
diff --git a/unimarc/unimarc/SearchModel/GoheungLibSearcher.cs b/unimarc/unimarc/SearchModel/GoheungLibSearcher.cs
index fde295f..f6e734d 100644
--- a/unimarc/unimarc/SearchModel/GoheungLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GoheungLibSearcher.cs
@@ -218,8 +218,9 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -244,67 +245,21 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
+
try
{
- // 1. 먼저 totalCount 요소에서 직접 추출 시도
- try
- {
- var totalCountElement = driver.FindElement(By.CssSelector("p.totalCount"));
- if (totalCountElement != null)
- {
- var totalCountText = totalCountElement.Text; // 예: "전체 1 건"
- var match = Regex.Match(totalCountText, @"전체\s+(\d+)\s+건", RegexOptions.IgnoreCase);
- if (match.Success)
- {
- if (int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
- }
-
- // strong 태그에서 직접 숫자 추출 시도
- try
- {
- var strongElement = totalCountElement.FindElement(By.TagName("strong"));
- if (strongElement != null && int.TryParse(strongElement.Text, out int strongCount))
- {
- if(strongCount == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
-
- errmessage = $"검색성공({strongCount}권)";
- return strongCount;
- }
- }
- catch { }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"totalCount 요소 검색 중 오류: {ex.Message}");
- }
-
- // 2. 페이지 소스에서 정규식으로 추출 시도
- var pageSource = driver.PageSource;
-
// 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다") ||
- pageSource.Contains("자료가 없습니다") ||
- pageSource.Contains("전체 0 건"))
+ if (htmlContent.Contains("검색결과가 없습니다") ||
+ htmlContent.Contains("검색된 자료가 없습니다") ||
+ htmlContent.Contains("자료가 없습니다") ||
+ htmlContent.Contains("전체 0 건"))
{
errmessage = "검색결과없음";
+ resulthtml = "검색결과가 없습니다";
return 0;
}
@@ -319,11 +274,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -335,49 +293,81 @@ namespace BokBonCheck
}
}
- // 3. 결과 테이블이나 리스트가 있는지 확인
- try
- {
- var resultElements = driver.FindElements(By.CssSelector(".bookList, .searchResult, .result-list, table tbody tr"));
- if (resultElements.Count > 0)
- {
- // 테이블 헤더나 빈 행을 제외한 실제 결과 개수 계산
- var actualCount = 0;
- foreach (var element in resultElements)
- {
- var text = element.Text?.Trim();
- if (!string.IsNullOrEmpty(text) &&
- !text.Contains("도서명") &&
- !text.Contains("저자") &&
- !text.Contains("출판사"))
- {
- actualCount++;
- }
- }
-
- if (actualCount > 0)
- {
- errmessage = $"검색성공({actualCount}권)";
- return actualCount;
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"결과 요소 검색 중 오류: {ex.Message}");
- }
-
errmessage = "결과수량을찾을수없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/GwangjuCityLibSearcher.cs b/unimarc/unimarc/SearchModel/GwangjuCityLibSearcher.cs
index b419b4e..15db808 100644
--- a/unimarc/unimarc/SearchModel/GwangjuCityLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GwangjuCityLibSearcher.cs
@@ -155,8 +155,9 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -181,87 +182,38 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
+
try
{
- // 1. 검색결과가 없는 경우 확인
- try
+ // 검색 결과가 없다는 메시지 확인
+ var noResultPatterns = new[]
{
- var noResultElement = driver.FindElement(By.XPath("//p[contains(text(), '조회된 도서가 없습니다')]"));
- if (noResultElement != null)
+ @"조회된 도서가 없습니다",
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
{
errmessage = "검색결과없음";
- return 0;
- }
- }
- catch
- {
- // 검색결과가 있는 경우로 진행
- }
-
- // 2. srch_info div에서 직접 추출 시도
- try
- {
- var srchInfoElement = driver.FindElement(By.CssSelector("div.srch_info"));
- if (srchInfoElement != null)
- {
- // span.heighlight에서 숫자 추출 시도
- try
- {
- var highlightElement = srchInfoElement.FindElement(By.CssSelector("span.heighlight"));
- if (highlightElement != null)
- {
- var countText = highlightElement.Text.Trim();
- if (int.TryParse(countText, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
- }
- }
- catch { }
-
- // 전체 텍스트에서 정규식으로 추출
- var srchInfoText = srchInfoElement.Text;
- var match = Regex.Match(srchInfoText, @"검색결과\s*총\s*(\d+)\s*건", RegexOptions.IgnoreCase);
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
if (match.Success)
{
- if (int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
+ resulthtml = ExtractResultContext(htmlContent, match);
}
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ return 0;
}
}
- catch (Exception ex)
- {
- Console.WriteLine($"srch_info 요소 검색 중 오류: {ex.Message}");
- }
-
- // 3. 페이지 소스에서 정규식으로 추출 시도
- var pageSource = driver.PageSource;
-
- // 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("조회된 도서가 없습니다") ||
- pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다"))
- {
- errmessage = "검색결과없음";
- return 0;
- }
// HTML에서 다양한 패턴 찾기
var htmlPatterns = new[]
@@ -274,11 +226,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -291,16 +246,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/GwangjuDongguLibSearcher.cs b/unimarc/unimarc/SearchModel/GwangjuDongguLibSearcher.cs
index 5f16854..6d8142d 100644
--- a/unimarc/unimarc/SearchModel/GwangjuDongguLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GwangjuDongguLibSearcher.cs
@@ -81,10 +81,11 @@ namespace BokBonCheck
// HTTP GET 요청 실행 (추가 헤더 포함)
using (var request = new HttpRequestMessage(HttpMethod.Get, searchUrl))
{
- // 브라우저와 유사한 헤더 추가
- request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
- request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ // 브라우저와 유사한 헤더 추가 (인코딩 문제 방지를 위해 압축 해제)
+ request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+ request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.9,en;q=0.1");
+ request.Headers.Add("Accept-Charset", "UTF-8,*;q=0.1");
+ // Accept-Encoding 제거 - 압축으로 인한 인코딩 문제 방지
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -96,10 +97,50 @@ namespace BokBonCheck
throw new HttpRequestException($"HTTP {(int)response.StatusCode} {response.StatusCode}: {errorContent}");
}
- var htmlContent = await response.Content.ReadAsStringAsync();
+ // 인코딩 문제 해결: 서버 응답의 Content-Type 확인 후 적절한 인코딩 사용
+ string htmlContent;
+ var contentType = response.Content.Headers.ContentType?.ToString() ?? "";
+ Console.WriteLine($"광주동구 Content-Type: {contentType}");
+
+ if (contentType.Contains("charset="))
+ {
+ // 서버에서 지정한 charset 사용
+ htmlContent = await response.Content.ReadAsStringAsync();
+ }
+ else
+ {
+ // charset이 명시되지 않은 경우 수동 처리
+ var responseBytes = await response.Content.ReadAsByteArrayAsync();
+
+ // UTF-8 먼저 시도
+ htmlContent = Encoding.UTF8.GetString(responseBytes);
+
+ // 한글이 없거나 깨진 경우 EUC-KR 시도
+ if (!ContainsKorean(htmlContent) || htmlContent.Contains("�"))
+ {
+ try
+ {
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ var euckrEncoding = Encoding.GetEncoding("EUC-KR");
+ var euckrContent = euckrEncoding.GetString(responseBytes);
+ if (ContainsKorean(euckrContent))
+ {
+ htmlContent = euckrContent;
+ Console.WriteLine("광주동구: EUC-KR 인코딩 사용");
+ }
+ }
+ catch (Exception encEx)
+ {
+ Console.WriteLine($"광주동구 EUC-KR 변환 오류: {encEx.Message}");
+ }
+ }
+ }
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+
+ // ResultHtml에 분석용 HTML 저장 (디버깅용으로 일부만)
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -126,10 +167,11 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage,out string resulthtml)
{
errorMessage = string.Empty;
-
+ resulthtml=string.Empty;
+
try
{
// 1. 검색 결과가 없는 경우 확인
@@ -141,18 +183,23 @@ namespace BokBonCheck
return 0;
}
- // 2. 검색 결과 수량 추출: 전체 2 건
+ // 2. 검색 결과 수량 추출 - 더 포괄적인 패턴 사용
var patterns = new[]
{
- @"]*class=""totalCount""[^>]*>전체\s*\s*(\d+)\s*\s*건
",
- @"전체\s*\s*(\d+)\s*\s*건",
- @"\s*(\d+)\s*\s*건",
- @"총\s*(\d+)\s*건"
+ // 기본 패턴들
+ @"전체\s*(?:\*\*)?(\d+)(?:\*\*)?\s*건", // 전체 **N** 건 또는 전체 N 건
+ @"]*>.*?전체\s*(?:\*\*)?(\d+)(?:\*\*)?\s*건.*?", // h태그 안의 전체 N 건
+ @"]*class=""totalCount""[^>]*>전체\s*\s*(\d+)\s*\s*건
", // 원래 패턴
+ @"전체\s*\s*(\d+)\s*\s*건", // strong 태그
+ @"\s*(\d+)\s*\s*건", // strong만
+ @"총\s*(\d+)\s*건", // 총 N 건
+ @"검색결과\s*:\s*(\d+)\s*건", // 검색결과: N 건
+ @"(\d+)\s*건의\s*검색결과", // N 건의 검색결과
};
foreach (var pattern in patterns)
{
- var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
@@ -160,25 +207,31 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value; // 매칭된 부분만 저장
return 0;
}
+
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
errorMessage = $"검색성공({count}권)";
- Console.WriteLine($"광주동구 검색 결과: {count}건");
+ Console.WriteLine($"광주동구 검색 결과: {count}건 (패턴: {pattern})");
return count;
}
}
}
- // 3. 더 자세한 패턴으로 시도 (줄바꿈 포함)
+ // 3. 멀티라인 패턴으로 재시도
var multilinePatterns = new[]
{
- @"전체\s*\s*\r?\n?\s*(\d+)\s*\r?\n?\s*\s*건",
- @"\s*\r?\n?\s*(\d+)\s*\r?\n?\s*\s*건"
+ @"전체\s*(?:\*\*)?[\r\n\s]*(\d+)[\r\n\s]*(?:\*\*)?\s*건",
+ @"전체\s*\s*[\r\n]*\s*(\d+)\s*[\r\n]*\s*\s*건",
+ @"\s*[\r\n]*\s*(\d+)\s*[\r\n]*\s*\s*건"
};
foreach (var pattern in multilinePatterns)
{
- var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
@@ -186,15 +239,24 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value; // 매칭된 부분만 저장
return 0;
}
+
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
errorMessage = $"검색성공({count}권)";
- Console.WriteLine($"광주동구 검색 결과: {count}건");
+ Console.WriteLine($"광주동구 검색 결과: {count}건 (멀티라인 패턴)");
return count;
}
}
}
-
+
+ // 4. 패턴을 찾지 못한 경우 - 디버깅을 위한 HTML 내용 일부 출력
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
+ Console.WriteLine($"광주동구 HTML 샘플: {resulthtml}");
+
errorMessage = "검색결과 패턴을 찾을 수 없음";
Console.WriteLine("광주동구 검색결과 패턴을 찾을 수 없음");
return -1;
@@ -202,6 +264,8 @@ namespace BokBonCheck
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음"; // 오류 시 HTML 일부 저장
+ Console.WriteLine($"광주동구 결과 분석 오류: {ex.Message}");
return -1;
}
}
@@ -210,5 +274,83 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 문자열에 한글이 포함되어 있는지 확인
+ ///
+ private bool ContainsKorean(string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ return false;
+
+ foreach (char c in text)
+ {
+ if (c >= 0xAC00 && c <= 0xD7A3) // 한글 유니코드 범위
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/GwangjuSeoguLibSearcher.cs b/unimarc/unimarc/SearchModel/GwangjuSeoguLibSearcher.cs
index c0ea2bc..37b673b 100644
--- a/unimarc/unimarc/SearchModel/GwangjuSeoguLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GwangjuSeoguLibSearcher.cs
@@ -337,7 +337,8 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
// 검색 결과 수 추출 (페이징 포함)
- var (resultCount, ermsg) = await ExtractBookCountWithPaging(_driver, searchTerm);
+ var (resultCount, ermsg, resultHtml) = await ExtractBookCountWithPaging(_driver, searchTerm);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -362,13 +363,15 @@ namespace BokBonCheck
return result;
}
- private async Task<(int count, string message)> ExtractBookCountWithPaging(IWebDriver driver, string searchTerm)
+ private async Task<(int count, string message, string resultHtml)> ExtractBookCountWithPaging(IWebDriver driver, string searchTerm)
{
string errmessage = string.Empty;
int totalCount = 0;
try
{
+ var htmlContent = driver.PageSource;
+ string resultHtml = string.Empty;
// 첫 번째 페이지에서 테이블 row 수 확인
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
@@ -381,7 +384,28 @@ namespace BokBonCheck
if (firstPageRows.Count == 0)
{
errmessage = "검색결과없음";
- return (0, errmessage);
+ // "검색결과가 없습니다"와 같은 메시지를 찾아 context 추출 시도
+ var noResultPatterns = new[]
+ {
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
+ {
+ resultHtml = ExtractResultContext(htmlContent, match);
+ return (0, errmessage, resultHtml);
+ }
+ }
+ }
+ resultHtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ return (0, errmessage, resultHtml);
}
totalCount += firstPageRows.Count;
@@ -390,7 +414,28 @@ namespace BokBonCheck
catch
{
errmessage = "검색결과없음";
- return (0, errmessage);
+ // "검색결과가 없습니다"와 같은 메시지를 찾아 context 추출 시도
+ var noResultPatterns = new[]
+ {
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
+ {
+ resultHtml = ExtractResultContext(htmlContent, match);
+ return (0, errmessage, resultHtml);
+ }
+ }
+ }
+ resultHtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ return (0, errmessage, resultHtml);
}
// 페이징이 있는지 확인하고 각 페이지 방문
@@ -436,18 +481,42 @@ namespace BokBonCheck
if (totalCount == 0)
{
errmessage = "검색결과없음";
- return (0, errmessage);
+ // "검색결과가 없습니다"와 같은 메시지를 찾아 context 추출 시도
+ var noResultPatterns = new[]
+ {
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다",
+ @"전체\s*0\s*건"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
+ {
+ resultHtml = ExtractResultContext(htmlContent, match);
+ return (0, errmessage, resultHtml);
+ }
+ }
+ }
+ resultHtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ return (0, errmessage, resultHtml);
}
+ resultHtml = $"검색성공 - 총 {totalCount}건";
errmessage = $"검색성공({totalCount}권)";
Console.WriteLine($"전체 검색 결과: {totalCount}건");
- return (totalCount, errmessage);
+ return (totalCount, errmessage, resultHtml);
}
catch (Exception ex)
{
errmessage = ex.Message;
- return (-1, errmessage);
+ string resultHtml = "오류 발생";
+ return (-1, errmessage, resultHtml);
}
}
@@ -492,5 +561,67 @@ namespace BokBonCheck
Console.WriteLine($"페이지 변경 감지 실패: {ex.Message}");
}
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, System.Text.RegularExpressions.Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = System.Text.RegularExpressions.Regex.Matches(searchText, tagPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = System.Text.RegularExpressions.Regex.Match(tagMatch.Value, @"<(\w+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = System.Text.RegularExpressions.Regex.Match(searchText, closeTagPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/GwangsanLibSearcher.cs b/unimarc/unimarc/SearchModel/GwangsanLibSearcher.cs
index d32cd53..baf1a66 100644
--- a/unimarc/unimarc/SearchModel/GwangsanLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GwangsanLibSearcher.cs
@@ -74,7 +74,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -84,7 +84,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -112,9 +113,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -124,6 +126,7 @@ namespace BokBonCheck
htmlContent.Contains("자료가 없습니다"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -146,8 +149,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
@@ -171,20 +177,25 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errorMessage = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -193,5 +204,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/GyeongnamLibSearcher.cs b/unimarc/unimarc/SearchModel/GyeongnamLibSearcher.cs
index 1cce63c..7a66ffa 100644
--- a/unimarc/unimarc/SearchModel/GyeongnamLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/GyeongnamLibSearcher.cs
@@ -107,8 +107,9 @@ namespace BokBonCheck
// JavaScript 렌더링 대기
await Task.Delay(3000);
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -133,71 +134,21 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
- // JavaScript 실행 후 실제 렌더링된 DOM에서 결과 추출
- var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
-
- // 1. 검색결과가 없는 경우 확인
- try
- {
- var noResultElements = driver.FindElements(By.XPath("//*[contains(text(), '검색결과가 없습니다') or contains(text(), '검색된 자료가 없습니다')]"));
- if (noResultElements.Count > 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- }
- catch
- {
- // 검색결과가 있는 경우로 진행
- }
-
- // 2. total_area에서 결과 수량 추출 (JavaScript 렌더링 후)
- try
- {
- var totalAreaElement = wait.Until(d => d.FindElement(By.CssSelector("div.total_area p.total span")));
- if (totalAreaElement != null)
- {
- var countText = totalAreaElement.Text.Trim();
- Console.WriteLine($"total_area 텍스트: '{countText}'");
-
- // "총 3건" 형태에서 숫자 추출
- var match = Regex.Match(countText, @"총\s*(\d+)\s*건", RegexOptions.IgnoreCase);
- if (match.Success && int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- Console.WriteLine("검색 결과: 0건");
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- Console.WriteLine($"검색 결과: {count}건");
- return count;
- }
- }
- }
- catch (Exception ex1)
- {
- Console.WriteLine($"total_area 요소 추출 실패: {ex1.Message}");
- }
-
- // 3. 페이지 소스에서 렌더링된 결과 추출
- var pageSource = driver.PageSource;
- Console.WriteLine("페이지 소스에서 결과 추출 시도");
-
// 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다") ||
- pageSource.Contains("자료가 없습니다") ||
- pageSource.Contains("총 0건"))
+ if (htmlContent.Contains("검색결과가 없습니다") ||
+ htmlContent.Contains("검색된 자료가 없습니다") ||
+ htmlContent.Contains("자료가 없습니다") ||
+ htmlContent.Contains("총 0건"))
{
errmessage = "검색결과없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return 0;
}
@@ -212,11 +163,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -229,16 +183,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 완전한 페이지 로딩 대기 메서드
private async Task WaitForCompletePageLoad(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/IksanLibSearcher.cs b/unimarc/unimarc/SearchModel/IksanLibSearcher.cs
index 69750ee..43521f4 100644
--- a/unimarc/unimarc/SearchModel/IksanLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/IksanLibSearcher.cs
@@ -74,7 +74,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -84,7 +84,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -110,9 +111,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
// 실제 HTML 구조에 맞는 패턴으로 수정
@@ -139,6 +141,7 @@ namespace BokBonCheck
if (pattern.Contains(@"\s*0\s*"))
{
errmessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
@@ -148,17 +151,21 @@ namespace BokBonCheck
if (count == 0)
{
errmessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errmessage = $"검색성공({count}권)";
return count;
}
}
}
- // 디버깅을 위해 HTML 내용 일부 출력
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
Console.WriteLine($"HTML 내용 일부: {htmlContent.Substring(0, Math.Min(1000, htmlContent.Length))}");
-
+
errmessage = "결과수량을찾을수없음";
return -1;
@@ -166,6 +173,7 @@ namespace BokBonCheck
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -177,5 +185,66 @@ namespace BokBonCheck
await Task.CompletedTask;
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
diff --git a/unimarc/unimarc/SearchModel/JeonbukEduLibSearcher.cs b/unimarc/unimarc/SearchModel/JeonbukEduLibSearcher.cs
index 71f5208..7136450 100644
--- a/unimarc/unimarc/SearchModel/JeonbukEduLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/JeonbukEduLibSearcher.cs
@@ -227,8 +227,9 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -253,71 +254,20 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
+
try
{
- // 1. search-info div에서 직접 추출 시도
- try
- {
- var searchInfoElement = driver.FindElement(By.CssSelector("div.search-info"));
- if (searchInfoElement != null)
- {
- var searchInfoText = searchInfoElement.Text;
-
- // "총 N건이 검색되었습니다" 패턴 찾기
- var match = Regex.Match(searchInfoText, @"총\s*(\d+)\s*건이\s*검색되었습니다", RegexOptions.IgnoreCase);
- if (match.Success)
- {
- if (int.TryParse(match.Groups[1].Value, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- return count;
- }
- }
-
- // 태그에서 직접 숫자 추출 시도
- try
- {
- var boldElements = searchInfoElement.FindElements(By.TagName("b"));
- foreach (var boldElement in boldElements)
- {
- var boldText = boldElement.Text.Trim();
- if (int.TryParse(boldText, out int boldCount))
- {
- if (boldCount == 0)
- {
- errmessage = "검색결과없음";
- return 0;
- }
- errmessage = $"검색성공({boldCount}권)";
- return boldCount;
- }
- }
- }
- catch { }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"search-info 요소 검색 중 오류: {ex.Message}");
- }
-
- // 2. 페이지 소스에서 정규식으로 추출 시도
- var pageSource = driver.PageSource;
-
// 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("0건이 검색되었습니다") ||
- pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다"))
+ if (htmlContent.Contains("0건이 검색되었습니다") ||
+ htmlContent.Contains("검색결과가 없습니다") ||
+ htmlContent.Contains("검색된 자료가 없습니다"))
{
errmessage = "검색결과없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return 0;
}
@@ -332,11 +282,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -349,16 +302,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/JunnamEduJiheaNuriSearcher.cs b/unimarc/unimarc/SearchModel/JunnamEduJiheaNuriSearcher.cs
index 22f3904..98025d3 100644
--- a/unimarc/unimarc/SearchModel/JunnamEduJiheaNuriSearcher.cs
+++ b/unimarc/unimarc/SearchModel/JunnamEduJiheaNuriSearcher.cs
@@ -260,7 +260,8 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -285,11 +286,13 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
+ var htmlContent = driver.PageSource;
// 먼저 검색결과가 없는 경우 확인
try
{
@@ -298,6 +301,7 @@ namespace BokBonCheck
if (noResultText.Contains("검색결과가 없습니다"))
{
errmessage = "검색결과없음";
+ resulthtml = noResultText;
return 0;
}
}
@@ -318,17 +322,36 @@ namespace BokBonCheck
if (int.TryParse(match.Groups[1].Value, out int vqty))
{
errmessage = $"검색성공({vqty}건)";
+ resulthtml = ExtractResultContext(htmlContent, match);
return vqty;
}
else
{
errmessage = $"수량값오류({match.Groups[1].Value})";
+ resulthtml = match.Value;
return -1;
}
}
else
{
errmessage = "수량항목없음";
+ // 매칭된 부분이 없는 경우, 기본적으로 pageInfoText 부분 추출 시도
+ try
+ {
+ var dummyMatch = System.Text.RegularExpressions.Regex.Match(pageInfoText, @"전체.*");
+ if (dummyMatch.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, dummyMatch);
+ }
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ }
+ catch
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
return -1;
}
}
@@ -336,6 +359,7 @@ namespace BokBonCheck
{
// page_info가 없는 경우 검색결과가 없는 것으로 판단
errmessage = "검색결과없음";
+ resulthtml = "검색결과 없음: " + ex.Message;
return 0;
}
@@ -343,11 +367,72 @@ namespace BokBonCheck
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "ExtractBookCount 오류: " + ex.Message;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
diff --git a/unimarc/unimarc/SearchModel/JunnamEduSearcher.cs b/unimarc/unimarc/SearchModel/JunnamEduSearcher.cs
index e440bbc..29b8bc0 100644
--- a/unimarc/unimarc/SearchModel/JunnamEduSearcher.cs
+++ b/unimarc/unimarc/SearchModel/JunnamEduSearcher.cs
@@ -272,7 +272,8 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -297,11 +298,13 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
+ var htmlContent = driver.PageSource;
// 먼저 검색결과가 없는 경우 확인
try
{
@@ -310,6 +313,7 @@ namespace BokBonCheck
if (noResultText.Contains("검색결과가 없습니다"))
{
errmessage = "검색결과없음";
+ resulthtml = noResultText;
return 0;
}
}
@@ -330,17 +334,36 @@ namespace BokBonCheck
if (int.TryParse(match.Groups[1].Value, out int vqty))
{
errmessage = $"검색성공({vqty}건)";
+ resulthtml = ExtractResultContext(htmlContent, match);
return vqty;
}
else
{
errmessage = $"수량값오류({match.Groups[1].Value})";
+ resulthtml = match.Value;
return -1;
}
}
else
{
errmessage = "수량항목없음";
+ // 매칭된 부분이 없는 경우, 기본적으로 pageInfoText 부분 추출 시도
+ try
+ {
+ var dummyMatch = System.Text.RegularExpressions.Regex.Match(pageInfoText, @"전체.*");
+ if (dummyMatch.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, dummyMatch);
+ }
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ }
+ catch
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
return -1;
}
}
@@ -348,6 +371,27 @@ namespace BokBonCheck
{
// page_info가 없는 경우 검색결과가 없는 것으로 판단
errmessage = "검색결과없음";
+ // "검색결과가 없습니다"와 같은 메시지를 찾아 context 추출 시도
+ var noResultPatterns = new[]
+ {
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, match);
+ return 0;
+ }
+ }
+ }
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
return 0;
}
@@ -355,11 +399,72 @@ namespace BokBonCheck
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "ExtractBookCount 오류: " + ex.Message;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
diff --git a/unimarc/unimarc/SearchModel/KcmLibSearcher.cs b/unimarc/unimarc/SearchModel/KcmLibSearcher.cs
index 654c050..da854fb 100644
--- a/unimarc/unimarc/SearchModel/KcmLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/KcmLibSearcher.cs
@@ -85,7 +85,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -100,7 +100,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -128,9 +129,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -141,6 +143,7 @@ namespace BokBonCheck
htmlContent.Contains("총 0 건이 검색되었습니다"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -163,8 +166,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"KCM자료검색시스템 검색 결과: {count}건");
return count;
@@ -189,15 +195,19 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
Console.WriteLine($"KCM자료검색시스템 검색 결과: {count}건");
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errorMessage = "검색결과 패턴을 찾을 수 없음";
Console.WriteLine("KCM자료검색시스템 검색결과 패턴을 찾을 수 없음");
return -1;
@@ -205,6 +215,7 @@ namespace BokBonCheck
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -213,5 +224,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/KwangjuCityEduLibrarySearcher.cs b/unimarc/unimarc/SearchModel/KwangjuCityEduLibrarySearcher.cs
index 777bb8f..72c1594 100644
--- a/unimarc/unimarc/SearchModel/KwangjuCityEduLibrarySearcher.cs
+++ b/unimarc/unimarc/SearchModel/KwangjuCityEduLibrarySearcher.cs
@@ -193,10 +193,21 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(30)));
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver);
+ var resultCount = ExtractBookCount(_driver, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
- result.BookCount = resultCount;
- result.IsSuccess = true;
+ if (resultCount == -1)
+ {
+ result.BookCount = 0;
+ result.IsSuccess = false;
+ result.ErrorMessage = errorMessage;
+ }
+ else
+ {
+ result.BookCount = resultCount;
+ result.IsSuccess = true;
+ result.ErrorMessage = errorMessage;
+ }
}
catch (Exception ex)
{
@@ -211,10 +222,14 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver)
+ private int ExtractBookCount(IWebDriver driver, out string errorMessage, out string resulthtml)
{
+ errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
+ var htmlContent = driver.PageSource;
+
// div.search-result 내부의 span에서 '전체 N' 텍스트 추출
var resultDiv = driver.FindElement(By.CssSelector("div.ndls_result"));
var span = resultDiv.FindElement(By.XPath(".//span[contains(text(),'전체')]"));
@@ -222,13 +237,106 @@ namespace BokBonCheck
var match = System.Text.RegularExpressions.Regex.Match(text, @"전체\s*(\d+)");
if (match.Success)
{
- return int.Parse(match.Groups[1].Value);
+ if (int.TryParse(match.Groups[1].Value, out int count))
+ {
+ if (count == 0)
+ {
+ errorMessage = "검색결과없음";
+ resulthtml = text;
+ return 0;
+ }
+ errorMessage = $"검색성공({count}건)";
+ resulthtml = ExtractResultContext(htmlContent, match);
+ return count;
+ }
}
- return 0;
+ errorMessage = "수량항목없음";
+ // 매칭된 부분이 없는 경우, 기본적으로 text 부분 추출 시도
+ try
+ {
+ var dummyMatch = System.Text.RegularExpressions.Regex.Match(text, @"전체.*");
+ if (dummyMatch.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, dummyMatch);
+ }
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ }
+ catch
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ return -1;
}
- catch
+ catch (Exception ex)
{
- return 0;
+ errorMessage = ex.Message;
+ resulthtml = "오류발생";
+ return -1;
+ }
+ }
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
}
}
diff --git a/unimarc/unimarc/SearchModel/MokpoLibSearcher.cs b/unimarc/unimarc/SearchModel/MokpoLibSearcher.cs
index e1b6497..adf8cce 100644
--- a/unimarc/unimarc/SearchModel/MokpoLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/MokpoLibSearcher.cs
@@ -77,7 +77,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -92,7 +92,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -120,9 +121,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -146,8 +148,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
@@ -161,6 +166,7 @@ namespace BokBonCheck
htmlContent.Contains("총 0권(개)"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -183,20 +189,25 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errorMessage = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -205,5 +216,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/MuanLibSearcher.cs b/unimarc/unimarc/SearchModel/MuanLibSearcher.cs
index 8b81f1f..099f100 100644
--- a/unimarc/unimarc/SearchModel/MuanLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/MuanLibSearcher.cs
@@ -196,9 +196,9 @@ namespace BokBonCheck
// 페이지 변경을 감지하는 메서드
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
-
- // 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var htmlContent = _driver.PageSource;
+ var resultCount = ExtractBookCount(htmlContent, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -223,71 +223,56 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
- // 검색결과 페이지 대기
- var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
-
- // 1. 검색결과가 없는 경우 확인
- try
+ // 검색 결과가 없다는 메시지 확인
+ var noResultPatterns = new[]
{
- var noResultElements = driver.FindElements(By.XPath("//*[contains(text(), '검색결과가 없습니다') or contains(text(), '검색된 자료가 없습니다')]"));
- if (noResultElements.Count > 0)
+ @"검색결과가 없습니다",
+ @"검색된 자료가 없습니다",
+ @"자료가 없습니다",
+ @"전체 0 건"
+ };
+
+ foreach (var pattern in noResultPatterns)
+ {
+ if (htmlContent.Contains(pattern))
{
errmessage = "검색결과없음";
+ // 검색결과 없음 메시지를 포함한 HTML 조각 추출
+ var index = htmlContent.IndexOf(pattern);
+ if (index >= 0)
+ {
+ var startIndex = Math.Max(0, index - 100);
+ var endIndex = Math.Min(htmlContent.Length, index + pattern.Length + 100);
+ resulthtml = htmlContent.Substring(startIndex, endIndex - startIndex);
+
+ // 상위 태그 찾기 시도
+ try
+ {
+ var match = System.Text.RegularExpressions.Regex.Match(htmlContent, pattern);
+ if (match.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, match);
+ }
+ }
+ catch
+ {
+ // 실패시 기본 추출 결과 사용
+ }
+ }
+ else
+ {
+ resulthtml = pattern;
+ }
return 0;
}
}
- catch
- {
- // 검색결과가 있는 경우로 진행
- }
-
- // 2. totalCount에서 결과 수량 추출
- try
- {
- var totalCountElement = wait.Until(d => d.FindElement(By.CssSelector("p.totalCount strong")));
- if (totalCountElement != null)
- {
- var countText = totalCountElement.Text.Trim();
- Console.WriteLine($"totalCount 텍스트: '{countText}'");
-
- if (int.TryParse(countText, out int count))
- {
- if (count == 0)
- {
- errmessage = "검색결과없음";
- Console.WriteLine("검색 결과: 0건");
- return 0;
- }
- errmessage = $"검색성공({count}권)";
- Console.WriteLine($"검색 결과: {count}건");
- return count;
- }
- }
- }
- catch (Exception ex1)
- {
- Console.WriteLine($"totalCount 요소 추출 실패: {ex1.Message}");
- }
-
- // 3. 페이지 소스에서 결과 추출
- var pageSource = driver.PageSource;
- Console.WriteLine("페이지 소스에서 결과 추출 시도");
-
- // 검색 결과가 없다는 메시지 확인
- if (pageSource.Contains("검색결과가 없습니다") ||
- pageSource.Contains("검색된 자료가 없습니다") ||
- pageSource.Contains("자료가 없습니다") ||
- pageSource.Contains("전체 0 건"))
- {
- errmessage = "검색결과없음";
- return 0;
- }
// HTML에서 다양한 패턴 찾기
var htmlPatterns = new[]
@@ -299,11 +284,14 @@ namespace BokBonCheck
foreach (var pattern in htmlPatterns)
{
- var match = Regex.Match(pageSource, pattern, RegexOptions.IgnoreCase);
+ var match = Regex.Match(htmlContent, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ // 매칭된 부분과 상위 태그 추출하여 resulthtml에 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
+
if (count == 0)
{
errmessage = "검색결과없음";
@@ -316,16 +304,80 @@ namespace BokBonCheck
}
errmessage = "결과수량을찾을수없음";
+ resulthtml = "결과수량을찾을수없음";
return -1;
}
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "ExtractBookCount 오류: " + ex.Message;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
+
// 완전한 페이지 로딩 대기 메서드
private async Task WaitForCompletePageLoad(WebDriverWait wait)
{
diff --git a/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs
index 80e3a90..abd2ec3 100644
--- a/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs
+++ b/unimarc/unimarc/SearchModel/NamguLibrarySearcher.cs
@@ -269,7 +269,8 @@ namespace BokBonCheck
await WaitForPageChange(new WebDriverWait(_driver, TimeSpan.FromSeconds(15)));
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg);
+ var resultCount = ExtractBookCount(_driver, searchTerm, out string ermsg, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
result.BookCount = 0;
@@ -294,11 +295,14 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage)
+ private int ExtractBookCount(IWebDriver driver, string searchTerm, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
+ var htmlContent = driver.PageSource;
+
// div.search-result 내부의 span에서 '전체 N' 텍스트 추출
var resultDiv = driver.FindElement(By.CssSelector("div.search-result"));
@@ -306,6 +310,7 @@ namespace BokBonCheck
if (bodytext.Contains("검색결과가 없습니다"))
{
errmessage = "검색결과없음";
+ resulthtml = bodytext;
return 0;
}
@@ -315,6 +320,7 @@ namespace BokBonCheck
if (searchTerm.Contains(searchtitle) == false)
{
errmessage = $"검색어불일치({searchtitle}/{searchTerm})";
+ resulthtml = searchtitle;
return -1;
}
var span = resultDiv.FindElement(By.XPath(".//span[contains(text(),'전체')]"));
@@ -325,10 +331,13 @@ namespace BokBonCheck
if (int.TryParse(match.Groups[1].Value, out int vqty) == false)
{
errmessage = $"수량값오류({match.Groups[1].Value})";
+ resulthtml = match.Value;
return -1;
}
else
{
+ errmessage = $"검색성공({vqty}건)";
+ resulthtml = ExtractResultContext(htmlContent, match);
searchTerm = string.Empty;
return vqty;
}
@@ -336,6 +345,23 @@ namespace BokBonCheck
else
{
errmessage = "수량항목없음";
+ // 매칭된 부분이 없는 경우, 기본적으로 text 부분 추출 시도
+ try
+ {
+ var dummyMatch = System.Text.RegularExpressions.Regex.Match(text, @"전체.*");
+ if (dummyMatch.Success)
+ {
+ resulthtml = ExtractResultContext(htmlContent, dummyMatch);
+ }
+ else
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
+ }
+ catch
+ {
+ resulthtml = htmlContent.Length > 500 ? htmlContent.Substring(0, 500) : htmlContent;
+ }
return -1;
}
@@ -343,11 +369,72 @@ namespace BokBonCheck
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "ExtractBookCount 오류: " + ex.Message;
return -1;
}
}
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
// 페이지 변경을 감지하는 메서드
public async Task WaitForPageChange(WebDriverWait wait)
diff --git a/unimarc/unimarc/SearchModel/SuncheonLibSearcher.cs b/unimarc/unimarc/SearchModel/SuncheonLibSearcher.cs
index 91d571a..2297b98 100644
--- a/unimarc/unimarc/SearchModel/SuncheonLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/SuncheonLibSearcher.cs
@@ -82,7 +82,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -97,7 +97,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -125,9 +126,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -150,8 +152,11 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
@@ -165,6 +170,7 @@ namespace BokBonCheck
htmlContent.Contains("총 0건"))
{
errorMessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -178,8 +184,10 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = resultConMatch.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, resultConMatch);
errorMessage = $"검색성공({count}권)";
return count;
}
@@ -203,20 +211,25 @@ namespace BokBonCheck
if (count == 0)
{
errorMessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
}
}
-
+
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errorMessage = "검색결과 패턴을 찾을 수 없음";
return -1;
}
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -225,5 +238,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/SearchModel/WandoLibSearcher.cs b/unimarc/unimarc/SearchModel/WandoLibSearcher.cs
index 5d79869..5d7487b 100644
--- a/unimarc/unimarc/SearchModel/WandoLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/WandoLibSearcher.cs
@@ -86,7 +86,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -96,7 +96,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -122,15 +123,17 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errmessage)
+ private int ExtractBookCount(string htmlContent, out string errmessage, out string resulthtml)
{
errmessage = string.Empty;
+ resulthtml = string.Empty;
try
{
// 검색 결과가 없다는 메시지 확인
if (htmlContent.Contains("0권(개)") || htmlContent.Contains("검색결과가 없습니다"))
{
errmessage = "검색결과없음";
+ resulthtml = "검색결과없음";
return 0;
}
@@ -153,14 +156,19 @@ namespace BokBonCheck
if (count == 0)
{
errmessage = "검색결과없음";
+ resulthtml = match.Value;
return 0;
}
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errmessage = $"검색성공({count}권)";
return count;
}
}
}
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errmessage = "결과수량을찾을수없음";
return -1;
@@ -168,6 +176,7 @@ namespace BokBonCheck
catch (Exception ex)
{
errmessage = ex.Message;
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -178,5 +187,67 @@ namespace BokBonCheck
// HTTP 방식에서는 즉시 응답이 오므로 대기 불필요
await Task.CompletedTask;
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
diff --git a/unimarc/unimarc/SearchModel/YeosuLibSearcher.cs b/unimarc/unimarc/SearchModel/YeosuLibSearcher.cs
index 956aa95..95599cc 100644
--- a/unimarc/unimarc/SearchModel/YeosuLibSearcher.cs
+++ b/unimarc/unimarc/SearchModel/YeosuLibSearcher.cs
@@ -82,7 +82,7 @@ namespace BokBonCheck
// 브라우저와 유사한 헤더 추가
request.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
request.Headers.Add("Accept-Language", "ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3");
- request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
+ //request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
request.Headers.Add("Connection", "keep-alive");
request.Headers.Add("Upgrade-Insecure-Requests", "1");
@@ -92,7 +92,8 @@ namespace BokBonCheck
var htmlContent = await response.Content.ReadAsStringAsync();
// 검색 결과 수 추출
- var resultCount = ExtractBookCount(htmlContent, out string errorMessage);
+ var resultCount = ExtractBookCount(htmlContent, out string errorMessage, out string resultHtml);
+ result.Resulthtml = resultHtml;
if (resultCount == -1)
{
@@ -120,9 +121,10 @@ namespace BokBonCheck
return result;
}
- private int ExtractBookCount(string htmlContent, out string errorMessage)
+ private int ExtractBookCount(string htmlContent, out string errorMessage, out string resulthtml)
{
errorMessage = string.Empty;
+ resulthtml = string.Empty;
try
{
@@ -134,12 +136,21 @@ namespace BokBonCheck
{
if (int.TryParse(match.Groups[1].Value, out int count))
{
+ if (count == 0)
+ {
+ errorMessage = "검색결과없음";
+ resulthtml = match.Value;
+ return 0;
+ }
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, match);
errorMessage = $"검색성공({count}권)";
return count;
}
else
{
errorMessage = $"수량값오류({match.Groups[1].Value})";
+ resulthtml = match.Value;
return -1;
}
}
@@ -153,11 +164,21 @@ namespace BokBonCheck
{
if (int.TryParse(alternateMatch.Groups[1].Value, out int count))
{
+ if (count == 0)
+ {
+ errorMessage = "검색결과없음";
+ resulthtml = alternateMatch.Value;
+ return 0;
+ }
+ // 매칭된 부분과 그 상위 태그를 찾아서 저장
+ resulthtml = ExtractResultContext(htmlContent, alternateMatch);
errorMessage = $"검색성공({count}권)";
return count;
}
}
-
+
+ // 패턴을 찾지 못한 경우
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
errorMessage = "검색결과 패턴을 찾을 수 없음";
return -1;
}
@@ -165,6 +186,7 @@ namespace BokBonCheck
catch (Exception ex)
{
errorMessage = $"결과 분석 오류: {ex.Message}";
+ resulthtml = "검색결과 패턴을 찾을 수 없음";
return -1;
}
}
@@ -173,5 +195,67 @@ namespace BokBonCheck
{
throw new NotImplementedException();
}
+
+ ///
+ /// 매칭된 결과와 그 상위 태그를 추출
+ ///
+ private string ExtractResultContext(string htmlContent, Match match)
+ {
+ try
+ {
+ var matchIndex = match.Index;
+ var matchLength = match.Length;
+
+ // 매칭된 위치 앞쪽에서 상위 태그 시작 찾기
+ var startSearchIndex = Math.Max(0, matchIndex - 200); // 매칭 위치 200자 전부터 검색
+ var searchText = htmlContent.Substring(startSearchIndex, matchIndex - startSearchIndex + matchLength + Math.Min(200, htmlContent.Length - matchIndex - matchLength));
+
+ // 상위 태그 패턴들 (div, p, h1-h6, span 등)
+ var tagPatterns = new[] { @"<(div|p|h[1-6]|span|section|article)[^>]*>", @"<[^>]+>" };
+
+ string resultContext = match.Value; // 기본값은 매칭된 부분만
+
+ foreach (var tagPattern in tagPatterns)
+ {
+ // 매칭된 부분 앞에서 가장 가까운 태그 시작 찾기
+ var tagMatches = Regex.Matches(searchText, tagPattern, RegexOptions.IgnoreCase);
+
+ for (int i = tagMatches.Count - 1; i >= 0; i--)
+ {
+ var tagMatch = tagMatches[i];
+ if (tagMatch.Index < (matchIndex - startSearchIndex))
+ {
+ // 태그 이름 추출
+ var tagName = Regex.Match(tagMatch.Value, @"<(\w+)", RegexOptions.IgnoreCase).Groups[1].Value;
+
+ // 닫는 태그 찾기
+ var closeTagPattern = $@"{tagName}[^>]*>";
+ var closeMatch = Regex.Match(searchText, closeTagPattern, RegexOptions.IgnoreCase);
+
+ if (closeMatch.Success && closeMatch.Index > (matchIndex - startSearchIndex))
+ {
+ // 상위 태그와 그 내용을 포함하여 반환
+ var startIdx = tagMatch.Index;
+ var endIdx = closeMatch.Index + closeMatch.Length;
+ resultContext = searchText.Substring(startIdx, Math.Min(endIdx - startIdx, 500)); // 최대 500자
+ return resultContext;
+ }
+ }
+ }
+ }
+
+ // 상위 태그를 찾지 못한 경우, 매칭 전후 50자씩 포함
+ var contextStart = Math.Max(0, matchIndex - 50);
+ var contextEnd = Math.Min(htmlContent.Length, matchIndex + matchLength + 50);
+ resultContext = htmlContent.Substring(contextStart, contextEnd - contextStart);
+
+ return resultContext;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"ExtractResultContext 오류: {ex.Message}");
+ return match.Value; // 오류 시 매칭된 부분만 반환
+ }
+ }
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/Skill.cs b/unimarc/unimarc/Skill.cs
index ef9f92d..373c040 100644
--- a/unimarc/unimarc/Skill.cs
+++ b/unimarc/unimarc/Skill.cs
@@ -63,7 +63,7 @@ namespace WindowsFormsApp1
else
dataGridView.Sort(dataGridView.Columns[col], System.ComponentModel.ListSortDirection.Ascending);
-
+
}
///
/// * Row헤더에 체크박스를 넣는 기능*
@@ -99,7 +99,7 @@ namespace WindowsFormsApp1
}
private void datagridview_checkBox_Click(object sender, EventArgs e)
{
- foreach(DataGridViewRow r in ((DataGridView)sender).Rows)
+ foreach (DataGridViewRow r in ((DataGridView)sender).Rows)
{
r.Cells["colCheck"].Value = ((CheckBox)sender).Checked;
}
@@ -119,16 +119,23 @@ namespace WindowsFormsApp1
char[] columnSplitter = { '\t' };
//get the text from clipboard
- IDataObject dataInClipboard = Clipboard.GetDataObject();
- string stringInClipboard = (string)dataInClipboard.GetData(DataFormats.Text);
+ if (Clipboard.ContainsText() == false) return;
+
+ string stringInClipboard = null;
+
+ if (e.Alt)
+ stringInClipboard = Clipboard.GetText(TextDataFormat.UnicodeText);
+ else
+ stringInClipboard = Clipboard.GetText();// (string)objdata;
+
//split it into lines
//20230209 \r텝 기능과 \n 줄넘김 기능을 같이 공백 제거 처리해버려 공백칸을 활용해야 함에도 제거하는 현상 발생.
//텝 공백 문자열 동시에 사용하여 분류
// stringInClipboard= stringInClipboard.Replace("\r", "");
if (stringInClipboard == null) return;
- ListrowsInClipboard = stringInClipboard.Split(rowSpliteter, StringSplitOptions.None).ToList();
- rowsInClipboard.RemoveAt(rowsInClipboard.Count-1);
+ List rowsInClipboard = stringInClipboard.Split(rowSpliteter, StringSplitOptions.None).ToList();
+ rowsInClipboard.RemoveAt(rowsInClipboard.Count - 1);
//get the row and column of selected cell in dataGridView1
int r = ((DataGridView)sender).SelectedCells[0].RowIndex;
int c = ((DataGridView)sender).SelectedCells[0].ColumnIndex;
@@ -209,7 +216,7 @@ namespace WindowsFormsApp1
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;
-
+
public void MouseMove(object sender, MouseEventArgs e)
{
DataGridView dataGridView = sender as DataGridView;
@@ -292,7 +299,8 @@ namespace WindowsFormsApp1
string[] db_data = db_res1.Split('|');
string[] db_pur = db_res2.Split('|');
- if (db_res1.Length < 3) {
+ if (db_res1.Length < 3)
+ {
MessageBox.Show("DB호출 에러!", "Error");
return "False";
}
@@ -300,20 +308,26 @@ namespace WindowsFormsApp1
string fax = string.Empty;
string emchk = string.Empty;
- if (db_pur.Length > 3) {
- for(int a= 0; a < db_pur.Length; a++)
+ if (db_pur.Length > 3)
+ {
+ for (int a = 0; a < db_pur.Length; a++)
{
- if (a % 3 == 0) { // 전화번호
- if (db_pur[a] != "") {
+ if (a % 3 == 0)
+ { // 전화번호
+ if (db_pur[a] != "")
+ {
tel = db_pur[a];
}
}
- if (a % 3 == 1) { // 팩스
- if (db_pur[a] != "") {
+ if (a % 3 == 1)
+ { // 팩스
+ if (db_pur[a] != "")
+ {
fax = db_pur[a];
}
}
- if (a % 3 == 2) { // 팩스 이메일 체크
+ if (a % 3 == 2)
+ { // 팩스 이메일 체크
emchk = db_pur[a];
}
}
@@ -401,7 +415,7 @@ namespace WindowsFormsApp1
#region 주문일자 / 보낸곳 (4행)
rng = ws.Range["A4", "C4"];
rng.MergeCells = true;
- rng.Value2 = "주문일자 : "+DateTime.Now.ToString("yyyy-MM-dd H:m:ss");
+ rng.Value2 = "주문일자 : " + DateTime.Now.ToString("yyyy-MM-dd H:m:ss");
rng.HorizontalAlignment = Excel.XlHAlign.xlHAlignLeft;
rng.Font.Bold = true;
@@ -495,7 +509,7 @@ namespace WindowsFormsApp1
#region 추신
endcount++;
- string 발송처 = "D"+endcount.ToString();
+ string 발송처 = "D" + endcount.ToString();
rng = ws.Range["A" + endcount, "C" + endcount];
rng.MergeCells = true;
@@ -551,7 +565,7 @@ namespace WindowsFormsApp1
rng2.Font.Bold = true;
////////
- rng = ws.Range[발송처, "D"+endcount];
+ rng = ws.Range[발송처, "D" + endcount];
rng.MergeCells = true;
rng.Value2 = "발 송 처";
rng.Font.Bold = true;
@@ -580,10 +594,10 @@ namespace WindowsFormsApp1
application.Interactive = true;
application.Quit();
-
+
return FileName;
}
- catch(Exception e)
+ catch (Exception e)
{
MessageBox.Show(e.ToString());
return "False";
@@ -630,9 +644,9 @@ namespace WindowsFormsApp1
private string Excel_Sub(string[] data)
{
string[] length = {
- "1", "2", "3", "4", "5",
- "6", "7", "8", "9", "10",
- "11", "12", "13", "14", "15",
+ "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", "10",
+ "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26"
};
@@ -646,8 +660,8 @@ namespace WindowsFormsApp1
string count = data.Length.ToString();
string res = string.Empty;
-
- for(int a = 0; a < length.Length; a++)
+
+ for (int a = 0; a < length.Length; a++)
{
if (length[a] == count)
{
@@ -658,7 +672,7 @@ namespace WindowsFormsApp1
}
#endregion
}
- public class Helper_Print
+ public class Helper_Print
{
///
/// 행의 갯수
@@ -788,7 +802,7 @@ namespace WindowsFormsApp1
///
/// [0] 발신번호 / [1] 수신번호
/// / [2] 수신자 회사명 / [3 ]수신자명
- public string Send_BaroFax(string file_name, string[] fax_param )
+ public string Send_BaroFax(string file_name, string[] fax_param)
{
BaroService_FAXSoapClient fAXSoapClient = new BaroService_FAXSoapClient();
@@ -824,7 +838,7 @@ namespace WindowsFormsApp1
BaroService_FAXSoapClient fAXSoapClient = new BaroService_FAXSoapClient();
// 수신자회사명, 수신번호, 전송일시, 전송결과, 전송페이지수, 성공페이지수, 전송파일명
- string[] MsgBox_Array = {
+ string[] MsgBox_Array = {
fAXSoapClient.GetFaxMessage(CERTKEY, CorpNum, sendkey).ReceiveCorp,
fAXSoapClient.GetFaxMessage(CERTKEY, CorpNum, sendkey).ReceiverNum,
fAXSoapClient.GetFaxMessage(CERTKEY, CorpNum, sendkey).SendDT,
@@ -1190,9 +1204,9 @@ namespace WindowsFormsApp1
public bool IsConnected { get; set; }
private string ipAddr = string.Empty;
- private string Port = string.Empty;
+ private string Port = string.Empty;
private string userId = string.Empty;
- private string Pwd = string.Empty;
+ private string Pwd = string.Empty;
public FTP() { }
@@ -1219,7 +1233,7 @@ namespace WindowsFormsApp1
using (ftpRequest.GetResponse()) { }
this.IsConnected = true;
}
- catch(Exception ex)
+ catch (Exception ex)
{
this.LastException = ex;
System.Reflection.MemberInfo info = System.Reflection.MethodInfo.GetCurrentMethod();
@@ -1288,7 +1302,7 @@ namespace WindowsFormsApp1
buff = null;
}
}
- catch(Exception ex)
+ catch (Exception ex)
{
MessageBox.Show(ex.ToString());
this.LastException = ex;
@@ -1392,14 +1406,14 @@ namespace WindowsFormsApp1
if (reader != null) reader.Close();
- foreach(string file in result.ToString().Split('\n'))
+ foreach (string file in result.ToString().Split('\n'))
{
resultList.Add(file);
}
}
return resultList;
}
- catch(Exception ex)
+ catch (Exception ex)
{
this.LastException = ex;
@@ -1420,12 +1434,12 @@ namespace WindowsFormsApp1
try
{
- foreach(string tmpFolder in arrDir)
+ foreach (string tmpFolder in arrDir)
{
try
{
if (tmpFolder == string.Empty) continue;
-
+
currentDir += @"/" + tmpFolder;
string url = string.Format(@"FTP://{0}:{1}/{2}", this.ipAddr, this.Port, currentDir);
@@ -1453,9 +1467,11 @@ namespace WindowsFormsApp1
private void checkDir(string localFullPathFile)
{
FileInfo finfo = new FileInfo(localFullPathFile);
- if (!finfo.Exists) {
+ if (!finfo.Exists)
+ {
DirectoryInfo dInfo = new DirectoryInfo(finfo.DirectoryName);
- if (!dInfo.Exists) {
+ if (!dInfo.Exists)
+ {
dInfo.Create();
}
}
@@ -1552,30 +1568,35 @@ namespace WindowsFormsApp1
int tDown = 0;
for (int a = 0; a < array_text.Count; a++)
{
- // if (array_text[a] == "") continue;
+ // if (array_text[a] == "") continue;
num.Add(array_text[a].Substring(0, 3));
- if (array_text[a][5] == '▼') {
+ if (array_text[a][5] == '▼')
+ {
array_text[a] = array_text[a].Remove(0, 3);
}
- else {
+ else
+ {
array_text[a] = array_text[a].Remove(0, 5);
}
가변길이 += array_text[a] + "\n";
int textLength = 0;
- if (EncodingType == "UTF-8") {
+ if (EncodingType == "UTF-8")
+ {
textLength = Encoding.UTF8.GetBytes(array_text[a]).Length
- WordCheck(array_text[a], "▲")
- WordCheck(array_text[a], "▼");
}
- else if (EncodingType == "UniCode") {
+ else if (EncodingType == "UniCode")
+ {
textLength = Encoding.Unicode.GetBytes(array_text[a]).Length
- WordCheck(array_text[a], "▲")
- WordCheck(array_text[a], "▼");
}
- else { // ANSI
+ else
+ { // ANSI
textLength = Encoding.Default.GetBytes(array_text[a]).Length
- WordCheck(array_text[a], "▲")
- WordCheck(array_text[a], "▼");
@@ -1587,12 +1608,13 @@ namespace WindowsFormsApp1
for (int a = 0; a < array_text.Count; a++)
{
- if (a == 0) { //total.Add("0");
+ if (a == 0)
+ { //total.Add("0");
tTotal.Add(0);
}
else
{
- // total.Add(total[a - 1] + count[a - 1]);
+ // total.Add(total[a - 1] + count[a - 1]);
tTotal.Add(tTotal[a - 1] + tCount[a - 1]);
}
//else if (a == 1)
@@ -1609,7 +1631,7 @@ namespace WindowsFormsApp1
// else c = Convert.ToInt32(Encoding.Default.GetBytes(array_text[a - 2]).Length.ToString()) - WordCheck(array_text[a - 2], "▲") - WordCheck(array_text[a - 2], "▼");
// int res = b + c;
// total.Add(res.ToString());
-
+
}
string[] str_num = num.ToArray();
@@ -1626,7 +1648,7 @@ namespace WindowsFormsApp1
// else if (total[a].Length == 2) { total[a] = total[a].Insert(0, "000"); }
// else if (total[a].Length == 1) { total[a] = total[a].Insert(0, "0000"); }
// 디렉토리 += str_num[a] + count[a] + total[a] + "\n";
- 디렉토리 += str_num[a] + tCount[a].ToString().PadLeft(4, '0') + tTotal[a].ToString().PadLeft(5, '0');
+ 디렉토리 += str_num[a] + tCount[a].ToString().PadLeft(4, '0') + tTotal[a].ToString().PadLeft(5, '0');
}
string[] 리더부 = { "00000","n", "a", "m", " ",
@@ -1642,11 +1664,11 @@ namespace WindowsFormsApp1
string dp = 가변길이 + 디렉토리;
int recode = 0;
- if (EncodingType == "UTF-8") recode = Encoding.UTF8.GetBytes(dp).Length- WordCheck(dp, "▲") - WordCheck(dp, "▼") - WordCheck(dp, "↔");
+ if (EncodingType == "UTF-8") recode = Encoding.UTF8.GetBytes(dp).Length - WordCheck(dp, "▲") - WordCheck(dp, "▼") - WordCheck(dp, "↔");
else if (EncodingType == "UniCode") recode = Encoding.Unicode.GetBytes(dp).Length - WordCheck(dp, "▲") - WordCheck(dp, "▼") - WordCheck(dp, "↔");
- else recode = Encoding.Default.GetBytes(dp).Length- WordCheck(dp, "▲") - WordCheck(dp, "▼") - WordCheck(dp, "↔");
-
-
+ else recode = Encoding.Default.GetBytes(dp).Length - WordCheck(dp, "▲") - WordCheck(dp, "▼") - WordCheck(dp, "↔");
+
+
리더부[0] = insert_Zero(recode + 24, 5);
int data_addr = 24 + Encoding.Default.GetBytes(디렉토리).Length - WordCheck(디렉토리, "▲");
@@ -1693,7 +1715,7 @@ namespace WindowsFormsApp1
return result;
}
#endregion
-
+
///
/// 추가하고 싶은 태그를 뷰형태의 마크에 추가하는 함수.
@@ -1706,7 +1728,7 @@ namespace WindowsFormsApp1
if (Tag.Length < 3) return "";
int TargetTagNum = Convert.ToInt32(Tag.Substring(0, 3));
-
+
string[] SplitView = TypeView.Split('\n');
List View = new List(SplitView);
@@ -1731,9 +1753,9 @@ namespace WindowsFormsApp1
/// 추가할 태그 (태그명\t지시기호\t태그내용)
/// 뷰형태의 마크
///
- public string AddTagInMarc(int pTargetTagNum,string pAddTag, string pTargetData)//TagTarget Num 을 찾아서 있을경우는 해당 Tag 데이터를 전송, 없을경우는 신규로 해야함.
+ public string AddTagInMarc(int pTargetTagNum, string pAddTag, string pTargetData)//TagTarget Num 을 찾아서 있을경우는 해당 Tag 데이터를 전송, 없을경우는 신규로 해야함.
{
-
+
if (pAddTag.Length < 3) return "";
string tRet = pTargetData;
// ex ) 020 : ~~~ 에 XXXX 내용줄 뒤에 추가
@@ -1827,7 +1849,7 @@ namespace WindowsFormsApp1
}
}
}
- }
+ }
else
{// 기존 태그 변경
int endIdx = SplitView[a].IndexOf("▼", startIdx + 1);
@@ -1906,7 +1928,7 @@ namespace WindowsFormsApp1
/// 마크 데이터
/// 추출할 함수(배열)
///
- public string[] Take_Tag(string marc, string[] search,bool pSearchTag = false)
+ public string[] Take_Tag(string marc, string[] search, bool pSearchTag = false)
{
string[] ary = marc.Split('');
string[] tag = res_dir(ary[0].Substring(24));
@@ -1958,7 +1980,7 @@ namespace WindowsFormsApp1
//memo = result[b];
start += 2;
int end = -1;
- if (tmp.Length > 1) end=tmp.IndexOf("", start);
+ if (tmp.Length > 1) end = tmp.IndexOf("", start);
if (memo == result[b])
break;
@@ -2188,7 +2210,8 @@ namespace WindowsFormsApp1
/// EventArgs
public void Int_Comma(object sender, EventArgs e)
{
- if (((TextBox)sender).Text != "") {
+ if (((TextBox)sender).Text != "")
+ {
string text;
text = ((TextBox)sender).Text.Replace(",", "");
((TextBox)sender).Text = String.Format("{0:#,###}", Convert.ToInt32(text));
@@ -2204,7 +2227,7 @@ namespace WindowsFormsApp1
public bool isContainHangul(string value)
{
char[] charArr = value.ToCharArray();
- foreach(char c in charArr)
+ foreach (char c in charArr)
{
if (char.GetUnicodeCategory(c) == System.Globalization.UnicodeCategory.OtherLetter)
return true;
@@ -2221,7 +2244,7 @@ namespace WindowsFormsApp1
public bool CheckString(string value, string chkString)
{
int index = value.IndexOf(chkString);
- if (index < 0)
+ if (index < 0)
return false;
return true;
@@ -2264,10 +2287,10 @@ namespace WindowsFormsApp1
public class API
{
- public string CheckString(string pText,string pStr)
+ public string CheckString(string pText, string pStr)
{
string tRet = pText;
- Regex reg = new Regex(@"([\"+pStr+"]+)" + @"[가-힣]+");//+ @"([\>]+)");//new Regex(@"([\<]+)"+ @"[ㄱ-ㅎ가-힣]+"+@"([\>]+)");
+ Regex reg = new Regex(@"([\" + pStr + "]+)" + @"[가-힣]+");//+ @"([\>]+)");//new Regex(@"([\<]+)"+ @"[ㄱ-ㅎ가-힣]+"+@"([\>]+)");
MatchCollection tMatch = reg.Matches(tRet);
for (int i = 0; i < tMatch.Count; i++)
{
@@ -2326,8 +2349,9 @@ namespace WindowsFormsApp1
xml = CheckString(xml, "〈");
doc.LoadXml(xml);
}
- catch (Exception ex){
- return "";
+ catch (Exception ex)
+ {
+ return "";
}
var json = JsonConvert.SerializeXmlNode(doc);
@@ -2520,19 +2544,23 @@ namespace WindowsFormsApp1
{
if (length == 1)
{
- try {
+ try
+ {
tmp_data.Add(docs[Param[b]]["#text"]);
}
- catch (KeyNotFoundException e) {
+ catch (KeyNotFoundException e)
+ {
tmp_data.Add("");
}
}
else
{
- try {
+ try
+ {
tmp_data.Add(docs[a][Param[b]]["#text"]);
}
- catch (KeyNotFoundException e) {
+ catch (KeyNotFoundException e)
+ {
tmp_data.Add("");
}
}
@@ -2649,8 +2677,8 @@ namespace WindowsFormsApp1
return dialogResult;
}
}
- public class PrintLine
- {
+ public class PrintLine
+ {
string num { get; set; }
string count { get; set; }
string list_name { get; set; }
@@ -2963,7 +2991,7 @@ namespace WindowsFormsApp1
{
string version = "0";
var fn = Application.StartupPath + "\\update.inf";
- if(System.IO.File.Exists(fn))
+ if (System.IO.File.Exists(fn))
{
StreamReader sr = new StreamReader(fn);
while (!sr.EndOfStream)
@@ -2976,7 +3004,7 @@ namespace WindowsFormsApp1
}
}
}
-
+
return version;
}
}
diff --git a/unimarc/unimarc/UniMarc.csproj b/unimarc/unimarc/UniMarc.csproj
index 7185567..727ccc0 100644
--- a/unimarc/unimarc/UniMarc.csproj
+++ b/unimarc/unimarc/UniMarc.csproj
@@ -224,6 +224,7 @@
True
Reference.svcmap
+
diff --git a/unimarc/unimarc/마크/Check_copyWD.Designer.cs b/unimarc/unimarc/마크/Check_copyWD.Designer.cs
index bcc1403..9abb84f 100644
--- a/unimarc/unimarc/마크/Check_copyWD.Designer.cs
+++ b/unimarc/unimarc/마크/Check_copyWD.Designer.cs
@@ -28,7 +28,8 @@
///
private void InitializeComponent()
{
- System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
this.panel1 = new System.Windows.Forms.Panel();
this.chkShowBrowser = new System.Windows.Forms.CheckBox();
this.chkRetryErrData = new System.Windows.Forms.CheckBox();
@@ -50,10 +51,9 @@
this.lbl_PW = new System.Windows.Forms.Label();
this.lbl_ID = new System.Windows.Forms.Label();
this.dv1 = new System.Windows.Forms.DataGridView();
- this.book_name = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.book_comp = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.Count = new System.Windows.Forms.DataGridViewTextBoxColumn();
- this.dvc_remark = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.일반문자로붙여넣기ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.btn_ApplyFilter = new System.Windows.Forms.Button();
this.panel3 = new System.Windows.Forms.Panel();
this.panel6 = new System.Windows.Forms.Panel();
@@ -66,19 +66,30 @@
this.btn_GridReset = new System.Windows.Forms.Button();
this.btn_OpenMemo = new System.Windows.Forms.Button();
this.chk_spChar = new System.Windows.Forms.CheckBox();
+ this.book_name = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.book_comp = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Count = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dvc_remark = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.dvc_resulthtml = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.nudAddDelay = new System.Windows.Forms.NumericUpDown();
+ this.label1 = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.groupBox1.SuspendLayout();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dv1)).BeginInit();
+ this.contextMenuStrip1.SuspendLayout();
this.panel3.SuspendLayout();
this.panel6.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.panel4.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudAddDelay)).BeginInit();
this.SuspendLayout();
//
// panel1
//
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.panel1.Controls.Add(this.label1);
+ this.panel1.Controls.Add(this.nudAddDelay);
this.panel1.Controls.Add(this.chkShowBrowser);
this.panel1.Controls.Add(this.chkRetryErrData);
this.panel1.Controls.Add(this.groupBox1);
@@ -90,7 +101,7 @@
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
this.panel1.Location = new System.Drawing.Point(0, 34);
this.panel1.Name = "panel1";
- this.panel1.Size = new System.Drawing.Size(637, 106);
+ this.panel1.Size = new System.Drawing.Size(719, 106);
this.panel1.TabIndex = 0;
//
// chkShowBrowser
@@ -98,7 +109,7 @@
this.chkShowBrowser.AutoSize = true;
this.chkShowBrowser.Checked = true;
this.chkShowBrowser.CheckState = System.Windows.Forms.CheckState.Checked;
- this.chkShowBrowser.Location = new System.Drawing.Point(515, 81);
+ this.chkShowBrowser.Location = new System.Drawing.Point(618, 50);
this.chkShowBrowser.Name = "chkShowBrowser";
this.chkShowBrowser.Size = new System.Drawing.Size(96, 16);
this.chkShowBrowser.TabIndex = 8;
@@ -125,7 +136,7 @@
this.groupBox1.Controls.Add(this.radTargetAll);
this.groupBox1.Location = new System.Drawing.Point(318, 34);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(304, 39);
+ this.groupBox1.Size = new System.Drawing.Size(294, 39);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "검색대상";
@@ -133,7 +144,7 @@
// radTargetErr
//
this.radTargetErr.AutoSize = true;
- this.radTargetErr.Location = new System.Drawing.Point(197, 16);
+ this.radTargetErr.Location = new System.Drawing.Point(239, 16);
this.radTargetErr.Name = "radTargetErr";
this.radTargetErr.Size = new System.Drawing.Size(47, 16);
this.radTargetErr.TabIndex = 9;
@@ -143,7 +154,7 @@
// radTargetEmpty
//
this.radTargetEmpty.AutoSize = true;
- this.radTargetEmpty.Location = new System.Drawing.Point(144, 16);
+ this.radTargetEmpty.Location = new System.Drawing.Point(172, 16);
this.radTargetEmpty.Name = "radTargetEmpty";
this.radTargetEmpty.Size = new System.Drawing.Size(47, 16);
this.radTargetEmpty.TabIndex = 8;
@@ -153,7 +164,7 @@
// radTargetErrEmpty
//
this.radTargetErrEmpty.AutoSize = true;
- this.radTargetErrEmpty.Location = new System.Drawing.Point(61, 17);
+ this.radTargetErrEmpty.Location = new System.Drawing.Point(75, 16);
this.radTargetErrEmpty.Name = "radTargetErrEmpty";
this.radTargetErrEmpty.Size = new System.Drawing.Size(77, 16);
this.radTargetErrEmpty.TabIndex = 7;
@@ -209,7 +220,7 @@
//
this.btn_Start.Location = new System.Drawing.Point(470, 4);
this.btn_Start.Name = "btn_Start";
- this.btn_Start.Size = new System.Drawing.Size(75, 24);
+ this.btn_Start.Size = new System.Drawing.Size(153, 24);
this.btn_Start.TabIndex = 2;
this.btn_Start.Text = "검색시작";
this.btn_Start.UseVisualStyleBackColor = true;
@@ -217,7 +228,7 @@
//
// btn_Stop
//
- this.btn_Stop.Location = new System.Drawing.Point(548, 4);
+ this.btn_Stop.Location = new System.Drawing.Point(631, 4);
this.btn_Stop.Name = "btn_Stop";
this.btn_Stop.Size = new System.Drawing.Size(75, 24);
this.btn_Stop.TabIndex = 2;
@@ -227,7 +238,7 @@
//
// btn_Close
//
- this.btn_Close.Location = new System.Drawing.Point(548, 4);
+ this.btn_Close.Location = new System.Drawing.Point(631, 4);
this.btn_Close.Name = "btn_Close";
this.btn_Close.Size = new System.Drawing.Size(75, 24);
this.btn_Close.TabIndex = 2;
@@ -270,14 +281,14 @@
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(637, 34);
+ this.panel2.Size = new System.Drawing.Size(719, 34);
this.panel2.TabIndex = 0;
//
// btn_SiteDenote
//
- this.btn_SiteDenote.Location = new System.Drawing.Point(462, 5);
+ this.btn_SiteDenote.Location = new System.Drawing.Point(470, 5);
this.btn_SiteDenote.Name = "btn_SiteDenote";
- this.btn_SiteDenote.Size = new System.Drawing.Size(77, 23);
+ this.btn_SiteDenote.Size = new System.Drawing.Size(155, 23);
this.btn_SiteDenote.TabIndex = 4;
this.btn_SiteDenote.Text = "사이트 표출";
this.btn_SiteDenote.UseVisualStyleBackColor = true;
@@ -307,55 +318,52 @@
this.dv1.BackgroundColor = System.Drawing.SystemColors.Control;
this.dv1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.dv1.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.dv1.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.dv1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
this.dv1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dv1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.book_name,
this.book_comp,
this.Count,
- this.dvc_remark});
+ this.dvc_remark,
+ this.dvc_resulthtml});
+ this.dv1.ContextMenuStrip = this.contextMenuStrip1;
this.dv1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dv1.Location = new System.Drawing.Point(0, 0);
this.dv1.Name = "dv1";
this.dv1.RowTemplate.Height = 23;
- this.dv1.Size = new System.Drawing.Size(637, 542);
+ this.dv1.Size = new System.Drawing.Size(719, 542);
this.dv1.TabIndex = 1;
this.dv1.RowPostPaint += new System.Windows.Forms.DataGridViewRowPostPaintEventHandler(this.dataGridView1_RowPostPaint);
this.dv1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.dataGridView1_KeyDown);
//
- // book_name
+ // contextMenuStrip1
//
- this.book_name.HeaderText = "도서명(총서명)";
- this.book_name.Name = "book_name";
- this.book_name.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
- this.book_name.Width = 300;
+ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem,
+ this.일반문자로붙여넣기ToolStripMenuItem});
+ this.contextMenuStrip1.Name = "contextMenuStrip1";
+ this.contextMenuStrip1.Size = new System.Drawing.Size(215, 48);
//
- // book_comp
+ // 유니코드문자로붙여넝ㅎ기ToolStripMenuItem
//
- this.book_comp.HeaderText = "출판사";
- this.book_comp.Name = "book_comp";
- this.book_comp.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
- this.book_comp.Width = 120;
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem.Name = "유니코드문자로붙여넝ㅎ기ToolStripMenuItem";
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem.Size = new System.Drawing.Size(214, 22);
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem.Text = "유니코드 문자로 붙여넣기";
+ this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem.Click += new System.EventHandler(this.유니코드문자로붙여넝ㅎ기ToolStripMenuItem_Click);
//
- // Count
+ // 일반문자로붙여넣기ToolStripMenuItem
//
- this.Count.HeaderText = "검색 수";
- this.Count.Name = "Count";
- this.Count.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
- this.Count.Width = 50;
- //
- // dvc_remark
- //
- this.dvc_remark.HeaderText = "비고";
- this.dvc_remark.Name = "dvc_remark";
- this.dvc_remark.Width = 110;
+ this.일반문자로붙여넣기ToolStripMenuItem.Name = "일반문자로붙여넣기ToolStripMenuItem";
+ this.일반문자로붙여넣기ToolStripMenuItem.Size = new System.Drawing.Size(214, 22);
+ this.일반문자로붙여넣기ToolStripMenuItem.Text = "일반 문자로 붙여넣기";
+ this.일반문자로붙여넣기ToolStripMenuItem.Click += new System.EventHandler(this.일반문자로붙여넣기ToolStripMenuItem_Click);
//
// btn_ApplyFilter
//
@@ -376,7 +384,7 @@
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(0, 0);
this.panel3.Name = "panel3";
- this.panel3.Size = new System.Drawing.Size(637, 738);
+ this.panel3.Size = new System.Drawing.Size(719, 738);
this.panel3.TabIndex = 3;
//
// panel6
@@ -386,7 +394,7 @@
this.panel6.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel6.Location = new System.Drawing.Point(0, 174);
this.panel6.Name = "panel6";
- this.panel6.Size = new System.Drawing.Size(637, 564);
+ this.panel6.Size = new System.Drawing.Size(719, 564);
this.panel6.TabIndex = 3;
//
// statusStrip1
@@ -396,7 +404,7 @@
this.lbSite});
this.statusStrip1.Location = new System.Drawing.Point(0, 542);
this.statusStrip1.Name = "statusStrip1";
- this.statusStrip1.Size = new System.Drawing.Size(637, 22);
+ this.statusStrip1.Size = new System.Drawing.Size(719, 22);
this.statusStrip1.TabIndex = 2;
this.statusStrip1.Text = "statusStrip1";
//
@@ -424,7 +432,7 @@
this.panel4.Dock = System.Windows.Forms.DockStyle.Top;
this.panel4.Location = new System.Drawing.Point(0, 140);
this.panel4.Name = "panel4";
- this.panel4.Size = new System.Drawing.Size(637, 34);
+ this.panel4.Size = new System.Drawing.Size(719, 34);
this.panel4.TabIndex = 2;
//
// chk_RemoveBrit
@@ -477,11 +485,60 @@
this.chk_spChar.Text = "특수문자 제거";
this.chk_spChar.UseVisualStyleBackColor = true;
//
+ // book_name
+ //
+ this.book_name.HeaderText = "도서명(총서명)";
+ this.book_name.Name = "book_name";
+ this.book_name.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.book_name.Width = 300;
+ //
+ // book_comp
+ //
+ this.book_comp.HeaderText = "출판사";
+ this.book_comp.Name = "book_comp";
+ this.book_comp.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.book_comp.Width = 120;
+ //
+ // Count
+ //
+ this.Count.HeaderText = "검색 수";
+ this.Count.Name = "Count";
+ this.Count.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.Count.Width = 50;
+ //
+ // dvc_remark
+ //
+ this.dvc_remark.HeaderText = "비고";
+ this.dvc_remark.Name = "dvc_remark";
+ this.dvc_remark.Width = 110;
+ //
+ // dvc_resulthtml
+ //
+ this.dvc_resulthtml.HeaderText = "결과";
+ this.dvc_resulthtml.Name = "dvc_resulthtml";
+ //
+ // nudAddDelay
+ //
+ this.nudAddDelay.Location = new System.Drawing.Point(618, 79);
+ this.nudAddDelay.Name = "nudAddDelay";
+ this.nudAddDelay.Size = new System.Drawing.Size(56, 21);
+ this.nudAddDelay.TabIndex = 9;
+ this.nudAddDelay.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(559, 83);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(53, 12);
+ this.label1.TabIndex = 10;
+ this.label1.Text = "추가지연";
+ //
// Check_copyWD
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(637, 738);
+ this.ClientSize = new System.Drawing.Size(719, 738);
this.Controls.Add(this.panel3);
this.Name = "Check_copyWD";
this.Text = "복본조사(New)";
@@ -494,6 +551,7 @@
this.panel2.ResumeLayout(false);
this.panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dv1)).EndInit();
+ this.contextMenuStrip1.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.panel6.ResumeLayout(false);
this.panel6.PerformLayout();
@@ -501,6 +559,7 @@
this.statusStrip1.PerformLayout();
this.panel4.ResumeLayout(false);
this.panel4.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.nudAddDelay)).EndInit();
this.ResumeLayout(false);
}
@@ -536,13 +595,19 @@
private System.Windows.Forms.RadioButton radTargetErr;
private System.Windows.Forms.RadioButton radTargetEmpty;
private System.Windows.Forms.RadioButton radTargetErrEmpty;
- private System.Windows.Forms.DataGridViewTextBoxColumn book_name;
- private System.Windows.Forms.DataGridViewTextBoxColumn book_comp;
- private System.Windows.Forms.DataGridViewTextBoxColumn Count;
- private System.Windows.Forms.DataGridViewTextBoxColumn dvc_remark;
public System.Windows.Forms.CheckBox chkRetryErrData;
public System.Windows.Forms.GroupBox groupBox1;
public System.Windows.Forms.CheckBox chkShowBrowser;
private System.Windows.Forms.ToolStripStatusLabel lbSite;
+ private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem 유니코드문자로붙여넝ㅎ기ToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem 일반문자로붙여넣기ToolStripMenuItem;
+ private System.Windows.Forms.DataGridViewTextBoxColumn book_name;
+ private System.Windows.Forms.DataGridViewTextBoxColumn book_comp;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Count;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dvc_remark;
+ private System.Windows.Forms.DataGridViewTextBoxColumn dvc_resulthtml;
+ private System.Windows.Forms.NumericUpDown nudAddDelay;
+ private System.Windows.Forms.Label label1;
}
}
\ No newline at end of file
diff --git a/unimarc/unimarc/마크/Check_copyWD.cs b/unimarc/unimarc/마크/Check_copyWD.cs
index b409359..00422f6 100644
--- a/unimarc/unimarc/마크/Check_copyWD.cs
+++ b/unimarc/unimarc/마크/Check_copyWD.cs
@@ -12,6 +12,7 @@ using UniMarc.SearchModel;
using System.Linq;
using UniMarc;
using System.Globalization;
+using System.Threading.Tasks;
namespace WindowsFormsApp1.Mac
{
@@ -39,6 +40,9 @@ namespace WindowsFormsApp1.Mac
main = _main;
db.DBcon();
+ // 도서관별 지연시간 설정 초기화
+ _delaySettings = new Helper_LibraryDelaySettings();
+
var idx = 1;
//도서검색(크롤링)
_searchService = new BookSearchService();
@@ -450,6 +454,7 @@ namespace WindowsFormsApp1.Mac
private readonly BookSearchService _searchService;
private bool _isSearching = false;
+ private readonly Helper_LibraryDelaySettings _delaySettings;
private async void InitializeChromeDriver()
{
@@ -612,7 +617,10 @@ namespace WindowsFormsApp1.Mac
int cnt_ok = 0;
int cnt_ng = 0;
int cnt_er = 0;
+ int addDelay = (int)nudAddDelay.Value * 1000; //추가 지연시간 : 1개의 레코드 처리 후 추가 지연한다.
+ // 현재 지연시간을 도서관별로 저장
+ SaveLibraryDelaySettings(searcher.SiteName, (int)nudAddDelay.Value);
RetrySearch:
foreach (DataGridViewRow drow in this.dv1.Rows)
@@ -620,6 +628,10 @@ namespace WindowsFormsApp1.Mac
if (this._isSearching == false)
{
drow.Cells["dvc_remark"].Value = "Cancel";
+ if (dv1.Columns.Contains("dvc_resulthtml"))
+ {
+ drow.Cells["dvc_resulthtml"].Value = "";
+ }
break;
}
@@ -630,6 +642,10 @@ namespace WindowsFormsApp1.Mac
{
cnt_skip += 1;
drow.Cells["dvc_remark"].Value = "No Title";
+ if (dv1.Columns.Contains("dvc_resulthtml"))
+ {
+ drow.Cells["dvc_resulthtml"].Value = "";
+ }
drow.DefaultCellStyle.BackColor = Color.HotPink;
drow.DefaultCellStyle.ForeColor = Color.Blue;
continue;
@@ -660,6 +676,13 @@ namespace WindowsFormsApp1.Mac
{
drow.Cells["dvc_remark"].Value = rlt.ErrorMessage;
drow.Cells["Count"].Value = $"{rlt.BookCount}";
+
+ // ResultHtml을 dvc_resulthtml 컬럼에 저장
+ if (dv1.Columns.Contains("dvc_resulthtml"))
+ {
+ drow.Cells["dvc_resulthtml"].Value = rlt.Resulthtml ?? "";
+ }
+
if (rlt.BookCount == 0)
{
cnt_ng += 1;
@@ -677,9 +700,18 @@ namespace WindowsFormsApp1.Mac
{
cnt_er += 1;
drow.Cells["dvc_remark"].Value = $"Error|{rlt.ErrorMessage}";
+
+ // 오류시에도 ResultHtml이 있으면 저장 (디버깅용)
+ if (dv1.Columns.Contains("dvc_resulthtml"))
+ {
+ drow.Cells["dvc_resulthtml"].Value = rlt.Resulthtml ?? "";
+ }
+
drow.DefaultCellStyle.BackColor = Color.HotPink;
drow.DefaultCellStyle.ForeColor = Color.Blue;
}
+ if(addDelay > 0)
+ await Task.Delay(addDelay);
}
if (_isSearching == true && retry == false && chkRetryErrData.Checked)
@@ -861,6 +893,12 @@ namespace WindowsFormsApp1.Mac
dv1.Rows[a].DefaultCellStyle.BackColor = Color.White;
dv1.Rows[a].Cells["Count"].Value = "";
dv1.Rows[a].Cells["dvc_remark"].Value = "";
+
+ // dvc_resulthtml 컬럼도 초기화
+ if (dv1.Columns.Contains("dvc_resulthtml"))
+ {
+ dv1.Rows[a].Cells["dvc_resulthtml"].Value = "";
+ }
}
}
@@ -912,6 +950,67 @@ namespace WindowsFormsApp1.Mac
}
chkShowBrowser.Enabled = !searcher.HttpApiMode;
this.lbSite.Text = $"[{searcher.AreaCode}] {searcher.SiteUrl}";
+
+ // 저장된 지연시간 불러오기
+ LoadLibraryDelaySettings(searcher.SiteName);
+ }
+
+ ///
+ /// 선택된 도서관의 저장된 지연시간을 불러와서 UI에 설정
+ ///
+ /// 도서관 이름
+ private void LoadLibraryDelaySettings(string libraryName)
+ {
+ try
+ {
+ var savedDelay = _delaySettings.GetDelay(libraryName);
+ if (savedDelay > 0)
+ {
+ nudAddDelay.Value = savedDelay;
+ Console.WriteLine($"도서관 지연시간 불러옴: {libraryName} = {savedDelay}초");
+ }
+ else
+ {
+ // 저장된 설정이 없으면 기본값 유지
+ Console.WriteLine($"도서관 지연시간 설정 없음, 기본값 사용: {libraryName}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"도서관 지연시간 불러오기 오류: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 검색 시작시 현재 지연시간을 저장
+ ///
+ /// 도서관 이름
+ /// 지연시간(초)
+ private void SaveLibraryDelaySettings(string libraryName, int delaySeconds)
+ {
+ try
+ {
+ _delaySettings.SetDelay(libraryName, delaySeconds);
+ Console.WriteLine($"도서관 지연시간 저장됨: {libraryName} = {delaySeconds}초");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"도서관 지연시간 저장 오류: {ex.Message}");
+ }
+ }
+
+ private void 유니코드문자로붙여넝ㅎ기ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Skill_Grid sg = new Skill_Grid();
+ var newkey = new KeyEventArgs(Keys.Control | Keys.V | Keys.Alt );
+ sg.Excel_to_DataGridView(this.dv1, newkey);
+ }
+
+ private void 일반문자로붙여넣기ToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Skill_Grid sg = new Skill_Grid();
+ var newkey = new KeyEventArgs(Keys.Control | Keys.V);
+ sg.Excel_to_DataGridView(this.dv1, newkey);
}
}
}
diff --git a/unimarc/unimarc/마크/Check_copyWD.resx b/unimarc/unimarc/마크/Check_copyWD.resx
index 9fc1aef..59145b0 100644
--- a/unimarc/unimarc/마크/Check_copyWD.resx
+++ b/unimarc/unimarc/마크/Check_copyWD.resx
@@ -129,8 +129,11 @@
True
-
- 17, 17
+
+ True
+
+
+ 134, 17
17, 17