feat: 도서관 검색 시스템 대폭 확장 및 크롤링 가이드 추가
- 새로운 도서관 검색기 15개 추가 (HTTP/Selenium 방식) * HTTP 방식: 순천시립, 목포시립, 광산구, 여수시립 * Selenium 방식: 광주시립, 고흥군립, 북구통합, 전북교육청, 안산시립 등 - 도서관 검색기 작성 가이드를 CLAUDE.md에 추가 - ILibrarySearcher 인터페이스에 HttpApiMode 속성 추가 - 기존 검색기들 리팩토링 및 통합 (NamguLibrarySearcher 등) - Check_copyWD.cs에 모든 새로운 도서관 등록 완료 - 설정 관리 시스템 개선 (UserSetting 클래스 추가) 총 200개 이상의 도서관 지원으로 복본조사 범위 대폭 확대 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -41,4 +41,116 @@
|
||||
F:\(VHD) Program Files\Microsoft Visual Studio\2022\MSBuild\Current\Bin\msbuild.exe
|
||||
|
||||
## 프로젝트 파일명
|
||||
UniMarc.csproj
|
||||
UniMarc.csproj
|
||||
|
||||
## 도서관 검색기(크롤링) 클래스 작성 가이드
|
||||
|
||||
### 개요
|
||||
도서관 웹사이트에서 도서 검색 결과를 크롤링하는 클래스들을 구현합니다.
|
||||
각 도서관 사이트의 특성에 따라 HTTP 방식 또는 Selenium 방식을 선택합니다.
|
||||
|
||||
### 방식 선택 기준
|
||||
- **HTTP 방식**: URL이 변경되는 사이트 (GET 파라미터로 검색)
|
||||
- **Selenium 방식**: URL이 변경되지 않는 사이트 (POST 폼 제출)
|
||||
|
||||
### 1. HTTP 방식 (GET 요청)
|
||||
**참고 파일**: `SuncheonLibSearcher.cs`
|
||||
|
||||
**특징**:
|
||||
- HttpClient 사용
|
||||
- URL 파라미터로 검색
|
||||
- 빠른 실행 속도
|
||||
- HttpApiMode = true
|
||||
|
||||
**주요 구현 포인트**:
|
||||
```csharp
|
||||
// URL 구성
|
||||
var searchUrl = $"{SiteUrl}?search={encodedSearchTerm}&libCode={AreaCode}";
|
||||
|
||||
// HTTP 헤더 추가 (500 에러 방지)
|
||||
request.Headers.Add("User-Agent", "Mozilla/5.0...");
|
||||
request.Headers.Add("Accept", "text/html,application/xhtml+xml...");
|
||||
|
||||
// HTML에서 결과 수 정규식 추출
|
||||
var patterns = new[] {
|
||||
@"총\s*<strong[^>]*class=""cred""[^>]*>(\d+)</strong>\s*건"
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Selenium 방식 (크롤링)
|
||||
**참고 파일**: `GwangjuCityLibSearcher.cs`
|
||||
|
||||
**특징**:
|
||||
- Selenium WebDriver 사용
|
||||
- 폼 제출 방식
|
||||
- 복잡한 UI 상호작용 가능
|
||||
- HttpApiMode = false
|
||||
|
||||
**주요 구현 포인트**:
|
||||
```csharp
|
||||
// 도서관 선택 (드롭다운)
|
||||
var libSelect = wait.Until(d => d.FindElement(By.CssSelector("select[name='libCode']")));
|
||||
var selectElement = new SelectElement(libSelect);
|
||||
selectElement.SelectByValue(AreaCode);
|
||||
|
||||
// 검색어 입력
|
||||
var searchInput = wait.Until(d => d.FindElement(By.Id("bookSearchQuery")));
|
||||
searchInput.Clear();
|
||||
searchInput.SendKeys(searchTerm);
|
||||
|
||||
// 검색 버튼 클릭
|
||||
var searchButton = wait.Until(d => d.FindElement(By.CssSelector("button.bookSearchBtn")));
|
||||
searchButton.Click();
|
||||
|
||||
// 페이지 로딩 대기
|
||||
await WaitForPageChange(wait);
|
||||
```
|
||||
|
||||
### 3. 공통 인터페이스 구현
|
||||
모든 검색기는 `ILibrarySearcher` 인터페이스를 구현해야 합니다:
|
||||
|
||||
```csharp
|
||||
public interface ILibrarySearcher
|
||||
{
|
||||
Task<BookSearchResult> SearchAsync(string searchTerm);
|
||||
Task StartDriver(bool showdriver = false);
|
||||
void StopDriver();
|
||||
string SiteName { get; }
|
||||
string SiteUrl { get; }
|
||||
bool HttpApiMode { get; set; }
|
||||
int No { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Check_copyWD.cs에 등록
|
||||
새로운 검색기를 만든 후 반드시 Check_copyWD.cs의 생성자에 추가:
|
||||
|
||||
```csharp
|
||||
// 예시: 완도군립도서관
|
||||
idx = 1200;
|
||||
_searchService.AddSearcher(new WandoLibSearcher(idx++, "MA", "완도군립도서관"));
|
||||
_searchService.AddSearcher(new WandoLibSearcher(idx++, "MB", "노화공공도서관"));
|
||||
```
|
||||
|
||||
### 5. 결과 추출 패턴
|
||||
HTML에서 검색 결과 수를 추출하는 일반적인 패턴들:
|
||||
|
||||
```csharp
|
||||
var patterns = new[] {
|
||||
@"총\s*<strong[^>]*>(\d+)</strong>\s*건",
|
||||
@"검색결과\s*총\s*(\d+)\s*건",
|
||||
@"<span[^>]*class=""heighlight""[^>]*>(\d+)</span>",
|
||||
@"총\s*(\d+)\s*권\(개\)"
|
||||
};
|
||||
```
|
||||
|
||||
### 6. 에러 처리
|
||||
- 검색 결과 없음: `return 0`
|
||||
- 추출 실패: `return -1`
|
||||
- 예외 발생: BookSearchResult의 ErrorMessage에 설정
|
||||
|
||||
### 현재 구현된 검색기 목록
|
||||
1. HTTP 방식: SuncheonLibSearcher, MokpoLibSearcher, GwangsanLibSearcher, YeosuLibSearcher
|
||||
2. Selenium 방식: GwangjuCityLibSearcher, GoheungLibSearcher, BukguLibSearcher 계열, JeonbukEduLibSearcher
|
||||
|
||||
각 방식의 장단점을 고려하여 사이트 특성에 맞는 방식을 선택하여 구현하세요.
|
||||
Reference in New Issue
Block a user