ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C# WebBrowser없이 HTML 파싱하기(HtmlAgilityPack 사용기)
    닷넷/C# 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']

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

    반응형

    댓글

Designed by Tistory.