Programming,  Python

[Python] Selenium

동적으로 웹 페이지에서 어떤 동작들을 하고 싶을때 Python 프로그램을 통해서 또한 가능하다. 아래 코드는 특정 사이트에서 로그인을 하는 프로그램이다.

from selenium import webdriver 

driver = webdriver.Chrome("chromedriver") 
driver.implicitly_wait(3)
driver.get("https://www.danawa.com/") 

login = driver.find_element_by_css_selector('li.my_page_service > a')
print("HTML 요소: ", login)
print("태그 이름: ", login.tag_name)
print("문자열: ", login.text)
print("href 속성: ", login.get_attribute('href'))

login.click()
driver.implicitly_wait(3)

my_id = "----- 아이디 입력 -----"
my_pw = "----- 비밀번호 입력 -----"

driver.find_element_by_id('danawa-member-login-input-id').send_keys(my_id)
driver.implicitly_wait(2)
driver.find_element_by_name('password').send_keys(my_pw)
driver.implicitly_wait(2)
driver.find_element_by_css_selector('button.btn_login').click()
HTML 요소:
태그 이름: a
문자열: 로그인
href 속성: https://auth.danawa.com/login?url=http%3A%2F%2Fwww.danawa.com%2F

위 코드의 결과를 보기전에 반드시 chromedriver가 필요하기 때문에 크롬 드라이버를 현재 크롬 버전에 맞춰서 다운받아서 해당 코드와 같은 directory에 저장을 시키면 된다. 그리고 본인의 아이디와 비밀번호도 함께 입력해주면 된다.

위 코드에서 login 변수에서 find_element_by_css_selector('li.my_page_service > a')는 실제 다나와 사이트에서 로그인 클릭을 나타내는 tag를 가리킨다. 'li.my_page_service > a' 정보는 다나와 사이트에서 우클릭 하여 ‘검사’ 버튼을 누르면 각 region별로 tag를 가리키게 된다.
원하는 tag에서 우클릭 – Copy – Copy selector를 클릭하면 tag 정보가 나오는데 우리가 실제 필요한 부분만 넣으면 된다.

danawa_header > div.danawa_top_search > div > div.my_service > div.my_service_list > ul > li.my_page_service > a > span

[대충 ‘검사’ 클릭 후 보여지는 화면…]

login.click() 을 하게되면 클릭하고 난 다음 화면으로 넘어가게 된다.

그리고 아이디와 비밀번호를 입력하기 위해 동일하게 tag 정보를 얻은 뒤 send_keys()를 통해 아이디와 비밀번호를 전달하고 확인 버튼을 누르면 우리가 원하는 로그인이 된다.

특정 정보 리스트 추출

로그인 후 관심있는 정보들을 리스트로 또한 얻을 수 있다. 정보를 얻는건 selenium을 통해서 얻고 html 정보를 얻으면 그 뒤엔 BeautifulSoup을 통해서 원하는 정보를 parsing하는 코드다.

from selenium import webdriver 

driver = webdriver.Chrome("chromedriver") 
driver.implicitly_wait(3)
driver.get("https://www.danawa.com/") 

login = driver.find_element_by_css_selector('li.my_page_service > a')
login.click()
driver.implicitly_wait(3)

my_id = "----본인 아이디 입력하세요----"
my_pw = "----본인 패스워드 입력하세요----"

driver.find_element_by_id('danawa-member-login-input-id').send_keys(my_id)
driver.implicitly_wait(2)
driver.find_element_by_name('password').send_keys(my_pw)
driver.implicitly_wait(2)
driver.find_element_by_css_selector('button.btn_login').click()
driver.implicitly_wait(2)

wishlist = driver.find_element_by_css_selector('li.interest_goods_service > a').click()
driver.implicitly_wait(2)
html_src = driver.page_source # html source
driver.close()
#print(html_src[:]) 

from bs4 import BeautifulSoup
import re
soup = BeautifulSoup(html_src, 'html.parser')

wish_table = soup.select('table[class="tbl wish_tbl"]')[0]
wish_items = wish_table.select('tbody tr')

for item in wish_items:
    title = item.find('div', {'class':'tit'}).text
    price = item.find('span', {'class':'price'}).text
    link = item.find('a', href=re.compile('prod.danawa.com/info/')).get('href')
    print(title)
    print(price)
    print(link)
    print("\n")
Western Digital WD BLUE SN550 M.2 NVMe (500GB)
87,600원
http://prod.danawa.com/info/?pcode=10120452
삼성전자 860 EVO (500GB)
101,100원
http://prod.danawa.com/info/?pcode=5834210

웹 페이지에서 파일 다운로드

from selenium import webdriver 
import time

def download_bok_statistics():

    driver = webdriver.Chrome("chromedriver") 
    driver.implicitly_wait(3)
    driver.get("http://ecos.bok.or.kr/jsp/vis/keystat/#/key") 
    
    
    excel_download = driver.find_element_by_css_selector('img[alt="download"]')
    driver.implicitly_wait(3)
    
    excel_download.click()
    time.sleep(5)
    
    driver.close()
    print("파일 다운로드 실행...")

    return None

download_bok_statistics()
파일 다운로드 실행…

활용 예제

Selenium과 BeautifulSoup을 활용해 특정 키워드를 통해서 우리가 원하는 정보를 찾아내 데이터를 추출하는 프로그램을 아래와 같이 작성할 수 있다.

from selenium import webdriver 
from bs4 import BeautifulSoup
import time

def download_bok_statistics_by_keyword():
    
    item_found = 0              
    while not item_found:
        
        keyword = ""       
        while len(keyword) == 0:
            keyword = str(input("검색할 항목을 입력하세요: "))
        
        driver = webdriver.Chrome("chromedriver")
        driver.implicitly_wait(3)
        driver.get("http://ecos.bok.or.kr/jsp/vis/keystat/#/key") 
        time.sleep(5)             
                   
        items1 = driver.find_elements_by_css_selector('a[class="ng-binding"]')
        items2 = driver.find_elements_by_css_selector('a[class="a-c1-list ng-binding"]')
        items3 = driver.find_elements_by_css_selector('a[class="a-c4-list ng-binding"]')
        driver.implicitly_wait(3)

        items = items1[1:] + items2 + items3    
        
        for idx, item in enumerate(items):
            if keyword in item.text:
                print("검색어 '%s'에 매칭되는 '%s' 통계지표를 검색 중..." % (keyword, item.text))
                item.click()
                item_found = 1
                time.sleep(5)
                break
            elif idx == (len(items) - 1):
                print("검색어 '%s'에 대한 통계지표가 존재하지 않습니다..." % keyword)
                driver.close()
                continue
            else:
                pass

    # Get html data
    html_src = driver.page_source 
    soup = BeautifulSoup(html_src, 'html.parser')
    driver.close()
  
    table_items = soup.find_all('td', {'class':'ng-binding'})
    date = [t.text for i, t in enumerate(table_items) if i % 3 == 0]
    value = [t.text for i, t in enumerate(table_items) if i % 3 == 1]    
    change = [t.text for i, t in enumerate(table_items) if i % 3 == 2]    
    
    result_file = open('bok_statistics_%s.csv' % keyword, 'w')
    
    for i in range(len(date)):
        result_file.write("%s, %s, %s" % (date[i], value[i], change[i]))
        result_file.write('\n')
    
    result_file.close()
    print("키워드 '%s'에 대한 통계지표를 저장하였습니다." % keyword)
    
    return date, value, change

result = download_bok_statistics_by_keyword()
print(result)
검색할 항목을 입력하세요: CD
검색어 ‘CD’에 매칭되는 ‘CD수익률(91일) (‘20.05.29)’ 통계지표를 검색 중…
키워드 ‘CD’에 대한 통계지표를 저장하였습니다.
([‘2013’, ‘2014’, ‘2015’, ‘2016’, ‘2017’, ‘2018’, ‘2019’, ‘2019.10’, ‘2019.11’, ‘2019.12’, ‘2020.1’, ‘2020.2’, ‘2020.3’, ‘2020.4’, ‘2020.5.22’, ‘2020.5.25’, ‘2020.5.26’, ‘2020.5.27’, ‘2020.5.28’, ‘2020.5.29’], [‘2.72’, ‘2.49’, ‘1.76’, ‘1.49’, ‘1.44’, ‘1.68’, ‘1.69’, ‘1.46’, ‘1.52’, ‘1.53’, ‘1.47’, ‘1.42’, ‘1.23’, ‘1.10’, ‘1.02’, ‘1.02’, ‘1.02’, ‘1.02’, ‘0.81’, ‘0.81’], [‘-0.58’, ‘-0.23’, ‘-0.73’, ‘-0.27’, ‘-0.05’, ‘0.24’, ‘0.01’, ‘-0.08’, ‘0.06’, ‘0.01’, ‘-0.06’, ‘-0.05’, ‘-0.19’, ‘-0.13’, ‘0.00’, ‘0.00’, ‘0.00’, ‘0.00’, ‘-0.21’, ‘0.00’])

Leave a Reply

Your email address will not be published. Required fields are marked *