데이터 수집

함수부

모듈 로딩

from selenium.webdriver.chrome.service import Service
from selenium import webdriver as wd
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
import re
import time

팝업 광고 제거

# 프로모션 광고 제거

def kill_annoying_ad() :
    try :
        popup = driver.find_element(By.CSS_SELECTOR, "body > div:nth-child(16) > div.q-dialog__inner.flex.no-pointer-events.q-dialog__inner--minimized.q-dialog__inner--standard.fixed-full.flex-center > div > button")
    except NoSuchElementException :
        pass
    else :
        popup.click()
        print("\n# 짜증나는 광고 처치")

카드사별 페이지 번호 로드

# 카드사별 고유 페이지 번호 받아오기

def get_pagenum(start=1, end=10) :
		# 매개변수로 몇번째 페이지부터 몇번째 페이지까지 받아올지 설정

    kill_annoying_ad()

    page_num_list = []

    class_names = driver.find_elements(By.CSS_SELECTOR, "#q-app > section > div.team > section > article > ul > li")
    
    for class_name in class_names :

        page_num = class_name.get_attribute("class")
        page_num = re.sub(r"[^0-9]", "", page_num)
        if re.match(r"0.+", page_num) :
            page_num = page_num[1:]

        company_name = class_name.find_element(By.CSS_SELECTOR,"p.name_kr").text
        page_num_list.append((page_num, company_name))
    page_num_list = page_num_list[start-1:end]

    print("\n# ", end="")
    for idx, item in enumerate(page_num_list) :
        if idx == len(page_num_list)-1 :
            print(item[1], end="")
        else :
            print(item[1], ", ", end="")
    print("의 페이지 번호를 가져옴")

    kill_annoying_ad()
    return page_num_list

카드 url 로드

# 카드사별 페이지 접속 후 카드 url 받아오기

def get_url(page_num_list, log_name="data_urls") :

    # 최종 결과물이 담길 변수 생성

    data_urls = []

    for page_num in page_num_list :
        driver.get("https://www.card-gorilla.com/team/detail/{}".format(page_num[0]))
        print("\n# {} 페이지에 접속.".format(page_num[1]))
        time.sleep(2)
        kill_annoying_ad()

        # 모든 카드 목록을 펼쳐놓기

        card_list_element = driver.find_element(By.CSS_SELECTOR, "#q-app > section > div.team_detail > section > div > article.con_area > div > div.player_lst.results_lst > ul")
        next_sibling = driver.execute_script("""
            return arguments[0].nextElementSibling
        """, card_list_element)

        while next_sibling.is_displayed() :
            kill_annoying_ad()
            to_next = driver.find_element(By.CSS_SELECTOR, "#q-app > section > div.team_detail > section > div > article.con_area > div > div.player_lst.results_lst > a")
            to_next.click()
            time.sleep(0.3)    
        print("\n* 모든 카드 목록을 펼침")

        # 카드 이름과 혜택 정보가 적힌 url을
        # 최종 결과물이 담길 변수 data_url에 저장

        card_list = driver.find_elements(By.CSS_SELECTOR, "#q-app > section > div.team_detail > section > div > article.con_area > div > div.player_lst.results_lst > ul > li")
        
        for card in card_list :

            interrupt_issue = card.find_elements(By.CSS_SELECTOR, "p.txt_stop")
            if len(interrupt_issue) != 0 :
                continue # 신규발급중단(interrupt_issue) 상태 카드의 url은 크롤링 안함

            card_url = dict()
            name = card.find_element(By.CSS_SELECTOR, "p.card_tit").text
            url = card.find_element(By.CSS_SELECTOR, "a.b_view").get_attribute("href")
            card_url["name"] = name
            card_url["info_url"] = url
            data_urls.append(card_url) # 카드명과 url을 크롤링

        print("\n* 카드 url 모두 불러옴, 총 개수 :", len(data_urls))
        time.sleep(1)
        kill_annoying_ad()

    # data_url을 json으로 저장

    import json
    with open(f"{log_name}.json", "w") as j :
        json.dump(data_urls, j)
    j.close()
    print("\n* url 저장 완료")

    return data_urls

카드 혜택 정보 추출

# 카드의 정보와 혜택 추출

def get_benefits(data_urls, th = 10, log_name="data_benefits") :

    # 모든 카드의 모든 정보, 혜택이 들어갈 변수
    data = [] 

    i = 0
    for item in data_urls :
        if i == th : break
        i += 1

        # 각각 카드의 정보와 혜택이 적힌 url에 접근
        driver.get(item["info_url"]) 
        time.sleep(1)
        kill_annoying_ad()

        # 카드 정보 추출
        card_info = {} # 카드 한개의 정보가 들어갈 변수
        info_main = driver.find_element(By.CSS_SELECTOR, "#q-app > section > div.card_detail.fr-view > section > div > article.card_top > div > div > div.data_area")
        
        # 카드 이름
        card_info["name"] = info_main.find_element(By.CSS_SELECTOR, "div.tit > strong").text
        
        # 카드사 이름
        card_info["bank"] = info_main.find_element(By.CSS_SELECTOR, "div.tit > p").text

        # 연회비 (국내전용 domestic)
        try :
            card_info["annual_dom"] = info_main.find_element(By.CSS_SELECTOR, "div.bnf2 > dl:nth-child(1) > dd.in_out > span:nth-child(1) > b").text
        except NoSuchElementException :
            card_info["annual_dom"] = None

        # 연회비 (해외겸용 forigen)
        try :
            card_info["annual_for"] = info_main.find_element(By.CSS_SELECTOR, "div.bnf2 > dl:nth-child(1) > dd.in_out > span:nth-child(2) > b").text
        except NoSuchElementException :
            card_info["annual_for"] = None

        # 전월실적
        try :
            last_usage = info_main.find_element(By.CSS_SELECTOR, "div.bnf2 > dl:nth-child(2) > dd > b").text
        except NoSuchElementException :
            card_info["last_usage"] = None

        if last_usage == "없음" :
            card_info["last_usage"] = "0"
        else :
            card_info["last_usage"] = last_usage + "0,000"

        name = item["name"]
        print(f"\n# {i}. {name} 카드의 이름, 카드사, 연회비, 전월실적을 불러옴.")

        # 소비 카테고리별 혜택 추출
        category_benefits = []
        info_detail = driver.find_elements(By.CSS_SELECTOR, "#q-app > section > div.card_detail.fr-view > section > div > article.cmd_con.benefit > div.lst.inner.faq_area > dl")
        
        for category in info_detail :
            category_benefit = {}

            # 소비 카테고리 이름
            category_name = category.find_element(By.CSS_SELECTOR, "strong").text
            category_benefit["name"] = category_name

            # 혜택 내용 요약 - 나중에 텍스트 전처리 필요!
            benefit_summary = category.find_element(By.CSS_SELECTOR, "i").text
            category_benefit["summary"] = benefit_summary

            # 혜택 내용 상세를 보기 위해 클릭
            trigger = category.find_element(By.CSS_SELECTOR, "dt")
            driver.execute_script("arguments[0].click();", trigger)
            kill_annoying_ad()
            if category_name == "선택형" :
                category_benefit["detail"] = "개별확인요망" # 이건 도대체 어떻게 해야할지...
            else :
                benefit_detail = category.find_element(By.CSS_SELECTOR, "div.in_box").text
                category_benefit["detail"] = benefit_detail

            category_benefits.append(category_benefit)
            print(f"{category_name} 카테고리의 카테고리명, 혜택 내용 요약, 상세 내용을 불러옴.")
            time.sleep(0.4)
            kill_annoying_ad()

        card_info["category"] = category_benefits

        # 카드 한개의 모든 혜택과 정보를 data 변수에 저장
        name = item["name"]
        data.append(card_info)
        print(f"{name} 정보 추출 완료")
        time.sleep(1.9)
        kill_annoying_ad()


    # 카드 혜택 정보 저장
    import json
    with open(f"{log_name}.json", "w") as j :
        json.dump(data, j)
    j.close()
    print("\n카드 혜택 정보 저장 완료")


메인부

# 셀레니움 구동
service = Service(executable_path="./chromedriver/chromedriver.exe")
driver = wd.Chrome(service=service)


# 카드고릴라 카드사 목록 페이지 들어가기
driver.get("https://www.card-gorilla.com/team")
print("\n페이지 접속 성공 :", driver.title)


# 사이트 최초로 뜨는 광고 제거
time.sleep(4.5) # 광고가 4초쯤 뒤에 뜨니까 그때까지 기다리자
kill_annoying_ad()


# 카드사별 페이지 번호 받아오기
page_num_list = get_pagenum(start=1, end=1)


# 카드사별 페이지 접속 후
# 카드 혜택 정보가 적혀있는 url 받아오기
data_urls = get_url(page_num_list, log_name="data_urls")


# 카드의 정보와 혜택 추출하기
data_benefits = get_benefits(data_urls, th=2, log_name="data_benefits")


# 셀레니움 종료
driver.close()

결과

정의

Leave a comment