WEB 스크래핑을 위한 Element 값 선정을 위해 간단히 알아본
XPath에 대해 이야기 해보려 한다.
XPath란?
XPath는 XML문장 속의 요소, 속성등을 지정하기 위한 언어이다. W3C(월드 와이드 웹 컨소시엄) 표준으로 문서의 구조를 통해 경로 위에 지정한 구문을 사용하여 항목을 배치하고 처리하는 방법을 기술하는 언어이다.
XPath는 XML의 항목을 배치하고 처리하기 위해 탄생하였지만 Markup Language를 처리하기 위한 방식이라고 봐야 한다.
그렇기 때문에 HTML과 같은 Markup Language에 대한 처리도 가능하다.
(본 글에서는 설명의 편의성을 위해 예시는 HTML코드를 대상으로 작성한다.)
XPath는 XML 표현보다 더 쉽고 약어로 되어있으며, XML문서의 노드를 정의하기 위해 경로식(Location Path)을 사용하며, 기타 확장 가능한 표현들도 있다.
예를 들어
<html>
<body>
<h1> Book </h1>
<div class="item">
<span class="title">Little Price</span>
<span class="create_year">1943</span>
<span class="price">8000</span>
</div>
</body>
</html>
위와 같은 HTML 코드를 경로식 트리로 변환하면 아래와 같은 구조가 된다.
또한 트리를 경로식으로 변환하면 다음과 같다.
/html/body/h1
/html/body/div/span
즉, "<h1> Book </h1> == /html/body/h1" 이 된다.
엘리먼트(=경로, =요소)에 대한 접근
XPath로 XML, HTML같은 마크업언어의 엘리먼트에 접근 가능하다.
경로식(이하 로케이션 패스)은 트리를 구성하는 엘리먼트의 값을 지정하거나 얻기 위한 방식이며, 표기는 우리가 흔히 보는 리눅스의 폴더 또는 URL구조와 유사하다.
<html>
<body>
<h1> Book </h1>
<div class="item">
<span class="title">Little Prince</span>
<span class="create_year">1943</span>
<span class="price">8000</span>
</div>
</body>
</html>
위 HTML코드 내 경로(=요소)에 대한 접근을 알아보자
"h1"요소에 접근 시 XPath에서는 "html 요소(element) -> body 요소 -> h1 요소" 로 접근해야 한다.
경로식으로 표현하면 아래와 같다.
/html/body/h1
'속성'을 활용한 요소 접근
그렇다면 다중 요소인 "span"은 어떻게 접근을 해야 할까?
정답은 "속성(Attribute)"에 있다.
XML, HTML과 같은 마크업언어에서 각 요소는 속성을 갖을 수 있다.(없을 수 도 있다)
<span class="title">Little Prince</span>
<span class="create_year">1943</span>
<span class="price">8000</span>
같은 경로, 같은 depth에 존재하는 "span" 요소를 보면 "class"라는 속성이 있다.
"class"라는 속성은 그룹으로 묶어서 css에서 스타일을 지정할 때 사용하는 속성이다.
더 상세한 이해가 필요하다면 html, css의 기본 지식이 필요하다. (https://aboooks.tistory.com/61 블로그의 글을 가볍게 보고 개념만 느껴보길 바란다.)
다시 본론으로 돌아와서,
다중으로 구성된 "span"요소에 접근을 하려면 각 요소를 구분지을 수 있는 "class"라는 속성을 이용하면 된다.
/html/body/div/span[@class='title']
위와 같은 로케이션패스로 접근을 한다면 "Little Prince"라는 값을 얻을 수 있다.
로케이션패스 축약('//')을 통한 편리한 요소 접근
하지만, 로케이션패스 단계가 매우 많거나, 코드가 매우 길어서 파악하기 어렵다면 "요소1/요소2/요소3/요소4...." 식으로 원하는 요소에 접근하기란 매우 어려울 것이다.
그렇기 때문에 XPath에서는 중간 로케이션패스를 생략할 수 있는 문법이 존재한다.
//span[@class='title']
눈치 빠른 독자는 이미 이해했을 것이다.
'//' 라는 표현을 통해 중간 로케이션패스가 생략 가능하다.
위 로케이션 패스의 의미는 아래 조건을 만족하는 요소의 값을 반환하는 것이다.
'//' : 어딘가에 있는
'span' : span 요소의
[ ] : 속성 중에
@class='title' : class 속성의 값이 'title'인
지정한 문자열 검색(contains)을 통한 요소 접근
속성, 축약을 통해 더욱 쉽게 요소에 접근할 수 있게 되었다.
하지만, 속성의 값을 일부만 알 경우는 어떻게 접근해야 할까?
XPath는 SQL에 like검색과 같은 접근법도 마련되어 있으며, 방법은 아래와 같다.
//span[contains(@class, 'year')]
'//' : 어딘가에 있는
'span' : span 요소의
[ ] : 속성 중에
contains(@class, 'year') : class 속성의 값에 'year' 문자열이 포함된
요소를 반환하라!
contains(text(), '문자열') 등으로 사용 시에는 '문자열'이 포함된 요소를 얻을 수 있다.
그 외 [ ] 안에 and, or, not 등 연계하여 다중 조건 표현도 가능하다.
//span[contains(@class,'year') or contains(@class,'create')]
마무리
지금까지 설명은 XPath를 다루는데 가장 기초가 되는 최소한의 정보입니다.
XPath에 대한 정보를 찾는 독자들은 스크래핑이나 RPA 등으로 인해 웹페이지에 대한 접근을 위해 찾는 경우가 대부분일 것입니다.
초급자라면 해당 글과 함께 HTML, CSS등의 기본 개념을 같이 참고하길 바랍니다.