C#

Web Crawler 웹 크롤러

Web Crawling을 위해 자신이 직접 멀티쓰레드를 사용하여 웹 페이지들을 방문, 링크를 분석해 나가며 크롤링하는 코드를 작성할 수 있지만, 좀 더 간단하게는 Web Crawler 라이브러리를 사용할 수도 있다. 이번 아티클에서는 .NET용 Web Crawler의 하나인 Abot Web Crawler를 사용해 본다.

Abot Web Crawler

Abot은 오픈소스 웹 크롤러로서 C#에서 쉽게 웹 크롤링 기능을 사용할 수 있다. Abot에 대한 코드와 설명은 Abot 깃허브를 참고한다.

(1) Abot 웹 크롤러를 사용하기 위해서는 먼저 VS 프로젝트에서 Abot Nuget 패키지를 설치한다.

PM> Install-Package Abot

(2) WebCrawler 객체 인스턴스를 생성한다. IWebCrawler 인터페이스를 구현하는 여러 웹 크롤러를 사용할 수 있는데, 아래 예제에서는 기본적인 PoliteWebCrawler 크롤러를 사용하였다.

(3) 웹 크롤러의 기본 옵션은 App.config에 지정하여야 한다. 아래 C# 코드 밑의 App.config 샘플처럼 configSections 섹션과 abot 섹션을 설정한다.
(주: Optional로 C# 코드에서 아래 예제처럼 옵션들을 지정할 수도 있는데, 이렇게 하면 App.config에 정의된 기본 옵션을 덮어쓰게 되고, WebCrawler 객체 인스턴스 생성시 옵션 객체를 전달하게 된다)

(4) Abot 웹 크롤러에는 여러 event를 제공하고 있는데, 일반적으로 웹 페이지 크롤링이 끝난 경우 호출되는 PageCrawlCompletedAsync 이벤트를 핸들링해 준다. 아래 예제에서는 크롤링이 시작할 때 호출되는 PageCrawlStartingAsync 이벤트도 핸들링해 주고 있다.
PageCrawlCompletedAsync 이벤트는 두번째 파라미터에서 PageCrawlCompletedArgs 아규먼트를 전달하는데, PageCrawlCompletedArgs.CrawledPage 속성은 웹 크롤링된 웹페이지에 대한 정보를 가지고 있다. CrawledPage.Content 속성은 실제 웹페이지 내용이고, CrawledPage.Content.Text은 HTML 문서를 문자열로 리턴하는 속성이다. 또한, 크롤링된 웹페이지의 URL 정보는 CrawledPage.Uri 속성에서 찾을 수 있다.

(5) 위와 같이 모든 설정이 셋업되었으면, 실제 크롤링을 위해 Crawl(url) 메서드를 호출한다. 이 메서드는 웹사이트 URL을 파라미터로 받아 해당 웹사이트에 대한 크롤링을 시작하고, 크롤링 결과를 위 (4)의 PageCrawlCompletedAsync 이벤트 핸들러에 전달한다.

아래 예제는 네이버 사이트에 대한 웹 크롤링을 해서,

using System;
using System.IO;
using Abot.Crawler;
using Abot.Poco;

namespace AbotCrawler
{
    // Nuget: Install-Package Abot

    class Program
    {
        static void Main(string[] args)
        {
            // 크롤러 인스턴스 생성
            IWebCrawler crawler = new PoliteWebCrawler();

            // 옵션과 함께 크롤러 인스턴스 생성할 경우
            // var crawlConfig = new CrawlConfiguration();
            // crawlConfig.CrawlTimeoutSeconds = 1000;
            // crawlConfig.MaxConcurrentThreads = 10;
            // crawlConfig.MaxPagesToCrawl = 10;
            // crawlConfig.UserAgentString = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0";
            // IWebCrawler crawler = new PoliteWebCrawler(crawlConfig);

            // 이벤트 핸들러 셋업
            crawler.PageCrawlStartingAsync += (s, e) =>
            {
                Console.WriteLine("Starting : {0}", e.PageToCrawl);
            };

            crawler.PageCrawlCompletedAsync += (s, e) =>
            {
                CrawledPage pg = e.CrawledPage;

                string fn = pg.Uri.Segments[pg.Uri.Segments.Length - 1];
                File.WriteAllText(fn, pg.Content.Text);

                //var hdoc = pg.HtmlDocument; //HtmlAgilityPack HtmlDocument

                Console.WriteLine("Completed : {0}", pg.Uri.AbsoluteUri);
            };

            // 크롤 시작
            string siteUrl = "http://www.naver.com";
            Uri uri = new Uri(siteUrl);

            crawler.Crawl(uri);            
        }

    }
}


/* App.config에 추가할 내용 */

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <section name="abot" type="Abot.Core.AbotConfigurationSectionHandler, Abot"/>
  </configSections>
  
  <abot>
    <crawlBehavior
      maxConcurrentThreads="1"
      maxPagesToCrawl="10"
      maxPagesToCrawlPerDomain="0"
      maxPageSizeInBytes="0"
      userAgentString="Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
      crawlTimeoutSeconds="0"
      downloadableContentTypes="text/html, text/plain"
      isUriRecrawlingEnabled="false"
      isExternalPageCrawlingEnabled="false"
      isExternalPageLinksCrawlingEnabled="false"
      httpServicePointConnectionLimit="200"
      httpRequestTimeoutInSeconds="15"
      httpRequestMaxAutoRedirects="7"
      isHttpRequestAutoRedirectsEnabled="true"
      isHttpRequestAutomaticDecompressionEnabled="false"
      isSendingCookiesEnabled="false"
      isSslCertificateValidationEnabled="false"
      isRespectUrlNamedAnchorOrHashbangEnabled="false"
      minAvailableMemoryRequiredInMb="0"
      maxMemoryUsageInMb="0"
      maxMemoryUsageCacheTimeInSeconds="0"
      maxCrawlDepth="100"
      maxLinksPerPage="1000"
      isForcedLinkParsingEnabled="false"
      maxRetryCount="0"
      minRetryDelayInMilliseconds="0"
      />
    <authorization
      isAlwaysLogin="false"
      loginUser=""
      loginPassword="" />
    <politeness
      isRespectRobotsDotTextEnabled="false"
      isRespectMetaRobotsNoFollowEnabled="false"
      isRespectAnchorRelNoFollowEnabled="false"
      isIgnoreRobotsDotTextIfRootDisallowedEnabled="false"
      robotsDotTextUserAgentString="abot"
      maxRobotsDotTextCrawlDelayInSeconds="5"
      minCrawlDelayPerDomainMilliSeconds="1000"/>
  </abot>

</configuration>

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

Previous Next Print