본문 바로가기
파이썬코드공유

셀레니움 find_element XPath 완벽 해설

by 하이어시스템 2023. 8. 4.
반응형

XPath의 활용

하이어시스템 소개

 

하이어시스템 소개 feat.김프로

소개 안녕하세요, 저는 하이어시스템의 김프로입니다. 여러분들이 어려움을 겪고 계신 일상 업무를 저의 안정적이고 빠른 소프트웨어로 자동화하는 것, 그것이 저의 목표입니다. '하이어시스템

wise-office-worker.tistory.com

 

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

반응형