프로그래밍 기술/웹 검색 엔진 만들기

6.2.2 WebPageGetter 구현

언제나휴일 2017. 12. 7. 09:19
반응형

6.2.2 WebPageGetter 구현


 

 이번에는 웹 페이지를 수집하는 WebPageGetter 클래스를 구현합시다.

class WebPageGetter

{

}

 

 멤버 이벤트로 웹 페이지 수집 완료 이벤트가 필요합니다. 이 부분은 이미 WebCollect에서 설명하였습니다.

internal event WebPostedEventHandler WebPosted = null;

 

 웹 페이지를 수집하는 방법은 여러가지 방법이 있는데 여기에서는 WebBrowser 컨트롤을 사용할게요. 이를 위해 Windows.Windows.Forms.dll을 참조 추가가 필요합니다. 멤버 필드로 웹 페이지 수집에 필요한 WebBrowser 개체를 생성합시다.

WebBrowser wb = new WebBrowser();

 

 수집 결과를 표현할 RawUrl 개체를 참조할 멤버 필드도 선언합시다.

RawUrl ru = null;

 

 이를 위해 RawUrl 클래스를 추가하세요.

public class RawUrl

{

}

 웹 페이지 수집을 위해서는 수집 대상 사이트가 필요합니다. 생성자에서 수집 대상 사이트 개체를 인자로 받게 합시다.

internal WebPageGetter(Candidate candidate)

 

 생성자에서는 인자로 받은 수집 대상 사이트를 입력 인자로 수집 결과 개체를 생성하여 멤버 필드에 설정합니다.

ru = new RawUrl(candidate);

 

 이를 위해 RawUrl 클래스에 수집 대상 사이트를 입력 인자로 받는 생성자를 추가하세요.

public RawUrl(Candidate candidate)

{

}

 

 WebPageGettter 생성자에서는 웹 브라이저 컨트롤의 문서 완료 이벤트 핸들러를 등록합니다.

wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(

                                       wb_DocumentCompleted);

 

 문서 완료 이벤트 핸들러에서는 웹 브라이저 컨트롤의 HtmlDocument의 내용이 필요합니다. 그리고 페이지 주소를 얻어옵니다.

HtmlDocument hdoc = wb.Document;

 string url = hdoc.Url.AbsoluteUri;

 

 만약 수집 결과 개체에 이미 포함하고 있는 주소이면 메서드를 종료합니다.

if (ru.Contain(url))

{

    return;

}

 

 이를 위해 RawUrl 클래스에 Contain 메서드를 추가합니다.

public bool Contain(string url)

{

    throw new NotImplementedException();

}

 

 수집 개체를 포함하고 있지 않으면 결과 주소를 추가합니다.

AddRawUrl(url, hdoc);

 

 그리고 수집한 웹 문서가 프레임 구조로 되어 있으면 내부 Html창 개체의 Load 이벤트 핸들러를 등록합니다.

foreach (HtmlWindow hw in hdoc.Window.Frames)

{

    hw.Load += new HtmlElementEventHandler(hw_Load);

}

 

 결과 주소를 추가하는 AddRawUrl 메서드를 구현합시다.

private void AddRawUrl(string url, HtmlDocument hdoc)

 

 

 입력 인자로 받은 Html 문서의 내부 문서가 null이면 메서드를 종료합니다.

if (hdoc.ActiveElement.InnerText == null)

{

    return;

}

 

 그렇지 않으면 수집한 웹 페이지 개체를 추가하고 수집 완료 이벤트를 호출합니다.

RawPostedPage purl = ru.AddPostedPage(url, hdoc);

if (WebPosted != null)

{

    WebPosted(thisnew WebPostedEventArgs(purl));

}

 

 이를 위해 RawUrl 클래스에 AddPostedPage 메서드를 추가하고 WebPostedEventArgs클래스에 생성자 메서드를 추가합니다.

public RawPostedPage AddPostedPage(string url,HtmlDocument hdoc)

{

    throw new NotImplementedException();

}

public WebPostedEventArgs(RawPostedPage rpp)

{

}

 

 Html 창의 Load 이벤트 핸들러를 구현합시다.

void hw_Load(object sender, HtmlElementEventArgs e)

 

 먼저 이벤트를 발생한 개체를 HtmlWindow 형식으로 참조합니다.

HtmlWindow hw = sender as HtmlWindow;

 

 Html 창의 주소를 얻어옮니다.

string url = hw.Url.AbsoluteUri;

 

 이미 수집 결과에 포함한 주소이면 메서드를 종료합니다.

if (ru.Contain(url))

{

    return;

}

 

 그렇지 않으면 수집한 결과에 추가합니다.

AddRawUrl(url, hw.Document);

 

 Html 창 내부가 프레임 구조로 되어 있으면 내부 창의 Load 이벤트 핸들러를 등록합니다.

foreach (HtmlWindow hw2 in hw.Frames)

{

    hw2.Load += new HtmlElementEventHandler(hw_Load);

}

 

 마지막으로 Start 메서드를 구현합시다. 여기에서는 수집 대상 주소로 웹 브라이저를 운행합니다.

internal void Start()

{

    wb.Navigate(ru.CD.Url);

}

 

WebPageGetter.cs

using System.Windows.Forms;

namespace WEB_Robot_Lib

{

    class WebPageGetter

    {

        internal event WebPostedEventHandler WebPosted = null;

        WebBrowser wb = new WebBrowser();

        RawUrl ru = null;

        internal WebPageGetter(Candidate candidate)

        {

            ru = new RawUrl(candidate);

            wb.DocumentCompleted +=

              new WebBrowserDocumentCompletedEventHandler(

              wb_DocumentCompleted);

        }

        void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

        {

            HtmlDocument hdoc = wb.Document;

            string url = hdoc.Url.AbsoluteUri;

            if (ru.Contain(url))

            {

                return;

            }

            AddRawUrl(url, hdoc);

            foreach (HtmlWindow hw in hdoc.Window.Frames)

            {

                hw.Load += new HtmlElementEventHandler(hw_Load);

            }

        }

        void hw_Load(object sender, HtmlElementEventArgs e)

        {

            HtmlWindow hw = sender as HtmlWindow;

            string url = hw.Url.AbsoluteUri;

            if (ru.Contain(url))

            {

                return;

            }

            AddRawUrl(url, hw.Document);

            foreach (HtmlWindow hw2 in hw.Frames)

            {

                hw2.Load += new HtmlElementEventHandler(hw_Load);

            }

        }

        private void AddRawUrl(string url, HtmlDocument hdoc)

        {

            if (hdoc.ActiveElement.InnerText == null){    return;    }

            RawPostedPage purl = ru.AddPostedPage(url, hdoc);

            if (WebPosted != null)

            {

                WebPosted(thisnew WebPostedEventArgs(purl));

            }

        }

        internal void Start()

        {

            wb.Navigate(ru.CD.Url);

        }

    }

}

 

반응형