이론적으로 철저하게 당했다.
해결한 문제
시간을 크게 줄였다. 2분 30초에서 10초 정도까지 줄였다.
multiprocessing.pool을 사용했는데, 이게 GPU 사용해서 병렬적으로 처리하는 코드라고 한다. 이론적인것을 잘 모르지만, 이해하려 노력해봤다. 참고로 아래의 코드는 작동하지 않는다.
마주친 문제
페이지의 마지막 번호를 알아내야 한다.
기존에는 while문으로 1부터 42까지 돌려서 41이 마지막인 것을 알아냈지만, pool함수를 써야 하기에 인자를 미리 집어넣어주어야 했다. 그래서 getPageNumberFromcoinmarketcal()함수를 만들어서 마지막 페이지 정보를 크롤링 하도록 했다. 잘 찾아보니깐 >> 버튼에 마지막 페이지번호로 가는 a태그가 있어서 거기서 정보를 얻어냈다.
변수 공유를 해야한다.
여기를 해결 못 했다. 병렬처리를 할때 변수는 각각의 메모리를 소비하고 처리 후에 그것이 사라진다. 즉 할당된 주소가 사라져 변수에 저장을 했더라도 결국에는 저장이 안된다. 이건 철저히 이론적인 문제였는데, 처음엔 이 사실을 몰라서 전역 변수로 설정하면 되겠지 싶어서 전역변수로 만들었다. 하지만 후에 그것이 아님을 깨닫고 다른 방법을 찾으려 했다. 결국에는 아직 해결을 못했고 그 방법에 대해서만 조금 알게 되었는데, manger()함수로 변수를 선언해 사용하면 된다고 한다. 하지만 잘 안된다.
전체 코드
from urllib.request import urlopen
from bs4 import BeautifulSoup
import multiprocessing
import time
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 getPageNumberFromcoinmarketcal():
html = urlopen("https://coinmarketcal.com/en/")
soup = BeautifulSoup(html, "html.parser")
coin_maxpage_data = soup.select("a[class='page-link rounded']").pop()
coin_maxpage = re.findall("\d+", str(coin_maxpage_data))
return int(coin_maxpage.pop())
def packingDataFromcoinmarketcal(page_number):
global result
url = "https://coinmarketcal.com/en/" + "?page=" + str(page_number)
html = urlopen(url)
# 사이트에 문제가 있으면 함수 종료
if html.status != 200:
return
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))
# 전처리 이름[이름, 태그], 호재 시간[년, 월, 일], 추가된 시간[년, 월, 일], 제목[문자열], 상세내용[문자열]
# 전처리 후 패킹
one_page_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
}
one_page_data.append(item_coin)
result.append(one_page_data)
if __name__ == '__main__':
manager = multiprocessing.Manager()
result = manager.list()
pool = multiprocessing.Pool(processes=8)
start_time = time.time()
max_page = getPageNumberFromcoinmarketcal()
pool.map(packingDataFromcoinmarketcal, range(1, max_page))
print(time.time() - start_time)
print(result)
해결해야 할 문제
병렬처리 시, 변수에 최종 결과 담기
'프로젝트 > COHO - 코인 호재 캘린더' 카테고리의 다른 글
[Django] 코호 - 실시간 코인 호재 모음 PROC 6 (0) | 2021.03.19 |
---|---|
[Django] 코호 - 실시간 코인 호재 모음 PROC 5 (0) | 2021.03.18 |
[Django] 코호 - 실시간 코인 호재 모음 PROC 4 (0) | 2021.03.17 |
[Django] 코호 - 실시간 코인 호재 모음 PROC 2 (0) | 2021.03.17 |
[Django] 코호 - 실시간 코인 호재 모음 PROC 1 (1) | 2021.03.16 |