ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Selenium] 셀레니움 ActionChains로 스크롤 끝까지 내리는 방법 알아보기
    Python/크롤링 2024. 2. 28. 14:53
    반응형

    파이썬 셀레니움 ActionChains로 스크롤 끝까지 내리는 방법 알아보기


    파이썬(Python)을 이용한 크롤링 작업 중, 셀레니움(Selenium)을 이용한 크롤링은 다양한 상호작용을 지원합니다. 그중에서, 스크롤을 일정 수준 내리면 새로운 콘텐츠가 로드되는 방식의 웹사이트는 단순히 HTML 문서를 파싱하는 방법으로는 크롤링할 수 없기 때문에 셀레니움 사용이 필수지요. 이번에는 원티드(wanted)에서 채용정보를 검색하는 상황을 가정하여 자동으로 스크롤 끝까지 내리는 방법을 구현해 보도록 하겠습니다.

     

     

     [사진 1] 원티드에서 채용정보를 검색했을 때의 화면

     

     

    원티드에서 플러터(Flutter) 기술 관련 채용정보를 검색한다고 가정해 봅시다. 이 때, 검색창에 flutter라는 키워드를 적은 뒤, 해당 포지션 정보를 조회할 수 있지요. 그런데, 이 검색 결과는 한 페이지에 24개. 추가 로드시 12개씩의 채용정보만 조회할 수 있습니다. 웹사이트의 아래 부분으로 스크롤을 내릴 경우, 추가 데이터가 로드되는 방식으로 구현되어 있지요. 이런 웹사이트의 특징은 이용자가 페이지 이동을 하지 않고 스크롤만 내리는 방식으로 조회를 할 수 있기 때문에, 모바일 친화적인 웹페이지를 구현하기 쉽다는 장점이 있습니다. 실제로 원티드는 반응형 웹 기술을 이용해서 모바일 화면에서도 똑같은 UI로 검색 결과를 제공하는 특징을 보여주고 있지요.

     

    하지만, 사용자 입장에서는 편할지 모르겠지만 크롤러를 만드는 입장에서는 전통적인 페이지 구분 방식의 웹사이트에 비해서 데이터 수집이 까다로운 경향이 있습니다. 이 때, 셀레니움에서 제공하는 액션체인(ActionChains)이라는 기능을 이용해 스크롤 끝까지 내리는 방법을 간편하게 구현해 보려 합니다.

     

     

     [사진 2] 액션체인 스크롤의 동작

     

     

    액션체인을 이용한 스크롤 원리는 다음과 같습니다.

    1. 화면의 맨 아래에 있는 버튼이나 텍스트 영역을 선택한다.
    2. 해당 영역이 화면에 보이도록 이동한다.
    3. 화면이 이동되는 즉시 아래 내용이 로드된다.
    4. 더이상 로드할 정보가 없을 때까지 (1) 의 내용부터 다시 시작한다.

     

    위 기능을 구현하기 위해 접속할 URL을 설정한 뒤, 셀레니움의 webdriver를 실행해 줍니다. URL은 https://www.wanted.co.kr/search?query=(검색어)&tab=position 가 되겠네요.

     

     

    # import package
    import selenium
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver import ActionChains
    import time
    
    # user agent 설정
    chrome_options = Options()
    chrome_options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36')
    
    # 검색어 및 URL 설정
    keyword = 'flutter'
    url = f'https://www.wanted.co.kr/search?query={keyword}&tab=position'
    
    # selenium webdriver 실행
    driver = webdriver.Chrome(options=chrome_options)
    driver.get(url)
    
    # ActionChains 활성화
    action = ActionChains(driver)

     

     

    위 코드를 실행했다면, 총 포지션 개수에 따라서 ActionChains를 이용해 스크롤 끝까지 내리기를 구현해 보도록 하겠습니다. 예를 들어, 총 포지션 개수가 30개라면 (30-24)/12 값인 0.5를 올림해서 1을 얻을 수 있지요? 이 값이 스크롤할 횟수가 되어서 셀레니움 창이 1번 스크롤을 내리도록 코드를 구현할 수 있습니다. 또는, (총 포지션 개수) - (현재 로드된 포지션 개수) = 0 이 될 때까지 반복하는 방법도 있겠습니다.

     

     

     [사진 3] 총 포지션 개수가 표기된 영역

     

     

    총 포지션 개수의 경우, 검색 결과에 포지션(N) 형식으로 출력이 되는 문구가 있는데, 여기서 숫자 영역의 Xpath를 확인한 뒤 해당 값을 이용해 주면 되겠습니다. 총 포지션 개수의 Xpath는

    //*[@id="search_tabpanel_position"]/div/div[1]/h2/span 이고, 현재 로드된 포지션 개수는

    //*[@id="search_tabpanel_position"]/div/div[4]/div/a/div[2]/strong 이 값을 받아봐 보겠습니다.

     

     

    # 총 포지션
    max_num = driver.find_element(By.XPATH, '//*[@id="search_tabpanel_position"]/div/div[1]/h2/span').text
    max_num = int(max_num)
    print('총 포지션 개수:', max_num)
    
    # 현재 로드한 포지션
    def position_check():
        load_position = driver.find_elements(By.XPATH, '//*[@id="search_tabpanel_position"]/div/div[4]/div/a/div[2]/strong')
        load_num = len(load_position)
        print('현재 로드된 포지션 개수:', load_num)
        return load_position, load_num
    
    load_position, load_num = position_check()
    총 포지션 개수: 50
    현재 로드된 포지션 개수: 24

     

     

    다음으로는, 모든 항목이 로드될 때까지 셀레니움의 액션체인을 이용해 스크롤 끝까지 내리기를 해 보겠습니다. 위에서 정의한 load_position의 맨 마지막 요소가 있는 곳으로 화면을 이동하면 새로운 항목이 로드되겠죠? 그러면 위에 적은 코드를 확인해서 새로 로드된 항목이 있는지 체크해보는 코드를 작성해 보겠습니다.

     

     

    while load_num < max_num:
        # 맨 마지막 요소가 있는 위치로 이동
        last_element = load_position[-1]
        action.move_to_element(last_element).perform()
    
        # 로딩시간동안 대기
        time.sleep(.5)
    
        # 현재 로드된 포지션을 다시 확인
        load_position, load_num = position_check()
    현재 로드된 포지션 개수: 36
    현재 로드된 포지션 개수: 48
    현재 로드된 포지션 개수: 50

     

     

    위 코드를 이용해서 원티드 웹사이트의 플러터 채용공고 페이지를 스크롤 끝까지 내리는 방법을 알아보았습니다. 이후에는 채용공고 정보를 수집하거나, 특정 조건을 만족하는 공고를 확인하는 방식으로 해당 웹사이트의 데이터를 크롤링하거나 자동 업무 진행을 기획해볼 수 있겠습니다.

    반응형

    댓글

문의: jwkang3929@naver.com