Backends PHP

PHP에서 CSS 선택자로 간편하게 웹 스크래핑(웹 크롤링)을 하는 방법

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

웹 스크래핑의 원리에 대해서는 이전 글인 웹 스크래핑(웹 크롤링)의 원리에서 다루었습니다. 이번 글에서는 PHP에서 몇 가지 패키지를 조합하여 손쉽게 구현한 웹 스크래핑 함수 예제코드를 소개합니다.

 

패키지 설치

이전 글을 토대로 웹 스크래핑의 원리에 대해서는 이해할 수 있었으나, 실제 그 과정을 직접 구현하는 것은 번거로운 일입니다. 그러나 PHP에서 Composer를 통해 설치할 수 있는 패키지 몇 가지만 있으면, 이 원리를 손쉽게 소스코드로 구현할 수 있습니다. 제가 구현시에 사용한 패키지는 아래 3가지입니다.

guzzle은 더 말할 필요가 없는 HTTP 통신 패키지의 대표주자로,  열기 과정에서 curl 대신에 사용할 수 있습니다. 이렇게 HTTP 통신으로 가져온 HTML을 dom-crawler 패키지를 사용하면, 찾기 과정에서 DOM 단위로 탐색할 수 있습니다. 마지막으로 css-selector는 dom-crawler에서 CSS 선택자를 사용할 수 있게 하는 패키지로, 보기 과정을 CSS 선택자로 한 번에 해결합니다.

composer require guzzlehttp/guzzle
composer require symfony/dom-crawler
composer require symfony/css-selector

각 패키지는 위와 같이 composer로 설치해주어야 합니다.

 

구현 함수

이 3가지 패키지를 통해 스크래핑 함수를 구현하면 아래와 같습니다. 함수는 먼저 $url 인자로 입력한 URL을 Guzzle 패키지를 통해 열어 HTML 소스코드를 받아옵니다. 이어서 입력한 CSS 선택자를 통해 DOM Crawler가 받아온 HTML 소스코드에서 해당하는 요소를 찾습니다. 마지막으로 찾은 내용을 배열 $res에 담아 최종적으로 반환합니다.

require_once(__DIR__ . '/../vendor/autoload.php');
 
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\DomCrawler\Crawler;
 
function scrapWebpage(string $url, string $selector): array
{
    $res = [];
    // 열기
    try {
        $client = new GuzzleClient();
        $response = $client->request('GET', $url);
    } catch (GuzzleException $e) {
        die('Exception');
    }
 
    if ($response->getStatusCode() == 200) {
        // 찾기
        $html = strval($response->getBody());
 
        $crawler = new Crawler($html);
        $crawler = $crawler->filter($selector);
        // 보기
        foreach ($crawler as $domElement) {
            $res[] = $domElement->nodeValue;
        }
    }
 
    return $res;
}

실제로 위 함수를 사용하는 예는 아래와 같습니다. 스크래핑할 URL와 스크래핑할 부분의 CSS 선택자를 넣어 간단하게 사용할 수 있습니다. 반환하는 값은 배열이기 때문에, 입력한 선택자에 여러 개의 요소가 해당하더라도 문제없이 정보를 수집할 수 있습니다.

$res = scrapWebpage('http://dev.epiloum.net/', 'h1.entry-title a');

위 코드는 간단한 소개를 위해서 네임스페이스 등이 생략되어 있으며, 전체 소스코드는 Github 저장소에서 확인하실 수 있습니다. 필요하신 분은 참고하여 주시기 바랍니다.

Leave a Reply

Your email address will not be published. Required fields are marked *