Web Crawling - 테이블 데이터 취득하기(C#, Selenium)

GUNHEE LEE·2024년 2월 29일
0

Web Crawling

목록 보기
2/2
post-thumbnail

[과제]
위 페이지에서 테이블의 데이터를 취득해서 바탕화면의 엑셀 파일에 저장한다.
테이블의 세 번째 행인 '공고명'부터 '입력일시'까지 취득하며
마지막 행에는 데이터를 취득한 시간을 추가한다.

1. NoSuchElementException

테이블을 개발자 도구로 검사하고 Xpath를 복사하고 검색하면 'NoSuchElementException' 에러가 발생한다.
이 문제는 HTML 문서가 여러 개의 frame으로 구성되어 있고 frame 마다 head와 body가 존재하기 때문에 발생한다.
내가 취득하려는 데이터가 있는 frame으로 이동하려면 다음과 같이 입력해야 한다.

// Switch to main frame
driver.SwitchTo().Frame("sub");
driver.SwitchTo().Frame("main");

2. table Xpath -> tr

그 다음 table의 Xpath를 복사하고, table의 element 중 tr 태그를 찾아 리스트에 저장한다.

// Find table element
var table = driver.FindElement(By.XPath("//*[@id=\"resultForm\"]/div[2]/table"));

// Find every table row
var rows = table.FindElements(By.TagName("tr"));

// Save table data in 'tableData'
List<List<string>> tableData = new List<List<string>>();

 // flag to check first row
bool isFirstRow = true; 

3. 데이터 취득(특정 인덱스부터, 내용 추가)

과제의 경우 공고명에서부터 입력일시까지의 데이터를 취득해야 했다.
이를 구현하기 위해 td 태그의 3번째 인덱스부터 cells.Count-2까지 리스트에 저장하도록 반복을 수행했다.
셀에 검색한 오늘의 날짜도 입력해야 해서 데이터를 취득한 현재 시간을 'yyyy.MM.dd HH:mm'의 골로 변환해서 행에 추가했다.

foreach (var row in rows)
{
	// Not to add current date and time in first row
	if (isFirstRow)
	{
		isFirstRow = false;
		continue; 
	}

	// Find every 'td' in every row
	var cells = row.FindElements(By.TagName("td"));
	List<string> rowData = new List<string>();

	// Use for loop start with 3rd index
	for (int i = 3; i < cells.Count-2; i++)
	{
		// Extract cell data
		rowData.Add(cells[i].Text);
	}
                
	// After extracting, add current date and time
	string currentDateTime = DateTime.Now.ToString("yyyy.MM.dd HH:mm");
	rowData.Add(currentDateTime);
                
	// If row data is not empty, then add to list 'tableData'
	if (rowData.Count > 0)
	{
		tableData.Add(rowData);
	}
}

4. 바탕화면의 엑셀 파일 경로 가져오기

바탕화면에 '장표.xlsx' 파일이 있다고 가정한다. 해당 파일의 경로를 가져와서 작업하기 위해 다음과 같이 작성한다. ExcelPackage를 사용할 때는 EPPlus 패키지가 필요하고 상업적, 비상업적으로 사용하겠다는 라이센스 설정이 필요하다. 필자는 비상업적으로 이용하기 때문에 이를 NonCommercial로 설정했다.

// License setting as NonCommercial
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

// Get folder path of desktop
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

// Set file path
string filePath = Path.Combine(desktopPath, "장표.xlsx");

// Create ExcelPackage object
FileInfo fileInfo = new FileInfo(filePath);

5. 취득한 데이터를 엑셀 워크시트에 추가하기

가장 첫 번째 워크시트를 사용하고, 마지막 행을 찾아 한 줄을 더한 행에 데이터를 추가한다.
table의 데이터를 저장한 'tableData' 리스트의 row를 반복문으로 추가한다.
전부 추가하고 나면 변동사항을 저장하고, 출력이 성공적으로 완수되었다는 콘솔 메세지를 출력한다.

 using (ExcelPackage package = new ExcelPackage(fileInfo))
{   
	// Use first worksheet
	ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; 

	// Find last row to add extracted data
	int lastRow = worksheet.Dimension.End.Row + 1; 

	// Add data
	foreach (var row in tableData)
	{
		for (int i = 0; i < row.Count; i++)
		{
			worksheet.Cells[lastRow, i + 1].Value = row[i];
		}
	lastRow++;
	}
	// Save changes
	package.Save();
}
Console.WriteLine("Extracting is sucessfully worked!");

6. 실행결과


profile
새싹 개발자

0개의 댓글