반응형

HtmlAgilityPack은 HTML 문서를 쉽게 분석하고 조작할 수 있는 .NET용 라이브러리입니다. ASP.NET (ASPX) 환경에서도 사용할 수 있으며, 주로 웹 스크래핑, HTML 파싱, 특정 요소 추출 등에 활용됩니다. 

 

1. HtmlAgilityPack 설치

HtmlAgilityPack은 NuGet 패키지로 제공됩니다. 다음 단계를 통해 프로젝트에 추가할 수 있습니다.

  1. Visual Studio에서 NuGet 패키지 관리자 콘솔 열기
    • 도구 > NuGet 패키지 관리자 > 패키지 관리자 콘솔 클릭.
  2. NuGet 패키지 설치
Install-Package HtmlAgilityPack

 

  1. 설치가 완료되면 프로젝트에 HtmlAgilityPack 라이브러리가 추가됩니다.

2. HTML 파싱 기본 코드

using System;
using System.Net.Http;
using HtmlAgilityPack;

public partial class WebForm1 : System.Web.UI.Page
{
    protected async void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            string url = "https://example.com"; // 분석할 URL
            string htmlContent = await GetHtmlFromUrlAsync(url);

            // HtmlDocument로 로드
            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(htmlContent);

            // 예: <title> 태그 추출
            var titleNode = htmlDoc.DocumentNode.SelectSingleNode("//title");
            string title = titleNode != null ? titleNode.InnerText : "Title not found";

            // 예: 특정 클래스의 div 요소 추출
            var divNodes = htmlDoc.DocumentNode.SelectNodes("//div[@class='example-class']");
            if (divNodes != null)
            {
                foreach (var div in divNodes)
                {
                    Response.Write($"<p>{div.InnerText}</p>");
                }
            }

            // 결과 출력
            Response.Write($"<h1>Page Title: {title}</h1>");
        }
    }

    private async Task<string> GetHtmlFromUrlAsync(string url)
    {
        using (HttpClient client = new HttpClient())
        {
            // URL에서 HTML 가져오기
            HttpResponseMessage response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }
}
 

3. 코드 설명

  1. HttpClient 사용:
    • 지정한 URL에서 HTML 콘텐츠를 가져옵니다.
    • HttpClient를 통해 비동기 방식으로 HTML을 다운로드합니다.
  2. HtmlAgilityPack.HtmlDocument:
    • HTML을 파싱하고 DOM을 생성합니다.
    • LoadHtml() 메서드를 사용하여 HTML 문자열을 로드합니다.
  3. XPath를 사용한 노드 검색:
    • SelectSingleNode("//title"): HTML 문서에서 <title> 태그를 가져옵니다.
    • SelectNodes("//div[@class='example-class']"): 특정 클래스를 가진 <div> 태그들을 가져옵니다.
  4. 결과 출력:
    • Response.Write로 분석된 내용을 클라이언트에 출력합니다.

4. HTML 분석 시 주의사항

  • URL의 HTML 구조가 자주 바뀌는 경우 XPath를 업데이트해야 할 수 있습니다.
  • 웹사이트에 따라 robots.txt 파일을 확인하여 크롤링이 허용되는지 확인하세요.
  • HTML 인코딩 문제를 처리하려면 HtmlAgilityPack의 OptionReadEncoding 속성을 사용할 수 있습니다:
     
htmlDoc.OptionReadEncoding = true;

 

 

더 자세하게 HtmlAgilityPack으로 노드를 찾는 법을 알아봅시다.

 

HtmlAgilityPack에서 노드를 찾는 방법은 XPath를 사용하여 HTML 문서의 특정 요소를 선택하는 방식으로 이루어집니다. XPath는 XML 및 HTML 문서에서 요소를 검색하기 위한 쿼리 언어로, 다양한 패턴을 지원합니다. 아래에 구체적인 예제를 통해 SelectSingleNode 및 SelectNodes를 사용하는 방법과 XPath 문법을 자세히 설명하겠습니다.

 

1. 기본 노드 찾기

HTML 문서에서 특정 태그를 직접 선택할 수 있습니다.

예제 HTML

<!DOCTYPE html>
<html>
<head>
    <title>Sample Page</title>
</head>
<body>
    <h1>Welcome to the Sample Page</h1>
    <p>This is a sample paragraph.</p>
    <a href="https://example.com">Example Link</a>
</body>
</html>

XPath 예제

코드

HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(htmlContent);

// 1. <title> 태그 가져오기
var titleNode = htmlDoc.DocumentNode.SelectSingleNode("//title");
Console.WriteLine(titleNode.InnerText); // Output: Sample Page

// 2. <h1> 태그 가져오기
var h1Node = htmlDoc.DocumentNode.SelectSingleNode("//h1");
Console.WriteLine(h1Node.InnerText); // Output: Welcome to the Sample Page

// 3. <p> 태그 가져오기
var pNode = htmlDoc.DocumentNode.SelectSingleNode("//p");
Console.WriteLine(pNode.InnerText); // Output: This is a sample paragraph.
 

2. 속성을 기준으로 노드 찾기

특정 속성을 가진 태그를 선택할 수 있습니다.

예제 HTML

<div class="header">Header Section</div>
<div class="content">Main Content</div>
<div id="footer" class="footer">Footer Section</div>
 

XPath 예제

// 1. class가 "header"인 <div> 가져오기
var headerNode = htmlDoc.DocumentNode.SelectSingleNode("//div[@class='header']");
Console.WriteLine(headerNode.InnerText); // Output: Header Section

// 2. id가 "footer"인 <div> 가져오기
var footerNode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='footer']");
Console.WriteLine(footerNode.InnerText); // Output: Footer Section

// 3. class가 "content"인 모든 <div> 찾기
var contentNodes = htmlDoc.DocumentNode.SelectNodes("//div[@class='content']");
foreach (var node in contentNodes)
{
    Console.WriteLine(node.InnerText); // Output: Main Content
}

3. 여러 노드 선택

여러 노드를 선택하려면 SelectNodes를 사용합니다.

예제 HTML

<ul>
    <li>Apple</li>
    <li>Banana</li>
    <li>Cherry</li>
</ul>

XPath 예제

// <li> 태그들 모두 가져오기
var liNodes = htmlDoc.DocumentNode.SelectNodes("//li");

foreach (var node in liNodes)
{
    Console.WriteLine(node.InnerText);
}
// Output:
// Apple
// Banana
// Cherry

4. 구체적인 XPath 패턴

XPath를 활용하면 더욱 세부적으로 노드를 선택할 수 있습니다.

예제 HTML

<div class="product">
    <h2>Product 1</h2>
    <span class="price">$10</span>
</div>
<div class="product">
    <h2>Product 2</h2>
    <span class="price">$20</span>
</div>

XPath 예제

// 첫 번째 제품의 이름과 가격 가져오기
var firstProductName = htmlDoc.DocumentNode.SelectSingleNode("//div[@class='product']/h2").InnerText;
var firstProductPrice = htmlDoc.DocumentNode.SelectSingleNode("//div[@class='product']/span[@class='price']").InnerText;

Console.WriteLine($"{firstProductName} - {firstProductPrice}");
// Output: Product 1 - $10

// 모든 제품 정보 가져오기
var products = htmlDoc.DocumentNode.SelectNodes("//div[@class='product']");
foreach (var product in products)
{
    var productName = product.SelectSingleNode("./h2").InnerText; // 현재 노드 기준 검색
    var productPrice = product.SelectSingleNode("./span[@class='price']").InnerText;
    Console.WriteLine($"{productName} - {productPrice}");
}
// Output:
// Product 1 - $10
// Product 2 - $20

5. XPath 문법 정리

  • //tag
    특정 태그를 문서 전체에서 찾음.
    예: //div - 모든 <div> 태그.
  • ./tag
    현재 노드의 하위 태그를 찾음.
    예: ./span - 현재 노드 아래의 <span> 태그.
  • //tag[@attr='value']
    특정 속성을 가진 태그를 찾음.
    예: //div[@class='content'] - class가 content인 <div> 태그.
  • //tag[contains(@attr, 'value')]
    속성 값이 특정 문자열을 포함하는 태그를 찾음.
    예: //div[contains(@class, 'prod')] - class에 prod가 포함된 <div>.
  • //tag[text()='value']
    특정 텍스트 값을 가진 태그를 찾음.
    예: //span[text()='$10'] - 텍스트가 $10인 <span> 태그.

6. 전체 예제

아래는 다양한 XPath를 활용하여 HTML 문서를 분석하는 완전한 예제입니다.

using HtmlAgilityPack;
using System;

class Program
{
    static void Main()
    {
        string htmlContent = @"
        <html>
            <body>
                <div class='product'>
                    <h2>Product A</h2>
                    <span class='price'>$30</span>
                </div>
                <div class='product'>
                    <h2>Product B</h2>
                    <span class='price'>$50</span>
                </div>
            </body>
        </html>";

        HtmlDocument htmlDoc = new HtmlDocument();
        htmlDoc.LoadHtml(htmlContent);

        // 모든 제품 정보 가져오기
        var products = htmlDoc.DocumentNode.SelectNodes("//div[@class='product']");
        foreach (var product in products)
        {
            var productName = product.SelectSingleNode("./h2").InnerText;
            var productPrice = product.SelectSingleNode("./span[@class='price']").InnerText;
            Console.WriteLine($"{productName}: {productPrice}");
        }
    }
}

출력 결과:

Product A: $30
Product B: $50
반응형

+ Recent posts