피카부 RSS 태그 관리 글쓰기 방명록 다시 시작하는 개발 블로그
2022-02-19 09:11:04

PHP로 웹 페이지를 크롤링하고 파싱할 때 매우 편리하게 사용할 수 있는

PHP Simple HTML DOM Parser의 사용방법을 소개합니다.

 

소개

먼저 라이브러리를 다운로드합니다.

PHP Simple HTML DOM Parser - Browse Files at SourceForge.net

 

그리고 사용할 php파일에 로드해줍니다.

require_once 'simple_html_dom.php';

 

객체 생성

파싱할 html을 str_get_html() 또는 file_get_html()로 simple_html_dom 객체를 생성합니다.

// 문자열로 직접 넣기
$html = str_get_html ( '<html><body>Hello!</body></html>' );

// URL에서 가져오기
$html = file_get_html ( 'http://simple-html-dom-parser.com/');

// HTML 파일로 열기
$html = file_get_html ( 'example.html' );

html을 잘 가져 왔는지 확인하려면 출력을 해봅니다.

var_dump($html); //주의! 이대로 출력하면 너무 많은 양의 html 객체로 인해 서버에 부하를 일으킬 수 있습니다.

var_dump($html->plaintext) //이것은 html요소를 제외한 html에 있는 텍스트만 출력합니다. 위 방법보다 이것을 추천합니다.

 

메모리 정리

file_get_html() 등으로 오브젝트의 생성을 반복하면, 「Fatal error: Allowed memory size of 12000000 bytes exhausted (tried to allocate 16 bytes)」등의 에러가 나오며 메모리가 부족해질 수 있습니다. 메모리 부족 오류는 php.ini의 memory_limit을 초과할 때 발생합니다.

 

이러한 경우에는 simple_html_dom 객체의 clear()를 호출합니다. 그러면 객체의 속성이 해제되고 순환 참조로 인한 메모리 누수를 피할 수 있습니다.

$html->clear();

 

HTML 요소 찾기

이제부터 우리가 원하는 파싱의 기능입니다. 기본적으로 파싱은 find() 메소드로 조건과 일치하는 요소를 얻을 수 있습니다.

// 모든 a 요소를 검색하고 요소의 배열을 가져옵니다.
$ret = $html->find( 'a' );

// 첫 번째로 발견된 a 요소를 얻습니다. 발견되지 않는 경우는 null가 반환됩니다.
$ret = $html->find( 'a', 0 ); //0대신 1을 넣으면 두번째의 a요소가 선택됩니다.

// ... PHP 5.4 이상이라면 다음과 같이 작성할 수 있습니다.
$ret = $html->find( 'a' )[ 0 ];

// id 속성이 있는 모든 요소를 가져옵니다.
$ret = $html->find( '[id]' );

// id 속성이 있는 모든 div 요소를 가져옵니다.
$ret = $html->find( 'div[id]' );

// id 속성이 foo인 모든 div 요소를 가져옵니다.
$ret = $html->find( 'div[id=foo]' );

 

속성 선택에 사용할 수 있는 연산자

 
필터   설명
[ attribute ]   지정된 속성을 가지는 요소
[ attribute=value ] = 지정된 값을 가지는 요소
[ attribute!=value ] != 지정된 값을 가지지 않는 요소
[ attribute^=value ] ^= 지정된 값으로 시작되는 요소
[ attribute$=value ] $= 지정된 값으로 끝나는 요소
[ attribute*=value ] *= 지정된 값을 포함하는 요소

 

간단한 사용 방법

$html = str_get_html( '<a><b>Hello!</b></a>' );
echo $html->find( 'b', 0 ); // <b>Hello!</b>가 출력됨

 

구체적인 사용 방법

CSS의 ID 셀렉터 및 클래스 셀렉터 구문으로도 요소를 얻을 수 있습니다.

// id 속성이 foo인 모든 요소를 가져옵니다.
$ret = $html->find( '#foo' );

// class 속성이 foo인 모든 요소를 가져옵니다.
$ret = $html->find( '.foo' );

또한 쉼표로 구분하여 여러 조건을 지정할 수 있습니다.

// 모든 a 및 img 요소를 얻습니다.
$ret = $html->find( 'a , img' );

// title 속성을 가진 모든 a 및 img 요소를 가져옵니다. 
$ret = $html->find( 'a[title] , img[title]' );

 

아들 선택자

CSS의 아들 선택자 구문으로도 요소를 얻을 수 있습니다.

// ul 요소 안에 있는 모든 li 요소를 얻습니다.
$es = $html->find( 'ul li' );

// 중첩 div 요소를 얻습니다.
$es = $html->find( 'div div div' );

 

또한 속성 지정과 결합됩니다.

// class 속성이 hello인 table 요소 안에 있는 모든 td 요소를 가져옵니다.
$es = $html->find( 'table.hello td' );

// table 요소 안에 있는 align=center 속성을 가진 모든 td 요소를 가져옵니다.
$es = $html->find( 'table td[align=center]' );

 

중첩 선택자

// ul 요소 안에 있는 모든 li 요소를 얻습니다.
foreach( $html->find( 'ul' ) as $ul )
{
  foreach( $ul->find( 'li' ) as $li )
  {
    // $li에 결과가 저장됩니다.
  }
}
// 첫 번째 ul 요소에서 첫 번째 li 요소를 가져옵니다.
$e = $html->find( 'ul', 0 )->find( 'li', 0 );

// PHP 5.4 이상이라면 다음과 같이 작성할 수 있습니다.
$e = $html->find( 'ul' )[ 0 ]->find( 'li' )[ 0 ];

 

텍스트와 주석

// 모든 텍스트 블록을 얻습니다.
$es = $html->find( ' text ' );

// 모든 주석 ( <!-- ... --> )을 얻습니다.
$es = $html->find( ' comment ' );

 

HTML 요소에 액세스

// 요소에서 태그를 제외한 텍스트 검색
echo $html->plaintext;

// 요소 외부에 다른 요소를 설정합니다.
$e->outertext = '<div class="wrap">'.$e->outertext.'<div>';

// 빈 문자를 설정하고 요소를 삭제합니다.
$e->outertext = '';

// 요소 뒤에 추가
$e->outertext = $e->outertext.'<div>foo<div>';

// 요소 앞에 삽입
$e->outertext = '<div>foo<div>'.$e->outertext;

 

요소의 속성

// 속성 얻기 (속성이 값이 아니면 논리 값이 반환됨)
$value = $e->href;

// 속성 설정 (속성이 값이 아니면 논리 값 설정)
$e->href = 'my link';

// 속성을 삭제하고 값을 NULL로 설정
$e->href = null;

// 속성 존재 여부 체크
if( isset( $e->href ) )
{
    echo 'href exist!';
}

 

이상으로 PHP simple html dom parser에 대한 설명을 마칩니다.