프로젝트/COHO - 코인 호재 캘린더

[Django] 코호 - 실시간 코인 호재 모음 PROC 1

모영이 2021. 3. 16. 22:18

코인 호재 정보를 한 곳에 모은 사이트를 만들려고 한다. 프로젝트 이름은 아직 안정했는데 멋진 이름을 구상중에 있다. 두명이서 진행하는데, 나는 크롤링 부분만 맡을 것 같다. 그 과정을 기록하려고 한다. 원래는 DAY 1 , DAY 2 이런식으로 제목을 하려했지만. 하루에 하는 양이 많고 과정의 흐름에 맞게 잘라내기 위해 process 1, process 2 이런식으로 제목을 수정했다. 1. 해결한 문제, 2. 마주친 문제, 3. 해결해야 할 문제 이렇게 정리하겠따..!

 

우선 크롤링에 대한 저작권적인 문제를 검색해봤다. 국내 판결과, 해외 판결의 사례를 찾아봤고 어차피 개인적인 사이트를 만드는 것이지만, 후에 상업적인 이용을 할지 모르고 그것이 불법이라면 문제가 될 수 있기 때문이다.

국내 판결, 야놀자 VS 여기어때, 사람인 VS 잡코리아의 사례에서 크롤링을 통해 상업적이용을 한 회사는 불법 판결을 받았다.

미국 판결, HiQ Labs Vs Linkedin 사례에서 HiQ Lab은 Linkedin에 올라와있는 사람들의 프로필을 수집하고 이 데이터를 가공하고 합쳐서 상업적으로 판매를 한 경우다. 특정 사용자에게만 오픈된 데이터가 아닌 것은 퍼블릭 데이터이고, 이를 크롤링하는 것은 불법이 아니다. 크롤링에 관한 저작권 문제는 상당히 모호할 수 있지만, 결국 크롤링 할 사이트는 해외 사이트이고 만약 법적 문제가 발생한다면 해외 판결을 받을 것이기에, 불법이 아니다. 만약 불법이라면 죄를 달게 받겠다. 

개인적인 생각이지만, 크롤링은 기계가 복사 붙여넣기를 해주는건데, 이것을 아예 막을 거라면, 웹 개발 툴에 허가되지 않은 링크를 크롤링하는 코드를 막는 기능을 법적으로 추가를 강제해야 한다고 생각한다. 총기 판매를 금지하는 것 처럼말이다. 너무 뇌절이어서 그만하겠다.. 어쨌든 아직 상업적으로 사용안했고, 개인적이기 때문에 현재로서는 불법이 아닌게 확실하다. 근데 진짜 정보가 넘쳐나는데 크롤링이 왜 불법일까.. 싶었지만, 정보의 가치를 올려주는 일이라 생각하면 살짝 인정하는데..그게 오히려 정보 격차를 만들지 않을까.. 싶었지만, 또 나보다 공부 많이 한 사람들이 판결을 내린 것이기 때문에 인정을 해야겠다..

 

우선. 여기 사이트를 크롤링 했다. 다른 사이트 + 뉴스 + 등등 다른 사이트도 크롤링 할 것이다.

 

 

여기까지 왔다. 

BeautifulSoup를 사용해서 CSS선택자를 이용해야 했다. 

제일 어려웠던 문제가 하나 있어서 정리하겠다.

 

마주친 문제

똑같은 이름이 아니어도 선택되는 문제

class="a"와 class = "a bc"있다고 할때 class="a"를 어떻게 선택할까?

soup.select(".a") 이렇게 하면 될 것 같지만 머리가 아파진다.

왜냐면 a bc도 가져오기 때문이다. 아무래도 띄어쓰기를 .으로 치환할 때의 문제가 발생하는 것 같다.

class = "a bc"를 선택하려면 soup.select("a.bc")이렇게 해줘야 하는데 여기서 a와 bc가 이어지면서 a를 선택했는데 a bc가 선택되는 문제가 발생하는 것 같다.

 

방법 1 : 부모를 찾아서 범위를 좁힌다.

방법 2 :  soup.select(div[class = 'a'])이렇게 해준다. 여기안에 들어가는 클래스 네임은 정확하게 같은 것만 찾아준다. 

 

전체 코드

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re

month = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 }

def packingData():
    result = []

    html = urlopen("https://coinmarketcal.com/en/")
    soup = BeautifulSoup(html, "html.parser")

    # 정보 -> 이름, 호재 시간, 추가된 시간, 제목, 상세내용
    coin_name_data = soup.select("article.col-xl-3.col-lg-4.col-md-6.py-3 > div.card.text-center > div.card__body > h5.card__coins > a.link-detail")
    coin_goodnewstime_data = soup.select("h5[class = 'card__date mt-0']")
    coin_addedtime_data = soup.select("p[class = 'added-date']")
    coin_title_data = soup.select("article.col-xl-3.col-lg-4.col-md-6.py-3 > div.card.text-center > div.card__body > a.link-detail > h5.card__title.mb-0.ellipsis")
    coin_detail_data = soup.select("p[class = 'card__description']")

    min_len = min(len(coin_name_data), len(coin_goodnewstime_data), len(coin_addedtime_data), len(coin_title_data), len(coin_detail_data))

    # 전처리 이름[이름, 태그], 호재 시간[년, 월, 일], 추가된 시간[년, 월, 일], 제목[문자열], 상세내용[문자열]
    # 전처리 후 패킹
    for i in range(0, min_len):
        # 이름 전처리
        coin_name = ' '.join(coin_name_data[i].string.split())
        coin_name = [coin_name[0 : coin_name.find('(') - 1], coin_name[coin_name.find('(') + 1 : coin_name.find(')')]]
        # 호재 시간
        coin_goodnewstime = coin_goodnewstime_data[i].string.split()
        coin_goodnewstime = coin_goodnewstime[:3]
        coin_goodnewstime[1] = str(month[coin_goodnewstime[1]])
        coin_goodnewstime.reverse()
        # 추가된 시간
        coin_addedtime = coin_addedtime_data[i].string.split()
        coin_addedtime = coin_addedtime[1:]
        coin_addedtime[1] = str(month[coin_addedtime[1]])
        coin_addedtime.reverse()
        # 제목
        coin_title = coin_title_data[i].string
        # 상세내용
        coin_detail = ' '.join(coin_detail_data[i].string.split())

        # 패킹
        item_coin = {
            'name': coin_name,
            'goodnewstime': coin_goodnewstime,
            'addedtime': coin_addedtime,
            'title': coin_title,
            'detail': coin_detail
        }
        result.append(item_coin)

    return result
for i in packingData():
    print(i)

 

해결해야 할 문제

1페이지가 아닌 41페이지 전체를 크롤링 해야 한다.

json파일로 넘겨주어야 한다.