Selenium 02 : 셀레니움 요소 찾기 find_element By 사용법 (find_element_by_ 안됨)

728x90

Selenium 02 : 셀레니움 요소 찾기 find_element By 사용법

 

https://m-flight.naver.com/

 

네이버 항공권

설레는 여행의 시작. 네이버 항공권과 함께!

m-flight.naver.com

네이버 항공권 사이트에서 자동으로 필요한 표를 예매하려고 한다.

find_element를 활용하여 기능을 구현할 수 있다.

 

from selenium import webdriver

bro = webdriver.Chrome()
bro.maximize_window() # 창 최대화
url = "https://m-flight.naver.com/flights/"
bro.get(url)

위의 코드를 입력하고 빌드하면 크롬에서 네이버 항공권 사이트가 자동으로 열리게 될 것이다.

 

 

웹 페이지에서 내가 필요한 부분을 선택하는 방법에는 여러가지가 있다.

먼저 내가 여행을 가는 날과 오는 날에 대해 자동으로 선택하려고 한다고 가정하자.

 

f12 버튼을 누르면 크롬의 개발자 도구 탭이 나타난다. 위의 버튼을 클릭하고

선택하려는 요소를 클릭하면

선택한 요소에 해당하는 html코드가 자동으로 나타날 것이다.

저 요소에 해당하는 고유 클래스값을 찾아내는 방법으로 크롬에서 네이버 항공권 사이트가 열렸을 때 가는 날 버튼까지 자동으로 클릭되는 기능을 만들어 보겠다.

(2022. 06월을 기준으로 기존의 find_element_by_... 의 방법으로 요소를 찾는 방법은 아래의 방법으로 대체 되었다.)

 

from selenium import webdriver
from selenium.webdriver.common.by import By

bro = webdriver.Chrome()
bro.maximize_window() # 창을 최대화 시키고 싶으면 필요한 코드
url = "https://m-flight.naver.com/"
bro.get(url)
bro.find_element(By.CLASS_NAME, "tabContent_option__2y4c6.select_Date__1aF7Y").click()

find_element(By.CLASS_NAME, "클래스 이름")을 사용하면 클래스 이름과 일치하는 요소를 찾아낸다.

모든 요소가 클래스 이름을 가지고 있는 것은 아니기 때문에 이것 말고도 다양한 방법으로 필요한 요소를 찾아낼 수 있다.

 

위의 코드를 빌드하면 이런 창이 열릴 것이다.

나는 9월 27일에 출발하여 10월 28일에 돌아오는 여행권을 사려고 한다고 가정하겠다.

이번에는 클래스 이름을 이용하지 않고, 웹 사이트에 있는 요소들 중에 27이라는 글자가 있는 요소만 선택하려고 한다.

 

find_element(By.XPATH, "XPATH 값")

XPATH 값과 일치하는 요소를 찾는다.

모든 요소는 고유의 XPATH를 가지고 있다. 요소의 XPATH값은 다음과 같은 방법으로 찾을 수 있다.

따라서 bro.find_element(By.XPATH, "XPATH 값")과 같은 방법으로 원하는 요소를 찾을 수 있을 것이다.

뿐만아니라 다음과 같은 방법을 활용하면 특정 텍스트가 포함된 요소를 찾아낼 수도 있다.

 

bro.find_elements(By.XPATH, "//*[contains(text(), '텍스트')]")

elements는 찾고자 하는 조건에 해당하는 복수의 요소를 검색한다.

//*는 모든 태그를 대상으로 검색한다.

만약 b 태그만을 대상으로 한다면 //b라고 쓰면된다.

 

아래의 코드를 보자.

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

bro = webdriver.Chrome()
bro.maximize_window() # 창을 최대화 시키고 싶으면 필요한 코드
url = "https://m-flight.naver.com/"
bro.get(url)
bro.find_element(By.CLASS_NAME, "tabContent_option__2y4c6.select_Date__1aF7Y").click()

time.sleep(2)
elem = bro.find_elements(By.XPATH, "//b[contains(text(), '27')]")
for e in elem:
    print(e)

 

날짜를 선택하는 창이 완전히 나타난 후에 다음 동작이 실시되어야 에러가 발생하지 않으므로 일부로 2초간 대기하도록 코드를 추가했다. 

캘린더가 나타나면 27이라는 텍스트가 포함된 모든 태그의 요소들을 elem라는 이름의 리스트에 할당된다.

그리고 그 요소들을 반복문으로 출력하면 다음과 같은 값이 나타난다.

22년 09월 ~ 23년 09월에 모두 27이라는 날짜가 존재하기 때문에 복수의 값이 리스트로 할당된 것이다.

나는 22년 09월 27일에 해당하는 버튼만 클릭하면 되기 때문에 다음과 같이 코드를 수정하였다.

 

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

bro = webdriver.Chrome()
bro.maximize_window() # 창을 최대화 시키고 싶으면 필요한 코드
url = "https://m-flight.naver.com/"
bro.get(url)
bro.find_element(By.CLASS_NAME, "tabContent_option__2y4c6.select_Date__1aF7Y").click()

time.sleep(2)
bro.find_elements(By.XPATH, "//b[contains(text(), '27')]")[0].click()

그리고 빌드하면 캘린더가 나타나고 2초 뒤에 필요했던 날짜만 클릭하는 것을 확인할 수 있을 것이다.

(리스트의 0번째 값은 현재 날짜를 기준으로 하기 때문에 1번째 값으로 했다면 10월 27일이 선택될 것이다.)

따라서 다음과 같이 코드를 작성하면 22년 9월 27일을 가는 날로, 22년 10월 28일을 오는 날로 선택할 수 있다.

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

bro = webdriver.Chrome()
bro.maximize_window() # 창을 최대화 시키고 싶으면 필요한 코드
url = "https://m-flight.naver.com/"
bro.get(url)
bro.find_element(By.CLASS_NAME, "tabContent_option__2y4c6.select_Date__1aF7Y").click()

time.sleep(2)
bro.find_elements(By.XPATH, "//b[contains(text(), '27')]")[0].click()
bro.find_elements(By.XPATH, "//b[contains(text(), '28')]")[1].click()

 

아래 코드는 위의 방법들을 활용하여 부산에서 제주도까지의 항공편을 검색하는 코드이다.

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

bro = webdriver.Chrome()
bro.maximize_window() # 창을 최대화 시키고 싶으면 필요한 코드
url = "https://m-flight.naver.com/"
bro.get(url)
bro.find_element(By.CLASS_NAME, "tabContent_option__2y4c6.select_Date__1aF7Y").click()

time.sleep(2)
bro.find_elements(By.XPATH, "//b[contains(text(), '27')]")[0].click()
bro.find_elements(By.XPATH, "//b[contains(text(), '28')]")[1].click()

bro.find_element(By.XPATH, "//*[@id='__next']/div/div[1]/div[4]/div/div/div[2]/div[1]/button[1]").click()
time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), '국내')]").click()
time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), 'PUS')]").click()

time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), '도착')]").click()
time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), '국내')]").click()
time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), 'CJU')]").click()
time.sleep(1)
bro.find_element(By.XPATH, "//*[contains(text(), '항공권 검색')]").click()

time.sleep(1)으로 1초씩 텀을 둔 이유는 다음 화면이 나타나기도 전에 다음 코드가 동작하는 것을 방지하기 위해서이다.

 

728x90