[PHP] htmlParser(phpquery라이브러리)를 이용해 XML파일(HTML)을 사용하는 방법


Development note/PHP  2019. 11. 6. 09:00

안녕하세요. 명월입니다.


이 글은 PHP에서 htmlParser(phpquery라이브러리)를 이용해 XML파일(HTML)을 사용하는 방법에 대한 글입니다.


이 html parser의 경우는 java에서는 Jsoup, C#에서는 Nsoup와 같은 방식의 라이브러리입니다.

링크 - [C#] NSoup 라이브러리 (XML, HTML 파서)

링크 - [Java] Jsoup를 이용해서 XML파일(HTML)을 다루는 방법


프로그램을 하다보면 웹 스크래핑이나 다른 웹 사이트의 html를 분석하거나 xml를 좀 더 효과적으로 데이터 취득하는 방법이 필요합니다.

저의 경우에는 Jquery의 Sizzle 엔진이 가장 편하다고 생각합니다.


예를 들어, 태그의 경우에는 "tag", 클래스로 읽을 때는 ".className", Id로 읽을 때는 "#IDName" 식으로 읽는 방법입니다.

그리고 find한 후에는 attr이나 val 등을 이용해 어트리뷰트를 읽고 html로 html 태그 전체를 읽을 때도 있습니다.


PHP에서는 phpquery라이브러리가 이를 제공합니다.

링크 - https://code.google.com/archive/p/phpquery/


먼저 composer로 라이브러리를 링크합니다.


{
    "require": {
        "electrolinux/phpquery": "0.9.6"
    }
}

packagist 사이트에서 phpquery를 찾으면 왠지는 모르겠는데 상당히 많이 나옵니다. 그 중에서 electrolinux/phpquery가 구글 프로젝트에 등록되어있는 라이브러리고 가장 많이 사용되기도 하네요.

이제 본 소스를 작성해 봅니다.

<?php
require_once 'vendor/autoload.php';
// ob함수로 php의 response 버퍼의 값을 읽어서 사용한다.
ob_start();
?>
<!DOCTYPE html>
<html>

<head>
  <title>title</title>
</head>

<body>
  <p id="data" data-type="test">hello world!!</p>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</body>

</html>
<?php
// 버퍼로 부터 데이터를 받고 clear한다.
$output = ob_get_contents();
ob_end_clean();
// html코드를 넣는다.
phpQuery::newDocumentHTML($output);
// p 태그를 찾는다.
$p = pq('p');
// p 태그의 html
var_dump($p->html());
// 어트리뷰트 data-type를 찾는다.
var_dump($p->attr("data-type"));


// cURL로 html를 가져오는 함수이다.
function connectHttp($url, $post, $param, $header = null)
{
  $handle = curl_init();
  try {
    curl_setopt($handle, CURLOPT_URL, $url);
    curl_setopt($handle, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($handle, CURLOPT_AUTOREFERER, TRUE);
    curl_setopt($handle, CURLOPT_POST, $post);
    curl_setopt($handle, CURLOPT_POSTFIELDS, $param);
    curl_setopt($handle, CURLOPT_VERBOSE, TRUE);
    curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($handle, CURLOPT_HEADER, TRUE);
    if ($header !== null) {
      curl_setopt($handle, CURLOPT_HTTPHEADER, $header);
    }
    $response = curl_exec($handle);
    $header_size = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
    $header_map = array();
    $header = substr($response, 0, $header_size);
    $temp = explode("\r\n", $header);
    array_push($header_map, $temp[0]);
    foreach ($temp as $item) {
      $temp2 = explode(":", $item);
      $header_map[$temp2[0]] = str_replace($temp2[0] . ":", "", $item);
    }
    $body = substr($response, $header_size);
    return array(
      "header" => $header_map,
      "body" => $body
    );
  } finally {
    curl_close($handle);
  }
}
// 내 블로그의 html를 가져온다.
$ret = connectHttp("https://nowonbun.tistory.com", "GET", array());
var_dump($ret);
// body의 데이터를 가져온다.(html 영역)
phpQuery::newDocumentHTML($ret["body"]);
// title 태그를 찾는다.
$title = pq('title');
// title 태그의 text를 출력한다.
var_dump($title->html());
?>

phpquery의 라이브러리에도 plugin으로 직접 html로 접속을 해서 html를 가져오는 함수가 있습니다. 그런데 왜인지 저는 에러가 발생하네요. 그래서 cUrl로 html를 가져와서 parsing해 보았습니다.

링크 - https://code.google.com/archive/p/phpquery/wikis/WebBrowser.wiki

링크 - [PHP] PHP의 HttpConnection 도구 cURL 사용 방법


결과는 예상대로 p태그의 data-type의 어트리뷰트 값과 html 값이 출력이 되었습니다.

그리고 제 블로그에서도 html를 가져와서 title를 제대로 출력을 했네요.


여기까지 PHP에서 htmlParser(phpquery라이브러리)를 이용해 XML파일(HTML)을 사용하는 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.