ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] Selenium 을 활용한 네이버 뉴스 크롤링
    IT 개발 2023. 7. 18. 10:26

    오늘은 Selenium 을 활용해서 뉴스헤드라인, url, 뉴스키워드csv 파일에 삽입해 볼 것입니다.

     

    원하는 키워드를 입력하여 검색했을 때 나오는 뉴스의 헤드라인과 url을 받아 키워드와 함께 csv 파일에 입력할 것입니다.

     

    시작하기 전 주의사항 ) 

     - 뉴스 기사는 기자 및 출판사에 저작물 등록이 되어있으므로 상업적 이용이 불가능합니다.

     - 해당 사이트의 robots.txt의 주의사항을 확인 후 크롤링합시다.

     

    기본 환경 세팅

    첫 번째로 환경 세팅을 해봅시다. 

    사용할 라이브러리 및 크롬드라이버를 받아줍니다.

    pip install selenium

    크롬 드라이버는 본인 컴퓨터에 설치된 크롬의 버전과 일치해야 합니다.

     

    크롬 버전 확인 방법

    크롬정보 확인
    크롬버전확인

    사용하고 있는 크롬 버전을 확인한 후 크롬드라이버를 다운로드합니다.

     

    크롬드라이버 페이지

    위 사진의 Downloads를 누르면 아래의 창이 나옵니다.

     

    다운로드 페이지

    다운로드 페이지에서 본인 크롬 버전과 맞는 버전을 다운로드하면 chromedriver.exe 파일을 할 수 있습니다.

    받은 chromedriver.exe 파일은 zip을 풀고 코드가 있는 폴더에 넣어두시면 됩니다.

     

    코드작성

    자 이제 모든 준비는 끝났습니다.

    저희에게 필요한 내용을 정리해 보자면,

    • 뉴스키워드
    • 뉴스헤드라인
    • 뉴스 url

    정도로 정리할 수 있습니다.

    뉴스헤드라인과 url 은 네이버뉴스에서 받아올 것이며, 뉴스키워드는 원하는 대로 지정 가능합니다.

    드라이버 지정

    from selenium import webdriver
    
    #드라이버 지정
    webDriver = webdriver.Chrome("본인이 넣어든 크롬드라이버 위치")

    selenium에서 webdriver를 import 하여 본인이 크롬드라이버를 넣어둔 위치에서부터 가져와 Chrome driver를 지정합니다.

    변수 선언

    #csv 파일에 저장할 요소 리스트 및 뉴스검색 키워드 선언
    news_urls = []
    news_titles = []
    news_column = 0
    search_word = "재난안전"

     

    csv 파일에 저장할 뉴스키워드, 헤드라인, url, 구분할 번호를 선언합니다.

    이제 본격적으로 코드를 작성합니다.

    메인 코드

    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    import time
    
    #사이트 열기
    webDriver.get('https://news.naver.com/')
    webDriver.implicitly_wait(10) #로딩 끝날때까지 10초 기다리기
    
    #뉴스 검색돋보기 클릭
    webDriver.find_element(By.CSS_SELECTOR,'a.Ntool_button._search_content_toggle_btn').click()
    time.sleep(2)
    
    #뉴스 검색 Input 클릭
    search = webDriver.find_element(By.CSS_SELECTOR, 'input.u_it._search_input')
    search.click()
    
    #검색어 입력
    search.send_keys(searchWord)
    search.send_keys(Keys.ENTER)
    webDriver.switch_to.window(webDriver.window_handles[1])

    우선 네이버뉴스 사이트를 열고 사이트가 열릴 때까지 10초 기다립니다.

    그 후 네이버 뉴스의 검색 돋보기를 By.CSS_SELECTOR로 가져와 클릭합니다.

     

    돋보기 버튼 class 가져오기

     

    빨간 동그라미 버튼을 클릭해 html 요소에 마우스를 가져다 대면 해당 요소의 class를 가져올 수 있습니다.

    돋보기 버튼을 클릭했을 시 아래사진처럼 검색창이 나옵니다. 검색창의 input 요소 또한 class를 가져와 클릭한후 선언해 놓은 뉴스키워드를 입력하여 ENTER를 눌러 검색합니다. 

     

    여기서 중요

    webDriver.switch_to.window(webDriver.window_handles[1]) 을 통해 크롬 웹드라이버가 뉴스키워드를 이용해 검색하여 새로 뜬 창으로 드라이버를 전환해주어야 합니다.

    뉴스키워드를 통해 검색했을 시 아래의 화면이 나옵니다.

     

     

    이곳에서 뉴스 제목을 클릭할 시 해당하는 언론사의 홈페이지에 게시된 기사 링크로 이동하게 됩니다. 해당 언론사 홈페이지로 이동하여 크롤링하려고 할 시, 언론사 홈페이지마다 전부 다른 방식으로 만들기 때문에 본문 내용 또는 헤드라인을 받아오기가 힘들어집니다. 그렇기 때문에 저희는 뉴스 제목이 아닌 네이버뉴스에서 해당기사를 게시한 링크로 이동해야 합니다.

     

     

    그래서 해당 부분을 확인해보니 a.info로 가져올 수 있다는 것을 확인하여 그대로 개발을 진행했습니다만,

     

    a.info 클래스로 가져오려고 하니 a.info.press 또한 같이 가져와진다는 것을 확인했습니다.

    그래서 클래스가 아닌 selector를 copy 해오려고 했습니다.

     

     

    하지만 Copy Selector 또한 최상단의 selector와 나머지 네이버뉴스의 selector 가 다른 걸 알게 됐습니다.

    최상단의 selector #sp_nws374 > div.news_wrap.api_ani_send > div > div.news_info > div.info_group > a:nth-child(3)

    나머지의 selector #sp_nws379 > div > div > div.news_info > div.info_group > a:nth-child(3)

    하지만 여기서 두고 비교해 보니 div > div.news_info > div.info_group > a:nth-child(3) 부분이 일치하는 걸 보고 코드를 작성하여 실행시켜 보니 작동한다는 걸 확인했습니다.

    결국 저희는 div.news_info > div.info_group > a:nth-child(3)로 네이버뉴스를 가져올 수 있습니다.

     

    while(1) :
        #네이버뉴스 클릭
        ems = webDriver.find_elements(By.CSS_SELECTOR, 'div.news_info > div.info_group > a:nth-child(3)')
        titles = webDriver.find_elements(By.CSS_SELECTOR,'a.news_tit')
        for i in titles:
            news_titles.append(i.text)
    
        for i in ems:
            i.click()
    
            # 현재탭에 접근
            webDriver.switch_to.window(webDriver.window_handles[2])
            time.sleep(2) #대기시간 변경 가능
    
            # 네이버 뉴스 url만 가져오기
            url = webDriver.current_url
    
            #네이버 뉴스 일시 url append
            if "news.naver.com" in url:
                news_urls.append(url)
    
            else:
                pass
    
            # 현재 탭 닫기
            webDriver.close()
    
            # 다시처음 탭으로 돌아가기
            webDriver.switch_to.window(webDriver.window_handles[1])
    
        #다음페이지로 넘어가는 btn 클릭
        btn_next = webDriver.find_element(By.CSS_SELECTOR, '#main_pack > div.api_sc_page_wrap > div > a.btn_next')
        is_disabled = True if btn_next.get_attribute("aria-disabled") == 'true' else False
        if is_disabled : break
        btn_next.click()

     

    위의 코드로 네이버뉴스를 클릭해 url을 받아오고, 뉴스 타이틀을 가져와 선언한 리스트에 저장할 수 있습니다.

    또한 현재페이지의 모든 뉴스를 크롤링했을 시 다음페이지로 넘어가 다음페이지 또한 크롤링해옵니다.

     

    CSV 파일에 저장

    이제 남은 건 받아온 뉴스 타이틀과 url, 키워드를 csv 파일에 저장하는 것입니다.

    우선 csv 파일에 저장하는 양식을 만듭니다.

    import csv
    
    #데이터 csv 저장
    f = open('data.csv', 'w', encoding='utf-8', newline='')
    wr = csv.writer(f)
    def append_csv(column, category, news_title, news_url):
        wr.writerow([column, category, news_title, news_url])
        print(column, '번째 csv 요소 삽입완료')
        
    f.close()

     

    이렇게 column과 뉴스키워드, 뉴스타이틀, 뉴스 url을 받아서 csv 파일에 저장하는 메서드를 작성했습니다.

    이제 이 메소드를 활용해 받아온 요소들을 csv 파일에 입력 후 f.close() 해줍니다.

     

    전체 코드

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    import time
    import csv
    
    #드라이버 지정
    webDriver = webdriver.Chrome()
    
    #csv 파일에 저장할 요소 리스트 선언
    news_urls = []
    news_titles = []
    news_column = 0
    searchWord = '재난안전'
    
    #사이트 열기
    webDriver.get('https://news.naver.com/')
    webDriver.implicitly_wait(10) #로딩 끝날때까지 10초 기다리기
    
    #뉴스 검색돋보기 클릭
    webDriver.find_element(By.CSS_SELECTOR,'a.Ntool_button._search_content_toggle_btn').click()
    time.sleep(2)
    
    #뉴스 검색 Input 클릭
    search = webDriver.find_element(By.CSS_SELECTOR, 'input.u_it._search_input')
    search.click()
    
    #검색어 입력
    search.send_keys(searchWord)
    search.send_keys(Keys.ENTER)
    webDriver.switch_to.window(webDriver.window_handles[1])
    
    #데이터 csv 저장
    f = open('data.csv', 'w', encoding='utf-8', newline='')
    wr = csv.writer(f)
    def append_csv(column, category, news_title, news_url):
        wr.writerow([column, category, news_title, news_url])
        print(column, '번째 csv 요소 삽입완료')
    
    while(1) :
        #네이버뉴스 클릭
        ems = webDriver.find_elements(By.CSS_SELECTOR, 'div.news_info > div.info_group > a:nth-child(3)')
        titles = webDriver.find_elements(By.CSS_SELECTOR,'a.news_tit')
        for i in titles:
            news_titles.append(i.text)
    
        for i in ems:
            i.click()
    
            # 현재탭에 접근
            webDriver.switch_to.window(webDriver.window_handles[2])
            time.sleep(2) #대기시간 변경 가능
    
            # 네이버 뉴스 url만 가져오기
            url = webDriver.current_url
    
            #네이버 뉴스 일시 url append
            if "news.naver.com" in url:
                news_urls.append(url)
    
            else:
                pass
    
            # 현재 탭 닫기
            webDriver.close()
    
            # 다시처음 탭으로 돌아가기
            webDriver.switch_to.window(webDriver.window_handles[1])
    
        #다음페이지로 넘어가는 btn 클릭
        btn_next = webDriver.find_element(By.CSS_SELECTOR, '#main_pack > div.api_sc_page_wrap > div > a.btn_next')
        is_disabled = True if btn_next.get_attribute("aria-disabled") == 'true' else False
        if is_disabled : break
        btn_next.click()
    
        #csv 파일에 데이터 입력
        if len(news_urls) != 0:
            csv_input_length = len(news_urls) - news_column
            for i in range(csv_input_length):
                append_csv(news_column, searchWord, news_titles[news_column], news_urls[news_column])
                news_column += 1
    
    f.close()

     

    이상 Selenium으로 네이버 뉴스 크롤링이었습니다.

Designed by Tistory.