닷넷/C#

C# WebBrowser없이 HTML 파싱하기(HtmlAgilityPack 사용기)

FreeBear 2019. 12. 26. 19:56
반응형

웹브라우저로 사이트 띄우고 html을 가져오고 하는게 은근히 손이 많이 들어간다.
처음부터 끝까지 오로지 하나의 메소드 안에서 코드로만 작업하고 싶다.

 사이트 주소는 모르고 html 형식으로 된 텍스트만 가지고 있을때
html을 파싱할 수 있는 방법이 어디 없을까?

 

도구 > NuGet 패키지 관리자 > 솔루션용 NuGet 패키치관리 순으로 클릭한다.

HtmlAgilityPack을 검색한다.

HtmlAgilityPack을 설치한다.

HtmlAgilityPack이 설치된 후 사용할 폼 코드 맨 윗줄에

System의 HtmlDocument랑 충돌나므로
using hap = HtmlAgilityPack; 이런 식으로 입력한다.

 

private void buttonSystem_Click(object sender, EventArgs e)
{
	// 웹브라우저를 통해 html를 가져온다.
    HtmlDocument doc = webBrowser1.Document;
    
    // html에서 ID에 해당하는 텍스트만 담는다.
    // travel-search-result-data는 쿠팡여행사이트 페이지 소스를 보면 있는 script ID이다.
    HtmlElement fm = doc.GetElementById("travel-search-result-data");
    
    string innerhtml = fm.InnerHtml;
	
    // 텍스트가 json으로 되어 있어서 내부 데이터인 json을 파싱하는 것이다. 
    JObject jobj = JObject.Parse(innerhtml);
    
    // 검색한 상품만
    string products = jobj["products"]["result"].ToString();        

    JArray array = JArray.Parse(products);
    
    foreach (JObject item in array)
    {
    	// 상품링크를 얻기위해 ID 찾기
    	listBox1.Items.Add(item["vendorItemPackageId"].ToString());
    }
}

위의 예제 코드처럼 System에 있는 HtmlDocument를 사용하기 위해선
HtmlDocument 형식으로 형변환이 필요하며 때문에 웹브라우저를 사용해야만 한다.

 

private void buttonHap_Click(object sender, EventArgs e)
{
    // WebClient를 통해 파싱하고자 하는 사이트의 html 텍스트를 가져온다.
    WebClient wc = new WebClient();
    wc.Encoding = Encoding.UTF8;
    string html = wc.DownloadString(txtSite.Text);
    
    // HtmlAgilityPack에 있는 HtmlDocument는 텍스트로 되어 있는 걸 담을 수 있다.
    agi.HtmlDocument doc = new agi.HtmlDocument();
    doc.LoadHtml(html);

    // 노드 파싱방법이 두가지이다.
    // 첫번째 ID로 찾기
    agi.HtmlNode someNode = doc.GetElementbyId("travel-search-result-data");   
    string innerhtml = someNode.InnerHtml; 
    
    // 두번째 주소로 찾기(명시적)
    // var fm = doc.DocumentNode.SelectNodes("//script[@id='travel-search-result-data']")[0];
    // string innerhtml = sfm.InnerHtml;
    
    JObject jobj = JObject.Parse(innerhtml);
    string products = jobj["products"]["result"].ToString();

    JArray array = JArray.Parse(products);

    foreach (JObject item in array)
    {
    	listBox1.Items.Add(item["vendorItemPackageId"].ToString());
    }
}

HtmlAgilityPack에 있는 HtmlDocument는 텍스트로 되어 있어도 된다.

노드를 파싱하는 방법은 두가지가 있는데

예를 들어

<html><head><body>
<div id="test">
블라블라
</div>
</body></head></html>

가 있으면

첫번째는 태그에 있는 ID를 안다면 ID로 찾는 방법

GetElementById를 이용하면 된다.
어떤 태그던 그 아이디를 가지고 있는 태그의 html를 가져올 수 있다.

두번째는 명시적경로이다.

head 안에 있다면 /div[@id='test']
body 안에 있다면 //div[@id='test']

로도 첫번째 방법과 똑같은 결과를 가져올 수 있다.

반응형