본문 바로가기
파이썬

인스타그램 좋아요 봇 만들기 5 : XPath 상대경로

by fecu 2022. 6. 5.
728x90

파이썬 셀레니움으로 인스타그램의 좋아요 버튼을 계속 누르고 있었는데, 인스타그램이 업데이트 될 때 마다 경로를 계속 변경해주어야 한다는 번거로움이 있었다. 그래서 이를 해소하기 위해 XPath를 어떻게 상대경로로 지정해 줄 수 있는지, 그리고 상대경로를 지정할 때의 장점에 대해 글을 써보려고 한다.

1. XPath 절대경로 형식, 그리고 문제점

이때까지 쓴 좋아요 봇의 글들은 모두 XPath를 절대경로로 지정했었다. XPath의 절대 경로의 형식은 아래와 같다.

xpath = /html/body/div[6]/div[3]/div/article/div/div[2]/div/div/div[2]/section[1]/span[1]

위의 경로는 좋아요 버튼의 부모 XPath이다. 문제는 최근 인스타그램의 업데이트가 잦아지면서 XPath가 계속 변한다는 것. 지난번 첫 글을 쓴 후에 2022년 2월, 5월 업데이트를 하였으나, 이번에 6월 업데이트에 또 다시 버튼들의 XPath가 모조리 바뀌면서 한달만에 또 업데이트를 해야하는 상황이 되었다. 이제 이런 상황을 방지하기 위해 XPath를 모두 상대경로로 변경하여 보기로 했다.

2. XPath 상대 경로

XPath의 상대 경로는 아래와 같은 형식을 지닌다.

XPath = //tagname[@atrribute='value']

 

셀레니움 상대경로 절대경로

상대 경로를 이용하면 태그명과 속성, 그리고 속성 이름과 속성 값을 알고 있다면 절대 경로가 변경되어도 값을 쉽게 찾을 수 있다.

셀레니움 상대경로 절대경로1

예를들어 인스타그램의 좋아요 버튼의 절대 경로는 계속 변경되지만, 버튼 내부의 svg 태그 속성 중 aria-label의 속성 값이 '좋아요'라는 속성 값을 가지고 있다는 것은 몇번의 업데이트를 지나도 변하지 않았다. 하지만 '좋아요'의 속성 값을 가진 svg 태그가 클릭을 받아줄 수 없기 때문에, 해당 태그의 부모 태그를 찾고 좋아요 버튼, 버튼의 상태 등을 받아내는 것으로 XPath를 수정해보려고 한다. 

3. XPath 상대 경로의 형식(매서드)

1) 기본 형식

셀레니움 상대경로 절대경로2

아래와 같이 다음 버튼의 XPath를 상대 경로로 지정해보기로 하자. 다음 버튼의 태그네임은 button, 속성 이름은 aria-label이며 속성 값은 '다음'이다. 이를 상대경로로 지정하면 아래와 같다.

XPath = //button[@aria-label='다음']
XPath = //*[@aria-label='다음']

XPath에서 태그네임에 *을 넣어준다면, 이는 모든 태그 네임을 검색하는 것을 뜻한다. 만일 이 버튼을 셀레니움을 이용하여 클릭하고 싶다면, 아래와 같이 코드를 작성할 수 있을 것이다.

driver.find_element_by_xpath('//button[@aria-label="다음"]').click()

 

2) contains(@attribute, 'value 중 일부')

contains()는 속성명 중 값에 해당하는 요소들을 찾아주는 메서드이다. 값의 전체를 넣지 않고 일부만 넣어도 찾아줄 수 있다. 

셀레니움 상대경로 절대경로3

예를들어 네이버 홈페이지에 모바일 버젼으로 접속했을 때, 속성이 media이고 속성 값이 false인 것을 찾아보기로 하자. 그러면 속성값이 media이고, 값이 false인 요소를 찾아준다. find_element_by_xpath는 찾은 요소 중 제일 첫번째 것을 보여주므로, elements를 이용하면 여러개의 요소를 찾을 수도 있다. find_elements_by_xpath를 이용하면 여러개의 요소들을 찾는 것이 가능하고, 리스트 형식으로 선택하는 것도 가능하다.

셀레니움 상대경로 절대경로4

contains(text(),'찾고자 하는 텍스트')를 활용하면 원하는 텍스트를 포함한 요소를 찾는 것도 가능하다. 

셀레니움 상대경로 절대경로5

3) and, or 

and와 or은 기본 프로그램 명령어와 같다. 원하는 요소를 모두 포함하려면 and, 둘중 하나만 포함하려면 or을 쓰면 된다. 

셀레니움 상대경로 절대경로7

예를들어 xpath를 이용하여 '다음' 버튼을 찾으려는데, 내부 속성값에 '다음'을 가진 버튼이 총 3개가 있을 때 and를 이용할 수 있다. 내가 누르고자 하는 버튼의 내부 속성에만 height = "16"이라는 값이 있을 경우, 이 버튼의 xpath를 찾고 누르는 코드를 만들어본다면 아래와 같을 것이다.

driver.find_element_by_xpath('//*[@aria-label="다음" and @height="16"]').click()

위와 같이 코딩할 경우, 셀레니움은 aria-label의 값이 '다음'이고 height 값이 '16'인 것을 클릭하게 될 것이다.

4) starts-with(@attribute, 'value')

셀레니움 상대경로 절대경로9

starts-with(@attribute, "value") 메서드는 속성 값 중 같은 값으로 시작하는 요소들을 찾아준다. 위와 같이 input 태그 중 aria-label이 '전화번호'의 값을 가진 태그를 클릭하자 아이디 입력칸에서 커서가 깜박인다. 패스워드 칸을 상대 경로로 인식해주고 싶다면, aria-label 값을 '비밀번호'로 입력해주면 될 것이다.

5) text() = 'value'

셀레니움 상대경로 절대경로10

text()메서드는 원하는 값이 있는 텍스트 요소를 찾아준다. xpath에서 '비밀번호를 잊으셨나요?' 라는 텍스트를 찾아 클릭하도록 하니 새롭게 로그인을 할 수 있는 페이지로 들어왔다. 

728x90

6) 계층 메서드

웹의 구조에서 div, span 등 계층적 구조의 내부나 외부에서 찾고자 하는 요소들을 찾아주는 기능이다.

(1) 자손 선택자

셀레니움 상대경로 절대경로11

찾고자 하는 태그 내에서의 태그네임을 찾을수 있다. 위의 식에선 h1태그 중 class 네임이 "sch_logo"인 것을 찾고, 그 안에서도 input을 받는 태그를 클릭하도록 구현해 보았다. 자손의 xpath를 찾기 위한 정규식은 아래와 같다.

XPATH = //tagname[@attribute='value'] // following::tagname

(2) 조상 선택자

셀레니움 상대경로 절대경로12

인스타그램의 좋아요 버튼을 누를 때, aria-label이 '좋아요' 혹은 '좋아요 취소'인 태그의 상위 태그를 찾아야 했다. 이를 구현하기 위한 코드는 아래와 같다.

div = driver.find_element_by_xpath('//*[@aria-label="좋아요" or @aria-label="좋아요 취소"]//ancestor :: span[2]')

자손 선택자에선 following을, 조상 선택자에선 ancestor을 넣어주면 된다. 맨 마지막에 리스트에서의 순서와 같이 [숫자]를 넣으면 자손 혹은 조상 선택자를 순차적으로 선택할 수 있다.

4. 결론 : 상대 경로를 이용해야 하는 이유

위의 내용과 같이 절대 경로를 이용하여 셀레니움을 운영하는 경우, 웹 사이트의 변경사항에 따라 매번 코드를 바꿔주어야 한다. 하지만 상대 경로의 경우 웹 사이트의 전체적인 구조가 변하지 않는 이상, 몇 가지의 포인트를 가지고 원하는 태그의 XPath를 찾아낼 수 있다. 따라서 업데이트를 해 주어야 할 주기도 줄어들게 된다. 이제 앞으로의 좋아요 봇의 글은 모두 상대 경로를 이용해 주려고 한다. 다음 글에서는 상대경로를 이용하여 이때까지 쓴 글들을 모두 한꺼번에 정리해볼 것이다.

728x90