본문 바로가기
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모드로 하는 것도 방법임.