본문 바로가기
Python_Wiki/Python_Library

웹크롤링: Selenium + chrome driver

by yj-data 2025. 7. 10.

목차


    설치

    # (1) 크롤링에 필요한 파이썬 라이브러리 설치
    !pip install webdriver-manager selenium
    
    # (2) 크롬 드라이버 자동 다운로드 => 특정 경로에 최신 버전의 크롬 드라이버가 설치됨.
    from webdriver_manager.chrome import ChromeDriverManager
    ChromeDriverManager().install()
    
    # (3) 셀레니움으로 크롬 브라우저 실행
    from selenium import webdriver
    browser = webdriver.Chrome()
    # (4) browser 이동시켜 (get) => url
    browser.get("http://www.naver.com")  #3,4는 한 셀에 넣고 실행하자

    코랩은 리눅스 기반이라 설치에 문제가 생길 수 있음. 아나콘다 기반의 주피터노트북으로 설치하자.

     

    url = 'https://weather.naver.com/'
    browser.get(url) # =해당 url로 이동해줘! 브라우저를 내가 가져오고자하는 정보가 있는 사이트로 이동을 시킨다.

     

    사이트로 넘어간 후, 가져오고자 하는 데이터 위에 커서를 두고 우클릭 > 검사 (f12와 동일)

     

    예, 현재날씨 35.2도에 대해 확인해보면

    <strong class = "card_now_temperature"> 35.2 </strong>

    # '현재 온도\n16.9°'
    from selenium.webdriver.common.by import By
    browser.find_element(By.CLASS_NAME, 'card_now_temperature').text #class_name, tag_name 등

     

    #위에 언급한 것들 한번에 모아보기
    #본격적으로 들어가기 전에 사전에 돌려야하는 코드
    
    from webdriver_manager.chrome import ChromeDriverManager
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    ChromeDriverManager().install()
    browser = webdriver.Chrome()
    
    url = 'https://www.dbpia.co.kr/search/topSearch?searchOption=all&query=%EC%86%8C%EB%B9%84%EC%9E%90+%ED%96%89%EB%8F%99' 
    browser.get(url)

     

    선택자 상수에는 무엇이 들어갈 수 있나? 

    By.ID id="..." 속성 By.ID, "search-box"
    By.NAME name="..." 속성 By.NAME, "username"
    By.CLASS_NAME class="..." 속성 (단일 클래스) By.CLASS_NAME, "btn"
    By.TAG_NAME 태그 이름 (<a>, <div> 등) By.TAG_NAME, "input"
    By.LINK_TEXT 링크 텍스트 전체 일치 (<a>텍스트</a>) By.LINK_TEXT, "Click here"
    By.PARTIAL_LINK_TEXT 링크 텍스트 일부 일치 By.PARTIAL_LINK_TEXT, "Click"
    By.XPATH XPath 표현식 By.XPATH, "//div[@class='item']"
    By.CSS_SELECTOR CSS 선택자 (가장 유연함) By.CSS_SELECTOR, ".item > a"

     

    싱글/멀티 데이터 추출

    #싱글데이터 추출
    browser.find_element(By.CLASS_NAME, 'complex_price--trade').text #'최근 매매 실거래가\n35억 2,000\n2025.06.18, 22층, 241㎡'
    browser.find_element(By.CLASS_NAME, 'complex_price--trade').text.split("\n")[1] #'35억 2,000'
    
    #한단계 더들어가기
    #item_link 아래에 있는 item_title에 접근하기
    browser.find_element(By.CLASS_NAME, 'item_link').find_element(By.CLASS_NAME, 'item_title').text
    #멀티데이터 추출 #.find_elements() => 해당 클래스 이름이 동일한 요소는 전부다 가져오는 함수
    data = browser.find_elements(By.CLASS_NAME, 'item_title')
    for i in data:
        print(i.text)
    #속성가져오기
    browser.find_element(By.CLASS_NAME, 'SDFD52').get_attribute('href')
    #example
    containers = browser.find_elements(By.CLASS_NAME, 'SoaBEf')
    for i in containers:
        news = i.find_element(By.CLASS_NAME, 'MgUUmf').text
        title = i.find_element(By.CLASS_NAME, 'n0jPhd').text
        contents = i.find_element(By.CLASS_NAME, 'GI74Re').text
        wdate = i.find_element(By.CLASS_NAME, 'rbYSKb').text
        link = i.find_element(By.CLASS_NAME, 'WlydOe').get_attribute('href')
        
        print(news,title,contents,wdate,link)
        
    #example2
    data=[]
    containers = browser.find_elements(By.CLASS_NAME, 'SoaBEf')
    for i in containers:
        news = i.find_element(By.CLASS_NAME, 'MgUUmf').text
        title = i.find_element(By.CLASS_NAME, 'n0jPhd').text
        contents = i.find_element(By.CLASS_NAME, 'GI74Re').text
        wdate = i.find_element(By.CLASS_NAME, 'rbYSKb').text
        link = i.find_element(By.CLASS_NAME, 'WlydOe').get_attribute('href')
        
        data.append({
            'title': title,
            'news_agency' : news,
            'contents': contents,
            'wdate': wdate,
            'link': link
        })
    print(data) 
    #[{'title': '심평원, 보건의료분야 빅데이터 분석가 양성한다',
      'news_agency': '메디칼타임즈',
      'contents': "[메디칼타임즈=] 건강보험심사평가원은 SAS코리아와 '제1회 보건의료 데이터 사이언티스트' 양성 교육과정을 마련하고 16일부터 5일간 실시한다고 16일 밝혔다.",
      'wdate': '5일 전',
      'link': 'https://medicaltimes.com/Users/News/NewsView.html?ID=1087319'},
     {'title': '차봇 고객데이터 분석해보니…“E클래스·5시리즈·GV70 상반기 경합”', ...   }]
     
    #data를 pd.DataFrame에 넣은 다음, df를 to_csv(인코딩 넣고) 로 저장하면 csv로 저장됨

     

    멀티 페이지 크롤링

    #멀티 페이지 크롤링
    import time
    
    for i in range(0,50,10):
        url = f'https://www.google.com/search?q=%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B6%84%EC%84%9D%EA%B0%80&sca_esv=edb9f998570affa4&tbm=nws&ei=EVV4aPymK53S2roPur28mAw&start={i}&sa=N&ved=2ahUKEwi887WA4sKOAxUdqVYBHboeD8M4ChDy0wN6BAgFEAQ&biw=958&bih=944&dpr=1'
    
        time.sleep(3)  #봇 차단을 막기위함. 각 페이지가 열릴때, 중간에 3초정도 쉬게 한다.
        browser.get(url)

     

    #여러 키워드 검색까지 더한, 최종코드
    keywords = ['a','b','c']
    
    import time
    
    data=[]
    for keyword in keywords:
        for num in range(0,50,10):
            url = f'https://www.google.com/search?q={keyword}&sca_esv=edb9f998570affa4&tbm=nws&ei=EVV4aPymK53S2roPur28mAw&start={num}&sa=N&ved=2ahUKEwi887WA4sKOAxUdqVYBHboeD8M4ChDy0wN6BAgFEAQ&biw=958&bih=944&dpr=1'
        
            time.sleep(3)
            browser.get(url)
        
            containers = browser.find_elements(By.CLASS_NAME, 'SoaBEf')
            
            for i in containers:
                news = i.find_element(By.CLASS_NAME, 'MgUUmf').text
                title = i.find_element(By.CLASS_NAME, 'n0jPhd').text
                contents = i.find_element(By.CLASS_NAME, 'GI74Re').text
                wdate = i.find_element(By.CLASS_NAME, 'rbYSKb').text
                link = i.find_element(By.CLASS_NAME, 'WlydOe').get_attribute('href')
                
                data.append({
                    'title': title,
                    'news_agency' : news,
                    'contents': contents,
                    'wdate': wdate,
                    'link': link
                })
        
        
        df = pd.DataFrame(data)
        df.to_csv('구글뉴스_데이터분석가_뉴스.csv', encoding='utf-8-sig')
    #time.sleep도 랜덤하게 하면 봇으로 잘 걸리지 않음.
    
    import time
    import random
    
    containers = browser.find_element(By.ID, 'paper-cards-section').find_elements(By.CLASS_NAME, 'thesis__subject')
    data=[]
    url_list=[]
    
    for i in containers:
        url = i.find_element(By.CLASS_NAME, 'thesis__pageLink').get_attribute('href')
        url_list.append(url)
    
    for link in url_list:    
        browser.get(link)
    
        number = random.randint(6,50)
        time.sleep(number)
        try: 
            title = browser.find_element(By.CLASS_NAME, 'thesisDetail__tit').text
            second_title = browser.find_element(By.ID, 'thesisEqualTitle').text
            abstract = browser.find_element(By.CLASS_NAME, 'abstractTxt').text
        except:
            pass
    
        data.append({
            '제목':title,
            '부제목':second_title,
            '초록': abstract
        })
        
    data_df = pd.DataFrame(data)
    data_df.head()

     

    조금이라도 셀레니움 속도를 빠르게 하고싶다면 headless모드로 하는 것도 방법임.