하이어시스템 소개
XPath는 원래 XML 문서에서 element를 탐색하기 위해 사용하는 표준입니다. 셀레니움(Selenium)에서도 Web Element를 탐색할 때 동일한 XPath 문법을 사용합니다. 셀레니움(Selenium)에서 XPath를 자유롭게 사용하기 위해 필요한 모든 내용을 정리하도록 하겠습니다.
Terminology 용어
노드(Nodes)
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
위의 예시에서 최상위 노드 bookstore 와 하위 노드 book, title, author, year, price가 존재합니다. 속성노드 lang="en"이 존재합니다.
원자값(Atomic values)
원자값은 노드가 아닌 값으로 이루어진 데이터입니다. Harry Potter, J K Rowling, 2005, 29.99 모두 원자값 입니다.
아이템(Item)
노드와 원자값을 통칭하여 아이템이라고 합니다.
Relationship of Nodes 노드간의 관계
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
Parent
book 엘리먼트는 title, author, year, price의 parent(부모) 입니다.
Children
반대로 title, author, year, price의 parent는 book의 children(자식) 엘리먼트는 입니다.
Siblings
title, author, year, price는 동일한 Parent를 가지는 siblings(형제) 엘리먼트입니다
<bookstore>
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
Ancestors
title의 Ancestors(조상) 엘리먼트는 book, bookstore 엘리먼트 입니다.
Descendants
bookstore의 Descendants(자손) 엘리먼트는 book과 title, author, year, price 입니다.
XPath Syntax 문법
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="en">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
Selecting Nodes 노드의 선택
XPath는 노드를 선택하기 위해 경로 표현식을 사용합니다. 가장 자주 사용하는 경로 표현식이 정리되어 있습니다.
Expression | Description |
nodename | Selects all nodes with the name "nodename" |
/ | XPath를 root 노드부터 작성시작 |
// | 문서 전체에서 해당 노드가 어느 위치에 있든 조건이 만족하면 모든 노드를 찾음 |
. | 현재 노드를 기준 노드로 XPath를 작성 |
.. | 현재 노드의 상위 노드를 선택 |
@ | 노드의 속성값을 선택 |
위 표에서의 경로 표현식과 이용하여 작성한 결과는 아래와 같습니다.
Path Expression | Result |
bookstore | 문서내에서 bookstore에 해당하는 모든 노드를 찾음 |
/bookstore | 최상위에 존재하는 bookstore를 찾음 주의:경로가 슬래쉬 slash ( / ) 로 시작하면 해당 XPath는 root 노드를 시작으로 하는 절대 경로 XPath |
bookstore/book | 문서내 모든 bookstore가 가지고 있는 모든 자식 book 노드를 찾음 |
//book | 문서 전체에서 어느 위치에 있든 모든 book 노드를 찾음 |
bookstore//book | 문서내 모든 bookstore가 가지고 있는 모든 자손 book 노드를 찾음 |
//@lang | 속성이름이 lang인 모든 속성을 찾음 |
Predicates 서술어
특정 노드를 지정하기 위해 서술어를 사용합니다. 서술어는 대괄호로 지정합니다.
Path Expression | Result |
/bookstore/book[1] | 루트 bookstore 하위의 book 노드중 첫번째를 지정합니다. 이 때 서술어를 제외하면 기본적으로 첫번째 노드를 찾게 됩니다. 노드 순번 서술어는 1부터 시작합니다. |
/bookstore/book[last()] | 루트 bookstore 자식 노드 book 중에서 가장 마지막 엘리먼트를 선택합니다. |
/bookstore/book[last()-1] | 루트 bookstore 자식 노드 book 중에서 뒤에서 2번째 엘리먼트를 선택합니다. |
/bookstore/book[position()<3] | 루트 bookstore하위 book 엘리먼트중 서술어가 1, 2인 엘리먼트를 선택합니다. |
//title[@lang] | 전체 문서에서 속성 lang을 가진 title 엘리먼트를 찾습니다. |
//title[@lang='en'] | 전체 문서에서 속성 lang의 값이 en인 title 엘리먼트를 찾습니다. |
/bookstore/book[price>35.00] | 루트 bookstore 하위 book 엘리먼트 중 하위의 price 엘리먼트 값이 35.00 보다 큰 book 엘리먼트를 찾습니다. |
/bookstore/book[price>35.00]/title | 루트 bookstore 하위 book 엘리먼트 중 하위의 price 엘리먼트 값이 35.00 보다 큰 book 엘리먼트의 자식 엘리먼트인 title 엘리먼트를 찾습니다. |
Selecting Unknown Nodes 알려지지 않은 노드 찾기
XPath 와일드카드를 사용하면 알려지지 않은 XML 노드를 찾을 수 있습니다.
Wildcard | Description |
* | 일치하는 모든 엘리먼트 노드 |
@* | 일치하는 모든 속성 노드 |
node() | 일치하는 엘리먼트 또는 속성 노드 |
In the table below we have listed some path expressions and the result of the expressions:
Path Expression | Result |
/bookstore/* | 루트의 bookstore 하위의 모든 자식 노드 |
//* | 현재 문서의 모든 노드 |
//title[@*] | 현재 문서에서 최소한 하나 이상의 속성을 가진 모든 tilte 노드 |
XPath Axes (여러가지 축)
축(Axis)은 문맥(현재) 노드와의 관계를 나타내며, 그 노드와 관련하여 트리 상에서 해당 노드를 찾는 데 사용됩니다.
AxisName | Result |
ancestor | 현재 노드의 모든 조상 노드 |
ancestor-or-self | 현재 노드를 포함한 모든 조상 노드 |
attribute | 현재 노드의 모든 속성들 |
child | 현재 노드의 모든 자식 노드 |
descendant | 현재 노드의 모든 자손 노드 |
descendant-or-self | 현재 노드를 포함한 모든 자손 노드 |
following | 현재 노드 이후로 문서에서 나타나는 모든 노드 |
following-sibling | 현재 노드 이후에 존재하는 모든 형제 노드 |
namespace | 현재 노드느의 모든 네임스페이스 노드 |
parent | 현재 노드의 모든 부모 노드 |
preceding | 현재 노드전에 존재하는 모든 노드. 단 조상노드, 속성노드, 네임스페이느 노드 제외 |
preceding-sibling | 현재 노드 이전에 존재하는 모든 형제 노드 |
self | 현재 노드 |
Axis Examples 축 사용 예시
Example | Result |
child::book | 자식 노드중 모든 book을 선택 |
attribute::lang | 현재 노드의 속성 중 lang 선택 |
child::* | 현재 노드의 모든 자식 노드 선택 |
attribute::* | 현재 노드의 모든 속성을 선택 |
child::text() | 현재 노드의 자식 노드에서 노든 text 노드를 선택 |
child::node() | 현재 노드의 모든 자식 노드를 선택 |
descendant::book | 현재 노드의 자손 노드중 모든 book을 선택 |
ancestor::book | 현재 노드의 조상 노드중 모든 book을 선택 |
ancestor-or-self::book | 현재 노드를 포함한 전체 조상 노드중 모든 book을 선택 |
child::*/child::price | 현재 노드의 손자 노드중 모든 price를 선택 |
XPath Operators 연산자
XPath를 사용할 때 다음의 연산자를 사용할 수 있습니다. 예시를 참고하세요.
operator | Description | Example |
| | 2개의 노드 모음 더하기 | //book | //cd |
+ | Addition | 6 + 4 |
- | Subtraction | 6 - 4 |
* | Multiplication | 6 * 4 |
div | Division | 8 div 4 |
= | Equal | price=9.80 |
!= | Not equal | price!=9.80 |
< | Less than | price<9.80 |
<= | Less than or equal to | price<=9.80 |
> | Greater than | price>9.80 |
>= | Greater than or equal to | price>=9.80 |
or | or | price=9.80 or price=9.70 |
and | and | price>9.00 and price<9.90 |
mod | Modulus (division remainder) | 5 mod 2 |
Examples 예시
1. 노드 구분자로 엘리먼트 찾기
/html/head
최상위 루트를 기준으로 절대경로를 이용해 head 엘리먼트 노드 찾기
//div
문서 전체에서 모든 div 엘리먼트 노드 찾기
//div/p
문서 전체에서 부모중에 div를 가지는 모든 p 엘리먼트 노드 찾기
//div//p
문서 전체에서 조상중에 div를 가지는 모든 p 엘리먼트 노드 찾기
//div//p/..
문서 전체에서 조상중에 div를 가지는 모든 p 엘리먼트의 부모 엘리먼트 노드 찾기
2. 서술어로 엘리먼트 찾기
//ul/li[1]
문서 전체에서 모든 ul 엘리먼트의 자식 엘리먼트중 가장 첫번째 li 엘리먼트 노드 찾기
//ul/li[last()]
문서 전체에서 모든 ul 엘리먼트의 자식 엘리먼트중 가장 마지막 li 엘리먼트 노드 찾기
3. 속성으로 엘리먼트 찾기
//*[@id="myElement"]
일치하는 속성값으로 엘리먼트 노드 찾기
//*[contains(@class, "myClass")]
일부 포함되는 속성값으로 엘리먼트 노드 찾기
4. 텍스트로 엘리먼트 찾기
//h2[text()="Welcome"]
일치하는 텍스트로 엘리먼트 노드 찾기
//p[contains(text(), "Hello")]
일부 포함되는 텍스트로 엘리먼트 노드 찾기
//span[translate(text(), ' ', '')="Click"]
공백 제거하고 문자열 비교하기
//span[starts-with(text(),'Hello')]
Hello로 시작하는 텍스트를 가진 span 엘리먼트 노드 찾기
5. 연산자를 이용해서 조합하여 엘리먼트 찾기
//input[@type="text" and @name="username"]
속성이 type 값이 text이면서 속성 name이 username인 엘리먼트 노트 찾기
//button[@class="btn-primary" or @class="btn-secondary"]
속성 class 값이 btn-primary 이거나 또는 속성 class가 btn-secondary인 엘리먼트 노트 찾기
6. Axis(축)으로 찾기
//div[@class="parent"]/child::p
속성 class 값이 parent인 노드의 자식 노드중 모든 p 엘리먼트 노드 선택
//p[@class="child"]/parent::div
속성 class 값이 child인 노드의 부모 노드중 모든 div 엘리먼트 노드 선택
//li[not(descendant::span[text()='AD'])]
전체 li 엘리먼트중에서 하위 자손들 중 span 태그이면서 text가 'AD'인 엘리먼트를 포함하지 않는 엘리먼트
7. 다수의 엘리먼트에서 한개의 엘리먼트를 지정하기
1)인덱스 번호 : 선택하려는 요소의 인덱스 번호를 지정하세요.
//p[@class='flightsLayoverInfo'][1]
2)position() : 요소의 위치 값을 할당하세요.
//p[@class='flightsLayoverInfo' and position()=1]
(//p[@class='flightsLayoverInfo'])[position()=1]
3)last() : 요소 목록에서 마지막 요소를 선택합니다.
//p[@class='flightsLayoverInfo' and last()]
(//p[@class='flightsLayoverInfo'])[last()-1]
8. 기타 유용한 xpath 사례
//div[@id="form_grdWrsItems_vscrollbar" and not(contains(@style,"display: none;"))]
style attribute의 값에 display: none; 이라는 단어가 포함되지 않은 경우에만 선택하고 아닌 경우는 TimeoutException
'파이썬코드공유' 카테고리의 다른 글
파이썬 셀레니움 파일 드래그 앤 드랍(selenium file drag and drop) (0) | 2023.08.21 |
---|---|
구글 시트 API 연결하기 (0) | 2023.08.07 |
Selenium Waits Explicit Implicit 명시적대기 암묵적대기 (0) | 2023.08.04 |
셀레니움 웹드라이버 close 와 quit 차이점 (0) | 2023.08.04 |
셀레니움 selenium 매크로 탐지 회피 전략 (0) | 2023.08.04 |