2022. 4. 28. 20:00ㆍ던전앤파이터/던파 타임라인 훔쳐보기
타임라인 불러오기에 들어가기 앞서,
여태껏 작성해왔던 코드 전문을 보완하고 정리하는 작업을 진행해보자.
우선, 우리는 여태껏 "말걸면"이라는 검색어로만 검색을 진행해왔다.
하지만 해당 검색어를 통해 찾을 수 있는 데이터는 너무나도 적다.
우리는 최대한 많은 데이터를 확보하는 것이 목표이므로,
생각나는 검색어를 리스트(List)로 저장하여 그것을 검색어로 활용하여
캐릭터의 서버와 이름까지 추출하는 과정을 진행해보겠다.
KEYWORDS = ["말걸면", "레이드돌고", "케처", "buffalo", "카쉬파"]
먼저, 검색어를 리스트 타입의 전역변수로 초기화한다.
실제로 사용할 경우는, 훨씬 더 많은 검색어를 생각하여 초기화하면 된다.
# 이전까지 사용했던 URL 인코딩 함수 #
def urlEncoding(keyword_):
encoded_keyword = parse.quote(keyword_)
return encoded_keyword
# 우리가 새로 사용할 URL 인코딩 함수 #
def urlEncoding(keyword_):
encoded_keyword = []
for word in keyword_:
encoded_keyword.append(parse.quote(word))
return encoded_keyword
이전에는 "말걸면"이라는 검색어 하나만을 사용한다는 가정 하에 코드 작성이 진행되었으나,
이제는 여러 개의 검색어를 사용할 것이므로 검색어를
URL 인코딩 시켜주는 함수를 수정해보도록 하자.
먼저, urlEncoding 함수로 전달되는 인자(keyword_)는
당연히 리스트 타입일 것이다. (이전에는 "말걸면"이라는 문자열 한 개였다.)
이 리스트 타입(keyword_)에 들어있는 문자열 각각(word)을
for문을 이용하여 (for word in keyword_)
URL 인코딩 시킨 뒤 반환하는 작업을 수행시키자.
수정한 함수를 사용하면 위의 디버깅 사진과 같이 KEYWORDS에 저장한
리스트 타입인 encoded_keyword에는 5 개의 단어가 URL 인코딩된 상태로
저장되어 있음을 확인할 수 있다.
# 이전까지 사용했던 모험단 URL 추출 함수 #
def advURL(adv_keyword):
adv_url_ = []
encoded_keyword = urlEncoding(adv_keyword)
try:
source_code = urlopen(ADV_SEARCH + encoded_keyword).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Wrapper-sc-1noqpd4-1 gfctoN').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs and 'class' in value_a.attrs:
if value_a.attrs['class'] == ["Row-sc-jrfk9d-1", "hiKazl"]:
adv_url_.append(HOMEPAGE_URL + value_a.attrs['href'])
except:
print("Error occurred on extracting adventure's URL process.")
return adv_url_
# 우리가 새로 사용할 모험단 URL 추출 함수 #
def advURL(adv_keyword):
adv_url_ = []
encoded_keyword = urlEncoding(adv_keyword)
for word in encoded_keyword:
try:
source_code = urlopen(ADV_SEARCH + word).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Wrapper-sc-1noqpd4-1 gfctoN').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs and 'class' in value_a.attrs:
if value_a.attrs['class'] == ["Row-sc-jrfk9d-1", "hiKazl"]:
adv_url_.append(HOMEPAGE_URL + value_a.attrs['href'])
except:
print("Error occurred on extracting adventure URL process.")
return adv_url_
ADV_SEARCH = "https://dunfamoa.com/characters/adventure?search="
이번에는 모험단 URL 추출 함수 부분이다.
여기서는 이미 우리가 모험단 URL을 리스트 형식으로 저장해왔기 때문에
따로 리스트 변수를 추가로 선언할 필요 없이 이전 사용하던 리스트(adv_url_)를
그대로 사용하면 된다.
수정된 URL 인코딩 함수에서 리스트 타입의 값이 반환될 것이기 때문에
(encoded_keyword = urlEncoding(adv_keyword))
반환된 값을 갖고 있는 encoded_keyword의 문자열 각각(word)에 대하여
(for word in encoded_keyword)
ADV_SEARCH에 이어붙여서(ADV_SEARCH + word)
이전과 같은 작업들을 진행해나가면 된다.
캐릭터 추출 부분은 복수의 사이트를 크롤링한다는 가정 하에
작성되었기 때문에 수정할 필요가 없다.
마지막으로, 향후 코드가 계속 추가되며 지금보다 난잡해질 수 있기 때문에
미리 코드를 정리하는 작업을 진행해보자.
먼저, 우리는 코드가 어떻게 동작하는지 생각해볼 필요가 있다.
위 사진과 같이 하나하나 나누어보면,
- 검색어를 입력으로 한다.
- 검색어가 URL로써 기능할 수 있도록 검색어를 URL 인코딩한다. (def urlEncoding())
- 인코딩된 입력을 사용하여 모험단의 URL을 추출한다. (def advURL())
- 추출한 모험단 URL 내 존재하는 캐릭터들의 서버와 이름을 추출한다. (def charList())
- 추출한 서버와 이름들을 dictionary 타입으로 저장한다. (def charDict())
결국 위 사진과 같이 2~3번은 모험단 URL을 추출하기 위한 과정,
4~5번은 캐릭터들의 서버와 이름을 추출하기 위한 과정이기 때문에
이 두 가지 과정을 각각 하나의 클래스로 묶도록 하자.
class extractAdv:
def __init__(self, adv_keyword):
self.adv_keyword = adv_keyword
def urlEncoding(self, keyword_):
encoded_keyword = []
for word in keyword_:
encoded_keyword.append(parse.quote(word))
return encoded_keyword
#---------검색어를 URL 인코딩----------#
def advURL(self):
adv_url_ = []
encoded_keyword = self.urlEncoding(self.adv_keyword)
for word in encoded_keyword:
try:
source_code = urlopen(ADV_SEARCH + word).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Wrapper-sc-1noqpd4-1 gfctoN').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs and 'class' in value_a.attrs:
if value_a.attrs['class'] == ["Row-sc-jrfk9d-1", "hiKazl"]:
adv_url_.append(HOMEPAGE_URL + value_a.attrs['href'])
except:
print("Error occurred on extracting adventure URL process.")
return adv_url_
#-----------------------던파모아활용(1~3)-----------------------#
urlEncoding 함수와 advURL 함수를 extractAdv라는 클래스의 메소드로 만들었다.
클래스를 초기화할 때, 검색어(adv_keyword)를 인자로 받아
이를 self.adv_keyword에 저장하여
클래스 내 어느 함수에서라도 self.adv_keyword를
사용할 수 있도록 __init__ 함수에서 초기화하였다.
기존 advURL 함수가 인자로 요구했던 부분은 extractAdv가 초기화될 때,
(extractAdv 클래스 객체를 만들 때)
인자로 받기 때문에 필요가 없어졌으니 지우도록 하자.
class extractChar:
def __init__(self, adv_url):
self.adv_url = adv_url
def charDict(self, char_url_):
char_info = char_url_.split('/')
char_dict = {'serverId':char_info[2], 'characterName':char_info[3]}
return char_dict
#------------------캐릭터 이름 및 서버 저장-------------------#
def charList(self):
char_list_ = []
for url in self.adv_url:
try:
source_code = urlopen(url).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Outer-sc-1cu42wh-3 kCIUEG').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs:
char_url = value_a.attrs['href']
char_list_.append(self.charDict(char_url))
except:
print("Error occurred on extracting character's name process.")
return char_list_
#---------------------------던파모아활용(4)----------------------------#
charDict 함수와 charList 함수를 extractChar라는 클래스의 메소드로 만들었다.
클래스를 초기화할 때, 모험단 주소 리스트(adv_url)를 인자로 받아
이를 self.adv_url에 저장하여
클래스 내 어느 함수에서라도 self.adv_url을
사용할 수 있도록 __init__ 함수에서 초기화하였다.
기존에 charList 함수가 인자로 요구했던 부분은 extractChar가 초기화될 때,
(extractChar 클래스 객체를 만들 때)
인자로 받기 때문에 필요가 없어졌으니 지우도록 하자.
그리고 더욱 더 깔끔하게 정리하기 위해
홈페이지 주소같은 const들과( ex) consts.py 만들어 저장. )
더 이상 확인할 필요가 사라진 두 개의 클래스를 동일 디렉토리 내
새로운 파일로 만들어서 저장하자. ( ex) extracting.py 만들어 저장. )
# consts.py
ADV_SEARCH = "https://dunfamoa.com/characters/adventure?search="
HOMEPAGE_URL = "https://dunfamoa.com"
# extracting.py
from consts import*
from urllib import parse
from urllib.request import urlopen
from bs4 import BeautifulSoup
class extractAdv:
def __init__(self, adv_keyword):
self.adv_keyword = adv_keyword
def urlEncoding(self, keyword_):
encoded_keyword = []
for word in keyword_:
encoded_keyword.append(parse.quote(word))
return encoded_keyword
#---------검색어를 URL 인코딩----------#
def advURL(self):
adv_url_ = []
encoded_keyword = self.urlEncoding(self.adv_keyword)
for word in encoded_keyword:
try:
source_code = urlopen(ADV_SEARCH + word).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Wrapper-sc-1noqpd4-1 gfctoN').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs and 'class' in value_a.attrs:
if value_a.attrs['class'] == ["Row-sc-jrfk9d-1", "hiKazl"]:
adv_url_.append(HOMEPAGE_URL + value_a.attrs['href'])
except:
print("Error occurred on extracting adventure URL process.")
return adv_url_
#-----------------------던파모아활용(1~3)-----------------------#
class extractChar:
def __init__(self, adv_url):
self.adv_url = adv_url
def charDict(self, char_url_):
char_info = char_url_.split('/')
char_dict = {'serverId':char_info[2], 'characterName':char_info[3]}
return char_dict
#------------------캐릭터 이름 및 서버 저장-------------------#
def charList(self):
char_list_ = []
for url in self.adv_url:
try:
source_code = urlopen(url).read()
soup = BeautifulSoup(source_code, "html.parser")
tag_a = soup.find('div', class_='Outer-sc-1cu42wh-3 kCIUEG').find_all('a')
for value_a in tag_a:
if 'href' in value_a.attrs:
char_url = value_a.attrs['href']
char_list_.append(self.charDict(char_url))
except:
print("Error occurred on extracting character's name process.")
return char_list_
#---------------------------던파모아활용(4)----------------------------#
# main.py
# Authorized by 죤씨나
from consts import*
from extracting import*
KEYWORDS = ["말걸면", "레이드돌고", "케처", "buffalo", "카쉬파"]
if __name__ == "__main__":
adv_url = extractAdv(KEYWORDS).advURL()
char_list = extractChar(adv_url).charList()
for data in char_list:
print(data)
지금까지 작성했던 코드들을
consts.py, extracting.py, main.py
3 개로 분할하였다.
동작이 잘 되는지 확인해보자.
동작이 잘 된다.
이제 진짜 타임라인 불러오기로 가보자.
'던전앤파이터 > 던파 타임라인 훔쳐보기' 카테고리의 다른 글
[웹크롤링] 인터넷에서 캐릭터 정보를 가져오자 - 던파모아 활용(4) (0) | 2022.04.27 |
---|---|
[웹크롤링] 인터넷에서 캐릭터 정보를 가져오자 - 던파모아 활용(3) (0) | 2022.04.26 |
[웹크롤링] 인터넷에서 캐릭터 정보를 가져오자 - 던파모아 활용(2) (0) | 2022.04.26 |
[웹크롤링] 인터넷에서 캐릭터 정보를 가져오자 - 던파모아 활용(1) (0) | 2022.04.26 |
[웹크롤링] 네오플 오픈 API 활용 - 캐릭터 검색(2) (0) | 2022.04.25 |