- Selenium을 활용한 네이버 항공권 크롤링 -

 

 

 

<개발 목적>

폴리텍 하이테크 AI Engineering 과정 중 짝꿍 한명이 매주 제주도를 가야만 했다.

그래서 주말이 다가올때쯤이면 매번 항공권을 예매하기 위해 가격을 비교하고 있었다.

매주 비행기표를 예매해야만 했기에 값 비싼 비행기표를 예매하는 것은 부담이라고 했다.

그래서 나는 값이 싼 항공권 정보를 자동으로 찾아주는 코드를 구현하여 도움을 주고 싶었다.

짝꿍이 원하는 항공권 정보의 priority 는 다음과 같았다.

 

1. 짝꿍이 원하는 시간

2. 그 시간대에서의 싼 가격대의 항공권

3. 항공사는 중요하지 않음

 

사실 네이버 항공권 사이트에 이러한 기능이 다 있지만, 

웹 크롤링과 파이썬 리스트 정렬을 활용하여 직접 구현해보고 싶었다.

 

 

 

<개요>

1. 크롬 드라이버를 통해 네이버 항공권 예매 사이트 접속

2. userInput을 통해 원하는 날짜 및 시간 선택

3. 항공권 데이터를 크롤링하여 리스트에 저장

4. 데이터 전처리 후 원하는 데이터만 출력

 

 

 

# Selenium 

셀레니움은 파이어폭스, 인터넷 익스플로어, 크롬등과 같은 브라우저를 컨트롤 할 수 있게 해주는 프레임워크

 

 

# Crawling

웹 페이지를 그대로 가져와서 거기서 데이터를 추출해 내는 행위

 

 

<코드 설명>

from selenium import webdriver
import time

필요한 라이브러리 import

 

 

# 스크롤 다운 함수
def scroll_down():
    SCROLL_PAUSE_SEC = 1
    # 스크롤 높이 가져옴
    last_height = driver.execute_script("return document.body.scrollHeight")

    while True:
        # 끝까지 스크롤 다운
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

        # 1초 대기
        time.sleep(SCROLL_PAUSE_SEC)

        # 스크롤 다운 후 스크롤 높이 다시 가져옴
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break
        last_height = new_height

웹 페이지 특성 상 스크롤 다운을 해야 모든 정보 크롤링 가능하므로 스크롤 다운 함수 정의

-> 항공권 데이터 크롤링 하기 전에 사용할 것임.

 

 

# 네이버 항공권 사이트 접속
driver = webdriver.Chrome('./chromedriver.exe')
driver.get('https://flight.naver.com/flights/?'
           'trip=OW&scity1=TAE&ecity1=CJU&adult=1&child=0&infant=0&fareTy'
           'pe=YC&airlineCode=&nxQuery=%ED%95%AD%EA%B3%B5%EA%B6%8C')

selenium webdriver를 통해 크롬 드라이버를 실행 및 웹 페이지 접속

 

 

# 날짜 선택란 클릭
driver.find_element_by_xpath("/html/body/div/div/div[2]/div[1]/fieldset/div[2]/div[1]/div/div[1]/a").click()
time.sleep(1)

# 날짜 선택 - input 형식으로 숫자를 받아서 html 주소에 숫자를 넣을 것임.
# 월 선택
months = ['이번 달', '다음 달']
for i, month in enumerate(months):
    print(f'{i + 1}. {month}\t', end='\t')
print()
monthInput = int(input("몇월에 떠나시나요? : "))
print()

# 주 선택
weeks = ['첫째 주', '둘째 주', '셋째 주', '넷째 주', '다섯째 주', '여섯째 주']
for i, week in enumerate(weeks):
    print(f'{i + 1}. {week}\t', end='\t')
print()
weekInput = int(input("몇째 주에 떠나시나요? : "))
print()

# 요일 선택
days = ['일', '월', '화', '수', '목', '금', '토']
for i, day in enumerate(days):
    print(f'{i + 1}. {day}\t', end='\t')
print()
dayInput = int(input("무슨 요일에 떠나시나요? : "))
print()

# 지정한 날짜 선택하기 - input 을 통해 원하는 html 주소 (날짜 선택) 를 클릭.
driver.find_element_by_xpath(f"/html/body/div/div/div[2]/div[1]/"
                             f"fieldset/div[2]/div[1]/div/div[3]/"
                             f"div/div[2]/div[1]/div/div[{monthInput}]/"
                             f"div[2]/table/tbody/tr[{weekInput}]/td[{dayInput}]/a").click()


# 항공권 검색 클릭
driver.find_element_by_xpath("/html/body/div/div/div[2]/div[1]/fieldset/a").click()
time.sleep(4)

원하는 날짜 선택 -> 웹 페이지 상의 table 정보를 가져와서 선택 (개발자 도구 (F12) 를 활용하여 코드를 읽을 수 있음)

 

날짜 선택 코드 실행 -&gt; 보기에 맞춰서 userInput을 입력

 

 

# 출발 시간항목 지정
departure_time = ['전체', '00:00 ~ 06:00', '06:00 ~ 09:00', '09:00 ~ 12:00',
                  '12:00 ~ 15:00', '15:00 ~ 18:00', '18:00 ~ 24:00']

for i, d_time in enumerate(departure_time):
    print(f"{i + 1}. {d_time}", end='\t')

print()
timeInput = int(input("출발 시간을 선택하세요 : "))
print()

# 출발 시간 선택
driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]/div/div[2]/ul/li[2]/a/span[1]").click()
if timeInput == 1:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[1]/span").click()
    # 시간항목이 전체일 경우 : 스크롤 다운 함수 실행
    scroll_down()

elif timeInput == 2:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[2]/span").click()
elif timeInput == 3:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[3]/span").click()
elif timeInput == 4:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[4]/span").click()
elif timeInput == 5:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[5]/span").click()
elif timeInput == 6:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[6]/span").click()
elif timeInput == 7:
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                 "/div/div[2]/ul/li[2]/div/ul/li[7]/span").click()

원하는 시간 선택 -> 날짜 선택과 비슷한 개념

시간 선택이 '전체'일 경우 모든 데이터를 보기 위해 스크롤 다운 함수 실행

 

시간 선택

 

 

# 전체 flight 정보들
flights = driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]/div/div[4]")

# 텍스트 형태로 info 에 저장
info = flights.text

# 띄어쓰기로 스플릿한 것들을 flight list 에 저장
flight_list = info.split()

데이터를 text 형태로 스플릿하여 리스트에 저장

 

['티웨이항공', '출발지', 'TAE', '12:20', '도착지', 'CJU', '13:20', '총', '소요시간', '01시간', '00분', '할인석', '편도', '34,400원', '편도', '32,556원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '티웨이항공', '출발지', 'TAE', '12:20', '도착지', 'CJU', '13:20', '총', '소요시간', '01시간', '00분', '일반석', '편도', '78,500원', '편도', '76,215원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '아시아나항공', '출발지', 'TAE', '13:25', '도착지', 'CJU', '14:30', '총', '소요시간', '01시간', '05분', '특가석', '편도', '35,400원', '편도', '33,546원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '아시아나항공', '출발지', 'TAE', '13:25', '도착지', 'CJU', '14:30', '총', '소요시간', '01시간', '05분', '할인석', '편도', '46,400원', '편도', '44,436원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '아시아나항공', '출발지', 'TAE', '13:25', '도착지', 'CJU', '14:30', '총', '소요시간', '01시간', '05분', '일반석', '편도', '83,400원', '편도', '81,066원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '제주항공', '출발지', 'TAE', '13:40', '도착지', 'CJU', '14:50', '총', '소요시간', '01시간', '10분', '할인석', '편도', '27,300원', '편도', '27,040원', '(KB국민카드', '결제시', '1%', '청구할인)', '성인이벤트혜택', '제주항공', '출발지', 'TAE', '13:40', '도착지', 'CJU', '14:50', '총', '소요시간', '01시간', '10분', '일반석', '편도', '76,400원', '편도', '75,650원', '(KB국민카드', '결제시', '1%', '청구할인)', '성인이벤트혜택', '진에어', '출발지', 'TAE', '13:45', '도착지', 'CJU', '14:50', '총', '소요시간', '01시간', '05분', '특가석', '편도', '29,200원', '편도', '27,408원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '진에어', '출발지', 'TAE', '13:45', '도착지', 'CJU', '14:50', '총', '소요시간', '01시간', '05분', '할인석', '편도', '33,700원', '편도', '31,863원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '진에어', '출발지', 'TAE', '13:45', '도착지', 'CJU', '14:50', '총', '소요시간', '01시간', '05분', '일반석', '편도', '77,400원', '편도', '75,126원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '진에어', '출발지', 'TAE', '14:55', '도착지', 'CJU', '15:55', '총', '소요시간', '01시간', '00분', '특가석', '편도', '21,200원', '편도', '19,488원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '진에어', '출발지', 'TAE', '14:55', '도착지', 'CJU', '15:55', '총', '소요시간', '01시간', '00분', '할인석', '편도', '35,200원', '편도', '33,348원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립', '진에어', '출발지', 'TAE', '14:55', '도착지', 'CJU', '15:55', '총', '소요시간', '01시간', '00분', '일반석', '편도', '77,400원', '편도', '75,126원', '(네이버페이', '결제시', '1%+1,500원', '적립)', '성인이벤트혜택', '1%', '적립']

↑↑

print(flight_list)

 

 

price_list = []

print("<< 시간 순 >>")

# 항공사, 출발 시각, 가격 -> 내가 필요한 정보만 추출하기 위한 슬라이싱
for i in range(len(flight_list)-1):

    if flight_list[i] == '제주항공':
        # 항공사 / 출발 시간 / 가격 출력력
        print(f'{flight_list[i]}\t\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
        price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

    elif flight_list[i] =='티웨이항공':
        print(f'{flight_list[i]}\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
        price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

    elif flight_list[i] == '진에어':
        print(f'{flight_list[i]}\t\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
        price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

    elif flight_list[i] == '아시아나항공':
        print(f'{flight_list[i]}\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
        price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

원하는 데이터만 출력하기위해 리스트의 규칙성을 이용해 슬라이싱 진행

가격순으로 정렬하기 위해 새로운 리스트에 데이터 추가

 

 

for i in price_list:
    # price_list 속 가격을 int 화 시키기
    str_price = i[2]
    price = str_price[:-1]
    price = int(price.replace(',', ''))

    # int 화 시킨 가격으로 리스트 다시 작성
    i.insert(0, price)

sort_price_list = sorted(price_list)

print("<< 가격 낮은 순 >>")
for i in sort_price_list:
    if i[1] == '제주항공':
        print(f'{i[1]}\t\t\t{i[2]}\t\t{i[3]}')
        
    elif i[1] == '티웨이항공':
        print(f'{i[1]}\t\t{i[2]}\t\t{i[3]}')
        
    elif i[1] == '진에어':
        print(f'{i[1]}\t\t\t{i[2]}\t\t{i[3]}')
        
    elif i[1] == '아시아나항공':
        print(f'{i[1]}\t\t{i[2]}\t\t{i[3]}')

driver.close()

리스트 안의 데이터를 가격순으로 정렬후 출력

드라이버 종료

 

[[21200, '진에어', '14:55', '21,200원'], [27300, '제주항공', '13:40', '27,300원'], 

[29200, '진에어', '13:45', '29,200원'], [33700, '진에어', '13:45', '33,700원'], 

[34400, '티웨이항공', '12:20', '34,400원'], [35200, '진에어', '14:55', '35,200원'], 

[35400, '아시아나항공', '13:25', '35,400원'], [46400, '아시아나항공', '13:25', '46,400원'], 

[76400, '제주항공', '13:40', '76,400원'], [77400, '진에어', '13:45', '77,400원'], 

[77400, '진에어', '14:55', '77,400원'], [78500, '티웨이항공', '12:20', '78,500원'], 

[83400, '아시아나항공', '13:25', '83,400원']]

↑↑

print(sort_price_list)

 

 

 

<전체 코드>

from selenium import webdriver
import time

# 스크롤 다운 함수
def scroll_down():
    SCROLL_PAUSE_SEC = 1
    # 스크롤 높이 가져옴
    last_height = driver.execute_script("return document.body.scrollHeight")

    while True:
        # 끝까지 스크롤 다운
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

        # 1초 대기
        time.sleep(SCROLL_PAUSE_SEC)

        # 스크롤 다운 후 스크롤 높이 다시 가져옴
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break
        last_height = new_height


if __name__ == '__main__':
    # 네이버 항공권 사이트 접속
    driver = webdriver.Chrome('./chromedriver.exe')
    driver.get('https://flight.naver.com/flights/?'
               'trip=OW&scity1=TAE&ecity1=CJU&adult=1&child=0&infant=0&fareTy'
               'pe=YC&airlineCode=&nxQuery=%ED%95%AD%EA%B3%B5%EA%B6%8C')

    # 날짜 선택란 클릭
    driver.find_element_by_xpath("/html/body/div/div/div[2]/div[1]/fieldset/div[2]/div[1]/div/div[1]/a").click()
    time.sleep(1)

    # 날짜 선택 - input 형식으로 숫자를 받아서 html 주소에 숫자를 넣을 것임.
    # 월 선택
    months = ['이번 달', '다음 달']
    for i, month in enumerate(months):
        print(f'{i + 1}. {month}\t', end='\t')
    print()
    monthInput = int(input("몇월에 떠나시나요? : "))
    print()

    # 주 선택
    weeks = ['첫째 주', '둘째 주', '셋째 주', '넷째 주', '다섯째 주', '여섯째 주']
    for i, week in enumerate(weeks):
        print(f'{i + 1}. {week}\t', end='\t')
    print()
    weekInput = int(input("몇째 주에 떠나시나요? : "))
    print()

    # 요일 선택
    days = ['일', '월', '화', '수', '목', '금', '토']
    for i, day in enumerate(days):
        print(f'{i + 1}. {day}\t', end='\t')
    print()
    dayInput = int(input("무슨 요일에 떠나시나요? : "))
    print()

    # 지정한 날짜 선택하기 - input 을 통해 원하는 html 주소 (날짜 선택) 를 클릭.
    driver.find_element_by_xpath(f"/html/body/div/div/div[2]/div[1]/"
                                 f"fieldset/div[2]/div[1]/div/div[3]/"
                                 f"div/div[2]/div[1]/div/div[{monthInput}]/"
                                 f"div[2]/table/tbody/tr[{weekInput}]/td[{dayInput}]/a").click()


    # 항공권 검색 클릭
    driver.find_element_by_xpath("/html/body/div/div/div[2]/div[1]/fieldset/a").click()
    time.sleep(4)

    # 출발 시간항목 지정
    departure_time = ['전체', '00:00 ~ 06:00', '06:00 ~ 09:00', '09:00 ~ 12:00',
                      '12:00 ~ 15:00', '15:00 ~ 18:00', '18:00 ~ 24:00']

    for i, d_time in enumerate(departure_time):
        print(f"{i + 1}. {d_time}", end='\t')

    print()
    timeInput = int(input("출발 시간을 선택하세요 : "))
    print()

    # 출발 시간 선택
    driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]/div/div[2]/ul/li[2]/a/span[1]").click()
    if timeInput == 1:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[1]/span").click()
        # 시간항목이 전체일 경우 : 스크롤 다운 함수 실행
        scroll_down()

    elif timeInput == 2:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[2]/span").click()
    elif timeInput == 3:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[3]/span").click()
    elif timeInput == 4:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[4]/span").click()
    elif timeInput == 5:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[5]/span").click()
    elif timeInput == 6:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[6]/span").click()
    elif timeInput == 7:
        driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]"
                                     "/div/div[2]/ul/li[2]/div/ul/li[7]/span").click()


    flights = driver.find_element_by_xpath("/html/body/div/div/div[1]/div[2]/div[2]/div/div[4]")
    info = flights.text  
    flight_list = info.split()
    print(flight_list)

    price_list = []

    print()
    print("<< 시간 순 >>")
    # 항공사, 출발 시각, 가격 -> 내가 필요한 정보만 추출하기 위한 슬라이싱
    for i in range(len(flight_list)-1):

        if flight_list[i] == '제주항공':
            # 항공사 / 출발 시간 / 가격 출력력
            print(f'{flight_list[i]}\t\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
            price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

        elif flight_list[i] =='티웨이항공':
            print(f'{flight_list[i]}\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
            price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

        elif flight_list[i] == '진에어':
            print(f'{flight_list[i]}\t\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
            price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

        elif flight_list[i] == '아시아나항공':
            print(f'{flight_list[i]}\t\t{flight_list[i + 3]}\t\t{flight_list[i + 13]}')
            price_list.append([flight_list[i], flight_list[i + 3], flight_list[i + 13]])

    print()

    for i in price_list:
        # price_list 속 가격을 int 화 시키기
        str_price = i[2]
        price = str_price[:-1]
        price = int(price.replace(',', ''))

        # int 화 시킨 가격으로 리스트 다시 작성
        i.insert(0, price)

    sort_price_list = sorted(price_list)

    print()
    print("<< 가격 낮은 순 >>")
    for i in sort_price_list:
        # print(i)
        if i[1] == '제주항공':
            print(f'{i[1]}\t\t\t{i[2]}\t\t{i[3]}')
        elif i[1] == '티웨이항공':
            print(f'{i[1]}\t\t{i[2]}\t\t{i[3]}')
        elif i[1] == '진에어':
            print(f'{i[1]}\t\t\t{i[2]}\t\t{i[3]}')
        elif i[1] == '아시아나항공':
            print(f'{i[1]}\t\t{i[2]}\t\t{i[3]}')

    driver.close()

 

 

 

<실행 화면>

코드 실행

 

 

 

 

- Just Do It -

 

반응형

'Python > Web_crawling' 카테고리의 다른 글

[Python] 식단정보 크롤링  (2) 2021.06.20
복사했습니다!