C# WebBrowser없이 HTML 파싱하기(HtmlAgilityPack 사용기)
웹브라우저로 사이트 띄우고 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']
로도 첫번째 방법과 똑같은 결과를 가져올 수 있다.