본문 바로가기
VBA/엑사남_심화방

[심화방] VBA_심화_100제 #14 [ 셀레니움 네이버항공 조회]

by 일등미노왕국 2023. 4. 1.

셀레니움으로 항공권을 조회하는 것을 해보려한다.

더 섬세하게 만들수도 있겠지만, 만들면서 생각해봐도 조회하는 정도 밖에는 쓸모가 없을 것 같아서 딱 그정도로 구현을 가능하게 하였다.

 

위와 같이 크롤링 되는 모습이 화면에 보이도록 창의 위치과 엑셀 창의 크기를 조절하는 코드이다.

Application.WindowState = xlNormal          '= 창의 위치와 크기 조정
Application.Top = 0
Application.Left = 0
Application.Width = 730
Application.Height = 1080

strUrl = "https://flight.naver.com/"            '= 항공권 예매


Sel.Start "chrome"                                                 
Sel.Window.SetPosition 960, 0                                      
Sel.Get strUrl

출발지를 입력하게 되면 아래와 같이 연관된 공항들이 나오게 되는데 출발지가 입력된 첫 위치값을 클릭하는 코드는 다음과 같다.

Sel.FindElementsByCss(".select_code__d6PLz")(1).Click                 '= 출발지 선택
    
Sel.FindElementByCss(".autocomplete_input__1vVkF").SendKeys Fromstr   '= 출발지 입력

If InStr(Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Text, Fromstr) > 0 Then

    Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Click    '= 항공사에 출발지가 포함되어 있으면 선택
End If

다음은 출발날짜를 선택하는 코드인데 이게 좀 난이도가 있었는데, CssSelector가 아닌 Xpath로 포함된 텍스트 값으로 해결하는 코드는 다음 번에 올려보도록 하겠다.

Sel.FindElementByCss(".tabContent_option__2y4c6").Click  '= 출발날짜 클릭
    
Sel.Wait 500
Haja_go FromMonthstr, FromDaystr                 '= 출발 월 / 출발 일을 Haja_go 매개변수로 전달

----------------------------------------------------------------------------------------
Function Haja_go(Monthstr$, Daystr$)

    Dim Cal As Object, Ca As Object, Tr As Object, Td As Object
    
    Set Cal = Sel.FindElementsByCss(".awesome-calendar > div.month")         '= 달력을 Cal변수에 담고

        For Each Ca In Cal                                                   '= 각 월을 순환
    
        If Ca.FindElementByCss(".dCaTmH").Text = Monthstr Then               '= 출발월과 같으면
       
            For Each Tr In Ca.FindElementsByCss("table > tbody > tr")        '= 여행일자를 주 단위로 순환
                     
                For Each Td In Tr.FindElementsByCss("td.day")                '= 여행의 주단위순환에서 일단위 순환
                
                If Td.Text <> "" Then                                        '= 달력에서 일자가 표현이 되었다면

                    If Td.FindElementByCss("button > b").Text = Daystr Then  '= 해당일자와 출발일자가 같은지 판별
                       Td.FindElementByCss("button > b").Click               '= 해당일자 클릭
                        
                    Exit Function
                    End If
            
                End If
                Next Td
            Next Tr
            
        End If
    
    Next Ca

End Function

이렇게 항공표를 검색하면 웹방식 특성상 끝까지가 아닌 중간에 끊겨서 데이터를 가져오게 되는데, 다음 코드로 해결이 가능하다. 현재 스크롤의 위치값을 prev_height에 담고, 스크롤을 화면 크기만큼 이동시켜서 [ 실행할 코드를 실행] 하고 이동한 스크롤의 위치를 current_height에 담는다..그리고 이전위치와 현재위치를 비교하여 다르면 Do문을 실행하고 같다면 더이상 이동할 스크롤값이 없으므로 Do문을 탈출하게 된다.

prev_height = Sel.ExecuteScript("return document. body.scrollHeight") 

Do
    Sel.ExecuteScript ("window.scrollTo(0, document.body.scrollHeight);")
    
    * 실행할 코드
    
    current_height = Sel.ExecuteScript("return document. body.scrollHeight") 

    If prev_height = current_height Then                                    
    
        Exit Do                                                             
        
    Else
    
        prev_height = current_height                                       
        
    End If
    
Loop

 

더보기
Sub Flight_naver()

    Dim strUrl$
    Dim Fromstr$: Fromstr = [b6]                    '= 출발
    Dim Tostr$: Tostr = [b7]                        '= 도착
    Dim FromMonthstr$: FromMonthstr = Format(Left([b5], 7), "yyyy.mm.") '= 출발년월(yyyy.mm.)
    Dim FromDaystr$: FromDaystr = Format([b5], "d") '= 출발일
    Dim node As Object
    Dim prev_height&, current_height&               '= 스크롤 위치
    Dim rngX As Range: Set rngX = [d9]              '= 출력위치
    
    Columns("d:g").Clear                            '= 초기화
    
    Application.Wait Now + TimeValue("0:00:02")     '= 2초지연
    
    Application.ScreenUpdating = False
    
        Application.WindowState = xlNormal          '= 창의 위치와 크기 조정
        Application.Top = 0
        Application.Left = 0
        Application.Width = 730
        Application.Height = 1080

    strUrl = "https://flight.naver.com/"            '= 항공권 예매

   ' Sel.AddArgument "--headless"                                       '= 헤드리스모드
    Sel.Start "chrome"                                                  '= 크롬으로 진행
    Sel.Window.SetPosition 960, 0                                       '= 크롬창 이동
    Sel.Get strUrl                                                      '= Url
    
    Sel.FindElementByCss("button[title='닫기']").Click                  '= 팝업 닫기
    
    Sel.FindElementsByCss("div.searchBox_tablist__1uWMk > button")(2).Click '= 편도 예약
    
    
    Sel.FindElementsByCss(".select_code__d6PLz")(1).Click                 '= 출발지 선택
    
    Sel.FindElementByCss(".autocomplete_input__1vVkF").SendKeys Fromstr   '= 출발지 입력
    
    If InStr(Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Text, Fromstr) > 0 Then
    
        Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Click    '= 항공사에 출발지가 포함되어 있으면 선택
    End If
    
    Sel.FindElementsByCss(".select_code__d6PLz")(2).Click                 '= 도착지 선택
    
    Sel.FindElementByCss(".autocomplete_input__1vVkF").SendKeys Tostr     '= 도착지 입력
    
    If InStr(Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Text, Tostr) > 0 Then
    
        Sel.FindElementByCss(".autocomplete_search_item__2WRSw").Click    '= 항공사에 도착지가 포함되어 있으면 선택
        
    End If
    
    Sel.FindElementByCss(".tabContent_option__2y4c6").Click               '= 출발날짜 클릭
    
    Sel.Wait 500
    Haja_go FromMonthstr, FromDaystr                                      '= 출발 월 / 출발 일을 Haja_go 매개변수로 전달
    
    'Sel.Wait 500
   ' Haja_go ToMonthstr, ToDaystr
    
    Sel.FindElementByCss(".searchBox_txt__3RoCw").Click                   '= 항공권 검색
    
    Sel.Wait 5000                                                         '= 5초 대기
  
    prev_height = Sel.ExecuteScript("return document. body.scrollHeight") '= 현재 스크롤 위치

Do
    Sel.ExecuteScript ("window.scrollTo(0, document.body.scrollHeight);") '= 현재 화면의 크기 만큼 스크롤 이동
    
    For Each node In Sel.FindElementsByCss(".domestic_Flight__sK0eA")
    
        rngX(1, 1) = node.FindElementByCss(".airline").Text               '= 항공사
        rngX(1, 2) = node.FindElementByCss(".info").Text                  '= 이벤트
        rngX(1, 3) = Replace(node.FindElementByCss(".route_Route__2UInh").Text, Chr(10), "  /  ")  '= 비행시간
        rngX(1, 4) = node.FindElementByCss(".domestic_prices__3N88F").Text '= 항공권 가격
        
        Set rngX = rngX.Offset(1)

    Next node
    
    current_height = Sel.ExecuteScript("return document. body.scrollHeight") '= 이동된 스크롤의 위치를 저장

    If prev_height = current_height Then                                     '= 처음 위치와 변동 위치가 같으면 / 변화가 없으면
    
        Exit Do                                                              '= Do 탈출
        
    Else
    
        prev_height = current_height                                         '= 현재위치를 prev_height 변수에 담아라
        
    End If
    
Loop
       
   Application.ScreenUpdating = False
   Haja_Format
   
   Sel.FindElementByCss(".jsx-1527821584.as_top").Click                      '= 맨위로 버튼 클릭
    
End Sub

Function Haja_go(Monthstr$, Daystr$)

    Dim Cal As Object, Ca As Object, Tr As Object, Td As Object
    
    Set Cal = Sel.FindElementsByCss(".awesome-calendar > div.month")         '= 달력을 Cal변수에 담고

        For Each Ca In Cal                                                   '= 각 월을 순환
    
        If Ca.FindElementByCss(".dCaTmH").Text = Monthstr Then               '= 출발월과 같으면
       
            For Each Tr In Ca.FindElementsByCss("table > tbody > tr")        '= 여행일자를 주 단위로 순환
                     
                For Each Td In Tr.FindElementsByCss("td.day")                '= 여행의 주단위순환에서 일단위 순환
                
                If Td.Text <> "" Then                                        '= 달력에서 일자가 표현이 되었다면

                    If Td.FindElementByCss("button > b").Text = Daystr Then  '= 해당일자와 출발일자가 같은지 판별
                       Td.FindElementByCss("button > b").Click               '= 해당일자 클릭
                        
                    Exit Function
                    End If
            
                End If
                Next Td
            Next Tr
            
        End If
    
    Next Ca

End Function
Function Haja_Format()

    With [d9].CurrentRegion
    
        .HorizontalAlignment = xlLeft
        .IndentLevel = 1
        .Borders.LineStyle = 1
        
    End With

End Function

네이버여행.xlsm
0.20MB

댓글