Backends PHP

웹 스크래핑(웹 크롤링)의 기본원리

웹 스크래핑(Web Scraping)은 웹 페이지로부터 원하는 정보를 추출하는 기법입니다. 어떤 서비스에서 API가 별도로 제공되고 있지 않지만 웹 페이지로는 정보가 제공되고 있을 때, 웹 스크래핑 기법을 이용하면 원하는 정보를 획득할 수 있습니다.

웹 스크래핑은 흔히 웹 크롤링(Web Crawling)이라고도 많이 불립니다. 물론 엄밀하게 두 단어는 서로 다른 의미입니다. 크롤링은 여러 웹 페이지를 기계적으로 탐색하는 일을 말합니다. 한편 웹 스크래핑은 특정한 하나의 웹 페이지를 탐색하고, 또 소스코드 작성자가 원하는 정보를 콕 집어 얻어낸다는 점에서 크롤링과 차이가 있습니다. 그럼에도 크롤링과 스크래핑은 구현방법이 거의 같기 때문에, 실무에서는 구분없이 많이 불립니다.

이번 포스팅에서는 미국 CNBC 방송의 웹사이트에서 S&P 500 지수의 값을 확인하는 과정을 통해서, 웹 스크래핑의 원리를 PHP 예제코드를 통해 설명합니다.

 

웹 스크래핑의 원리

CNBC 웹사이트의 S&P 500 지수 그래프 화면
CNBC 웹사이트의 S&P 500 지수 그래프 화면 (링크)

위 화면은 미국의 대표적인 경제방송 CNBC의 웹 사이트에 게재되어 있는 S&P 500 지수현황입니다. 스크린 샷에서 2,952.01이라고 표시된 부분이 S&P 500 지수의 현재 값입니다. 이 웹 페이지에서 사람이 S&P 500 지수를 찾는 과정을 거쳐야 하는지 살펴본다면, 다음 3가지 과정으로 정리할 수 있습니다.

  1. 열기 : 웹 브라우저로 웹 페이지를 엽니다.
  2. 찾기 : 눈으로 원하는 정보(여기서는 S&P 500 지수)가 표시된 부분을 찾습니다.
  3. 보기 : 찾은 부분 안에 표시된 지수를 눈으로 보고 확인합니다.

사람이 웹 페이지에서 정보를 찾는 “열고, 찾고, 본다”의 3가지 과정을 소스코드로 그대로 구현해놓은 것이 바로 웹 스크래핑입니다. 다만 사람이 바라보는 것은 웹 브라우저에 표시된 화면이지만, 컴퓨터가 바라보는 것은 HTML 코드라는 것이 다른 점입니다. 따라서 웹 스크래핑으로 정보를 찾을 때에는 아래와 같이 HTML 코드를 헤짚는 과정을 거칩니다.

  1. 열기 : HTTP 통신으로 웹 페이지를 열어 HTML 코드 전체를 가져옵니다.
  2. 찾기 : 원하는 정보가 표시된 HTML 태그를 찾습니다.
  3. 보기 : 찾은 HTML 태그 안에 기재된 정보를 가져옵니다.

이 3가지 과정을 정확하게 소스코드로 구현할 수 있다면, 어떤 프로그래밍 언어로든 웹 스크래핑을 구현할 수 있습니다. 지금부터는 PHP로 S&P 500 지수 현황을 스크래핑을 진행하는 예제코드를 위 3단계에 맞추어서 소개합니다.

 

PHP에서의 웹 스크래핑 구현

#1 열기 (Loading)

PHP에서 웹 페이지를 열어보기 위해 가장 널리 쓰이는 방법은 cURL 라이브러리를 이용하는 것입니다. cURL 라이브러리는 우분투나 CentOS에서 패키지 관리 명령어로 간단하게 설치를 할 수 있고, 사용법 또한 매우 간결합니다.

cURL에 대한 소개와 사용법은 제가 이전 글에서 정리한 내용이 있으므로 참고하실 수 있습니다. 여기서는 실제 S&P 500 지수 현황 페이지의 HTML 코드를 문자열로 수신하는 예제코드만 소개합니다.

function getWebPage($url)
{
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HEADER, false);
	$res = curl_exec($ch);
	curl_close($ch);
	
	return $res;
}

$res = getWebPage('https://www.cnbc.com/quotes/?symbol=.SPX');

위 코드를 실행한 후 변수 $res를 확인하면, 웹 페이지의 HTML 소스코드가 문자열로 고스란히 담겨 있음을 확인할 수 있습니다.

 

#2 찾기 (Searching)

웹 페이지의 HTML 소스코드를 얻어냈다면, 이제 긴긴 HTML 코드를 해치고 원하는 정보가 어느 태그에 담겨 있는지를 발견해내야 합니다. 가장 손쉬운 방법은 웹 브라우저의 개발자 도구를 이용하는 것입니다.

대표적으로 Chrome 브라우저의 경우에는 F12 단축키를 눌러 개발자 도구를 열 수 있습니다. 개발자 도구는 설정에 따라 새 창으로 열릴 수도 있고, 웹 브라우저 한 켠에 구분된 영역으로 표시될 수도 있습니다.

구글 크롬 브라우저의 개발자 도구

열린 개발자 도구의 좌측 상단을 보면, 사각형 위에 마우스 포인터가 올려진 듯한 버튼이 있습니다. 이 버튼을 누르고 웹 페이지에서 자신이 확인하고자 하는 부분 위를 클릭하면, 해당 영역의 HTML 태그를 찾을 수 있는 단서를 찾을 수 있습니다. 위 화면의 경우에는 (‘.SPX’,’last’,’original’)라는 부분이 눈에 띕니다.

이제 개발자 도구에서 확인한 단서를 기초로 하여, HTML 소스코드를 열어서 해당 부분의 실제 HTML 태그를 확인합니다. 위 화면의 경우에는 S&P 500 지수의 현재 값이 다음과 같이 <span> 태그로 감싸져 있는 것을 확인할 수 있습니다.

<span class=’last original’ ng-bind=”quoteData[‘.SPX’].lastOutputoriginal | filter:processStripCondition(‘.SPX’,’last’,’original’)”>2991.25</span>

여기서 주목해야 할 점은 (‘.SPX’,’last’,’original’)라는 코드는 이 웹페이지의 HTML 소스코드에서는 다른 어디에서도 나오지 않고, 오직 우리가 원하는 S&P 500 지수를 감싸는 <span> 태그에만 유일하게 등장한다는 점입니다. 따라서 이 코드를 중심으로 HTML 태그를 헤짚는다면, 우리가 원하는 값에 충분히 도달할 수 있을 것입니다.

 

#3 보기 (Extracting)

이제 우리가 찾은 단서를 활용하여, 웹페이지의 HTML 소스코드 전체에서 원하는 값만 남기고 모두 제거하여 봅시다. 여기에는 여러 가지 방법이 있겠습니다만, 이해하기 쉽고 접근하기도 쉬운 좋은 방법 중 하나는 문자열 함수를 이용하는 것입니다. 아래의 예제처럼 strstr(), substr() 함수 등을 이용하여 차근차근 HTML 소스코드를 양분해가며 범위를 좁혀가면, 어느새 우리가 원하는 값에 도달하게 됩니다.

$res = strstr($res, "('.SPX','last','original')");
$res = strstr($res, ">");
$res = substr($res, 1);
$res = strstr($res, "<", true);

echo $res;

검출해야 할 HTML 태그가 복잡하지 않다면, 정규표현식을 이용해볼 수도 있습니다. 금번에 예제로 삼은 S&P 500 지수는 양 옆을 감싸고 있는 <span> 태그 하나를 잘 검출해내면 값을 금방 찾아낼 수 있으므로, 정규표현식 또한 아래처럼 간결하게 구성할 수 있습니다.

$regExp = "/\('\.SPX','last','original'\).+>([0-9.]+)</";
preg_match($regExp, $res, $matches);

echo $matches[1];

 

웹 스크래핑의 한계

웹 스크래핑은 API가 지원되지 않거나 서비스 제공사 측의 기술적인 지원이 없는 상황을 타개하고, 원하는 정보를 가져올 수 있는 사실상의 유일한 방법입니다. 그러나 웹 스크래핑에도 한계는 존재합니다.

첫 번째로 웹 페이지가 변경되거나 중단되면 수집 또한 중단된다는 것입니다. 수집 대상이 되는 웹 사이트가 리뉴얼을 단행하거나 도메인 이전이 이루어지는 경우, 또는 장애가 발생한 경우가 대표적인 예입니다. 이러한 일은 보통 예고 없이 발생하게 되므로, 만약 스크래핑으로 획득한 값은 비즈니스에서 핵심적인 역할로 활용하기 어렵습니다.

두 번째로 수집빈도를 높이는 것이 현실적으로 어렵다는 것입니다. 수 분의 간격이라면 문제가 되지 않겠지만, 그 간격이 수 초 단위로 줄어들면 웹서비스 측에서는 이를 악의적인 접속으로 판단하여 차단할지도 모릅니다. 특히 웹 스크래핑을 통해 실시간으로 정보를 수집하려고 시도한다면 그 자체로 DoS 공격과 다르지 않게 되므로, 이러한 시도는 해서는 안될 것입니다.

마지막으로 법적이슈에 취약하다는 것입니다. 빈번한 스크래핑으로 인하여 대상이 되는 웹 서비스에 서버 지연 등의 어려움이 발생하면, 형법상 영업방해죄에 해당할 여지가 있습니다. 또한 수집된 정보의 저작권 정보 역시 민감한 부분이기 때문에, 스크래핑을 비즈니스의 핵심적인 컨셉에 포함하는 계획은 위험성이 있음을 기억해야 합니다.

 

언어별 스크래핑 예제 보기