스파르타 코딩클럽에서 코딩 공부를 시작하고 나서, 이론을 배울 때는 잘 이해하고 기록해두면서 뭔가 항상 "금방 쉽게 하겠지~" 라는 생각을 가지고 있었는데, 막상 시작을 하면 너무 기초적인 것 부터 "아 이거 여긴 어떻게 하지?" 라는 생각이 든다. 내 전체적인 프로젝트를 생각하면 모르는게 너무 많을 것 같아 두려움이 앞선다.

 

시간은 한정적이고 할 일은 많다. 회사에서 업무를 위해 오픈소스와 리눅스 공부는 계속 해야하고, 자녀들과도 시간을 보내고 아내를 도와주기도 해야 하고, 놀아야 하고, 다른 공부도 해야하고, 영어도 해야하고... 너무나 할일이 많다. 이번 스파르타 코딩 프로젝트를 진행하면서, 모든 우선순위를 제쳐두고 집중하면서도 잘 되지 않으면 어쩌나 라는 걱정도 많이 했다. 

 

그래도 내가 해야 할 모든 일들을 생각하는 것 보다, 눈앞에 해야 할 일만 생각하면 조금 더 마음이 편해질 수 있었고, 내가 가장 먼저 해야하는 것부터 조금씩 해나간다면 그래도 뭔가 진행이 된다는 사실에 또 마음이 편해졌다.

 


 

내가 해야 할 프로젝트 중 가장 먼저 완료해야 하는것은 스크래핑을 통해 원하는 데이터를 가져오는 것이다. 이게 되지 않는다면 프로젝트 자체를 진행할 수 없다.

 

프로젝트 계획안대로, 아래의 모든 사이트들을 스크래핑했다.

 

- 퀘이사존 : https://quasarzone.com/bbs/qb_saleinfo

- 카톡 톡딜 : https://store.kakao.com/

- 클리앙 알뜰구매 : https://www.clien.net/service/board/jirum

 - 펨코 핫딜 : https://www.fmkorea.com/hotdeal

- 루리웹 핫딜1 : https://bbs.ruliweb.com/market/board/600004

- 루리웹 핫딜2 : https://bbs.ruliweb.com/market/board/1020

- 뽐뿌 오프라인뽐뿌 : http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu5

 

대부분의 사이트들은 가장 기초적인 beautifulsoup을 사용한 스크래핑이 되지 않도록 어느정도 방안을 마련한 것 같았다. 어떻게 해도 스크래핑이 되지 않는 경우가 있어, 결국 모든 스크래핑은 selenium으로 진행했다.

 

그런데 하다보니, 각 사이트들이 일관성이 없어도 너무 없었다. 결국 "특가" 라는 개념에는 특정 가격의 제품을 소개할 수도 있지만, 단순히 할인이나 모음전, 어떤 사람은 마트에서 싸게 나온 제품을 사진찍어서 올리는 사람도 있었다. 다시말해, 가격이 없는 게시글, 이미지가 없는 게시글, 아예 제품이 뭔지 정해지지 않은 게시물 등 중구난방이었다.

 

결국 처음에 목적으로 했던 가격으로 검색하는 기능이나, 이미지를 포함하여 보기 좋게 하려는 것은 불가능하다고 판단했고, 과감하게 스크래핑 목록에서 이미지와 가격은 빼버렸다. 즉, 딱 제목과 링크, 날짜만 가져오게 된 것이다. 뭔가 많이 부족해 보여서 고민을 많이 했는데, 그래도 여러 특가를 한번에 볼 수 있다는 메리트는 계속 있다고 생각되어, 다행히 프로젝트는 엎어지지 않고 그대로 진행하기로 했다.

 

여러가지 사이트의 크롤링 구문 중 퀘이사존의 특가정보를 스크래핑하는 구문이다.

## 패키지 Import
from selenium import webdriver
from bs4 import BeautifulSoup
import re
import pymysql.cursors


## 셀레니움 스크래핑 기본정보
option = webdriver.ChromeOptions()
option.headless = True
option.add_argument("window-size=1920x1080")
option.add_argument("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36")
browser = webdriver.Chrome('C:\chromedriver', options=option)
browser.maximize_window()


# 퀘이사존 스크래핑 함수 제작
def quasarzone(url):

    # 데이터 가공
    browser.get(url)
    soup = BeautifulSoup(browser.page_source, "lxml")
    # 필요한 데이터 가져오기. 원하는 데이터가 모두 포함된 가장 적절한 태그는 tr 이다.
    # 그 위의 <tbody>를 하지 않는 이유는, 데이터가 리스트화되지 않고 한개의 뭉텅이가 되어서 스크래핑시 하나밖에 못가져온다.
    datas = soup.find_all("tr")

    # 스크래핑 시작
    for data in datas:
        
        # 각 데이터에 대한 변수 선언
        dealTitle = data.find("a", attrs={"class": "subject-link"}) # 제목
        dealLink = data.find("a", attrs={"class": "subject-link"}) # 글링크
        dealDate = data.find("span", attrs={"class" : "date"}) # 날짜
        dealBlind = data.find("i", attrs={"class" : "fa fa-lock"}) # 블라인드 처리된 글
        
        # 전체 데이터 중 None이 발생할 수 있어 None을 제거함
        if dealTitle is not None:
            
            # 각 게시물 중 "블라인드 처리된 글입니다." 라는 글이 있는데, 해당 글은 제외함
            if dealBlind:
                # 즉, dealBlind가 있다면 아무것도 안하고 그냥 넘어감.
                continue
            
            finalDealTitle = dealTitle.text.strip()
            finalDealLink = "https://quasarzone.com/" + dealLink["href"]
            finalDealDate = extractDate(dealDate.text.strip())
            
            print(finalDealTitle)
            print(finalDealLink)
            print(finalDealDate)


# 페이지별 스크래핑
address1 = "https://quasarzone.com/bbs/qb_saleinfo?page=1"
address2 = "https://quasarzone.com/bbs/qb_saleinfo?page=2"
quasarzone(address1)
quasarzone(address2)

 

각 사이트마다 특징이 있는데, 그 중 퀘이사존 특가게시판은 유독 블라인드 처리된 글이 많았다. 해당 블라인드 글까지 가져올 수는 없으므로, 블라인드 된 글을 따로 제거하기 위해 블라인드 된 글의 공통 클래스를 찾았고, 해당 클래스로 블라인드된 글만 제거할 수 있었다.

 

def fmkorea(url):

    # 데이터 가공
    browser.get(url)
    soup = BeautifulSoup(browser.page_source, "lxml")
    # 필요한 데이터 가져오기. 원하는 데이터가 모두 포함된 가장 적절한 태그는 tr 이다.
    datas = soup.find_all("tr")

    # 스크래핑 시작
    for data in datas:
    
        # 각 데이터에 대한 변수 선언
        dealTitle = data.find("td", attrs={"class" : "title hotdeal_var8"}) # 제목
        # 참고로, 에펨코리아는 품절된 제품은 아예 제목의 클래스를 바꿔버리므로 품절된 제품은 아예 검색에서 빠진다. 편하네. (품절제품 클래스명 : hotdeal_var8Y)
        dealLink = data.find("a", attrs={"class" : "hx"}) # 글링크
        dealDate = data.find("td", attrs={"class" : "time"}) #날짜
        
        # 데이터 중 None 이 있다면 None 부분은 skip 하도록 함.
        if dealTitle is not None:
            finalDealTitle = dealTitle.find("a").text.strip().replace("(무료)", "").replace("(0원)", "")
            finalDealLink = "https://www.fmkorea.com/" +  dealLink["href"]
            finalDealDate = extractDate(dealDate.text.strip())
            
            print(finalDealTitle)  # 배송비 (무료), (0원) 부분은 없어도 되므로 제거함.
            print(finalDealLink)
            print(finalDealDate)

            
# 3. 에펨코리아 : 핫딜
address1 = "https://www.fmkorea.com/index.php?mid=hotdeal&listStyle=list&page=1"
#address2 = "https://www.fmkorea.com/index.php?mid=hotdeal&listStyle=list&page=2"
fmkorea(address1)
#fmkorea(address2)

에펨코리아 사이트에서는 품절된 제품이 따로 표시되는데, 클래스가 맞지 않아 어떻게 스크래핑할까 고민하다가 알고보니 품절된 제품은 아예 클래스를 변경해버리는 것을 확인했다. 내가 뭘 할것도 없이 클래스가 다르니 스크래핑할 때 걸러지는 것이었다. 그걸 몰라서 혼자 뻘생각을 하다가 "앗.. 이게 이렇게 되네?" 이러고 허무하게 넘어갔다.

 


 

막상 7개의 사이트를 모두 스크래핑하니, 2페이지씩만 해도 한번에 게시글이 300개 이상 나왔다. 매일매일 간단하게 특가 정보를 확인하려는게 목적인데 아무래도 너무 양이 많은 것 같아서 결국 카카오톡 톡딜은 탈락했다.

 

그래도 양을 줄여서 추가해볼까 했는데, 일단 최종 결과물이 나오고 나서 다시한번 확인해볼 예정이다. 만약 카테고리별로 글을 나눌 수 있으면 게시글 양이 많아도 좋을텐데, 카테고리를 나누는 것은 딥러닝 정도는 쓸 수 있어야.. 할 수 있을 것 같다. 일단은 보류.

+ Recent posts