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 – 열기

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 소스코드가 문자열로 고스란히 담겨 있음을 확인할 수 있습니다.

 

PHP에서의 웹 스크래핑 구현 #2 – 찾기

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

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

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

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

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

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

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

 

PHP에서의 웹 스크래핑 구현 #3 – 보기

이제 우리가 찾은 단서를 활용하여, 웹페이지의 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];

 

웹 스크래핑에서 웹 크롤링으로 확장해가기

금번 예제에서는 이해를 쉽게 하기 위해, 하나의 웹 페이지에서 단 하나의 값 만을 얻는 웹 스크래핑 방법을 설명하였습니다. 그러나 여러 개의 웹 페이지를 순차적으로 찾아들어가는 웹 크롤링 또한 이 과정에서 크게 벗어나지 않습니다. 뉴스 사이트에서 각 기사내용을 크롤링하는 사례를 예로 들자면 아래와 같습니다.

  1. 열기 : 기사목록 웹 페이지를 HTTP 통신으로 열어 HTML 소스코드 전체를 가져옵니다.
  2. 찾기 : 기사목록에 게재된 기사들의 URL을 찾습니다. 이 때, 찾아야 할 URL이 예제와는 다르게 여러 개라는 점이 다를 뿐입니다.
  3. 다시 열기 : 찾은 HTML 태그 안에는 URL이 있기 때문에, “보기” 과정 대신에 1번으로 돌아가 찾은 URL을 다시 HTTP 통신으로 엽니다.
  4. 보기 : 더이상 찾아 들어갈 URL이 없다면, 이제는 원하는 값을 가져옵니다.

웹 크롤링 또한 결국 열기·찾기·보기의 3단계 과정에서 벗어나지 않습니다. 단지 “찾기” 과정에서 획득한 URL을 이용해 “열기” 과정을 반복한다는 점이 다를 뿐입니다.

 

웹 스크래핑의 한계

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

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

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

카카오톡

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.

*

다음의 HTML 태그와 속성을 사용할 수 있습니다: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>