Skip to content

Commit

Permalink
Formatted with black
Browse files Browse the repository at this point in the history
  • Loading branch information
Re-st authored and github-actions[bot] committed Oct 13, 2023
1 parent c1562e9 commit 59f1559
Show file tree
Hide file tree
Showing 9 changed files with 763 additions and 334 deletions.
116 changes: 67 additions & 49 deletions scrap/local_councils/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
party_keywords = getPartyList()
party_keywords.append("무소속")


def find(soup, element, class_):
if class_ is None:
return soup.find(element)
Expand All @@ -29,12 +30,12 @@ def get_profiles(soup, element, class_, memberlistelement, memberlistclass_):
# 의원 목록 사이트에서 의원 프로필을 가져옴
if memberlistelement is not None:
try:
soup = find_all(soup, memberlistelement,
class_=memberlistclass_)[0]
soup = find_all(soup, memberlistelement, class_=memberlistclass_)[0]
except Exception:
raise RuntimeError('[basic.py] 의원 목록 사이트에서 의원 프로필을 가져오는데 실패했습니다.')
raise RuntimeError("[basic.py] 의원 목록 사이트에서 의원 프로필을 가져오는데 실패했습니다.")
return find_all(soup, element, class_)


def getDataFromAPI(url_format, data_uid, name_id, party_id) -> Councilor:
# API로부터 의원 정보를 가져옴
url = url_format.format(data_uid)
Expand All @@ -45,36 +46,33 @@ def getDataFromAPI(url_format, data_uid, name_id, party_id) -> Councilor:
)



def get_name(profile, element, class_, wrapper_element, wrapper_class_):
# 의원 프로필에서 의원 이름을 가져옴
if wrapper_element is not None:
profile = find_all(profile, wrapper_element, class_=wrapper_class_)[0]
name_tag = find(profile, element, class_)
if name_tag.find('span'):
if name_tag.find("span"):
name_tag = copy.copy(name_tag)
# span 태그 안의 것들을 다 지움
for span in name_tag.find_all('span'):
for span in name_tag.find_all("span"):
span.decompose()
name = name_tag.get_text(strip=True) if name_tag else "이름 정보 없음"

# name은 길고 그 중 strong태그 안에 이름이 있는 경우. 은평구, 수원시 등.
if name_tag.strong is not None:
name = name_tag.strong.get_text(
strip=True) if name_tag.strong else "이름 정보 없음"
name = name.split('(')[0].split(
':')[-1].strip() # 이름 뒷 한자이름, 앞 '이 름:' 제거
name = name_tag.strong.get_text(strip=True) if name_tag.strong else "이름 정보 없음"
name = name.split("(")[0].split(":")[-1].strip() # 이름 뒷 한자이름, 앞 '이 름:' 제거
# TODO : 만약 이름이 우연히 아래 단어를 포함하는 경우를 생각해볼만 함.
if len(name) > 3:
# 수식어가 이름 앞이나 뒤에 붙어있는 경우
for keyword in ['부의장', '의원', '의장']: # 119, 강서구 등
for keyword in ["부의장", "의원", "의장"]: # 119, 강서구 등
if keyword in name:
name = name.replace(keyword, '').strip()
name = name.replace(keyword, "").strip()
for keyword in party_keywords:
if keyword in name: # 인천 서구 등
name = name.replace(keyword, '').strip()
name = name.replace(keyword, "").strip()
break
name = name.split(' ')[0] # 이름 뒤에 직책이 따라오는 경우
name = name.split(" ")[0] # 이름 뒤에 직책이 따라오는 경우
return name


Expand All @@ -92,37 +90,42 @@ def goto_profilesite(profile, wrapper_element, wrapper_class_, wrapper_txt, url)
# 프로필보기 링크 가져오기
profile_link = find(profile, wrapper_element, class_=wrapper_class_)
if wrapper_txt is not None:
profile_links = find_all(profile, 'a', class_=wrapper_class_)
profile_link = [
link for link in profile_links if link.text == wrapper_txt][0]
profile_links = find_all(profile, "a", class_=wrapper_class_)
profile_link = [link for link in profile_links if link.text == wrapper_txt][0]
if profile_link is None:
raise RuntimeError('[basic.py] 의원 프로필에서 프로필보기 링크를 가져오는데 실패했습니다.')
raise RuntimeError("[basic.py] 의원 프로필에서 프로필보기 링크를 가져오는데 실패했습니다.")
# if base_url[-1] != '/':
# base_url = base_url + '/'
profile_url = base_url + profile_link['href']
profile_url = base_url + profile_link["href"]
try:
profile = get_soup(profile_url, verify=False)
except Exception:
raise RuntimeError('[basic.py] \'//\'가 있진 않나요?', ' url: ', profile_url)
raise RuntimeError("[basic.py] '//'가 있진 않나요?", " url: ", profile_url)
return profile


def get_party(profile, element, class_, wrapper_element, wrapper_class_, wrapper_txt, url):
def get_party(
profile, element, class_, wrapper_element, wrapper_class_, wrapper_txt, url
):
# 의원 프로필에서 의원이 몸담는 정당 이름을 가져옴
if wrapper_element is not None:
profile = goto_profilesite(
profile, wrapper_element, wrapper_class_, wrapper_txt, url)
party_pulp_list = list(filter(lambda x: regex_pattern.search(
str(x)), find_all(profile, element, class_)))
profile, wrapper_element, wrapper_class_, wrapper_txt, url
)
party_pulp_list = list(
filter(
lambda x: regex_pattern.search(str(x)), find_all(profile, element, class_)
)
)
if party_pulp_list == []:
raise RuntimeError('[basic.py] 정당정보 regex 실패')
raise RuntimeError("[basic.py] 정당정보 regex 실패")
party_pulp = party_pulp_list[0]
party_string = party_pulp.get_text(strip=True).split(' ')[-1]
party_string = party_pulp.get_text(strip=True).split(" ")[-1]
while True:
if (party := extract_party(party_string)) is not None:
return party
if (party_pulp := party_pulp.find_next('span')) is not None:
party_string = party_pulp.text.strip().split(' ')[-1]
if (party_pulp := party_pulp.find_next("span")) is not None:
party_string = party_pulp.text.strip().split(" ")[-1]
else:
return "[basic.py] 정당 정보 파싱 불가"

Expand All @@ -131,44 +134,57 @@ def get_party_easy(profile, wrapper_element, wrapper_class_, wrapper_txt, url):
# 의원 프로필에서 의원이 몸담는 정당 이름을 가져옴
if wrapper_element is not None:
profile = goto_profilesite(
profile, wrapper_element, wrapper_class_, wrapper_txt, url)
profile, wrapper_element, wrapper_class_, wrapper_txt, url
)
party = extract_party(profile.text)
assert (party is not None)
assert party is not None
return party


def scrap_basic(url, cid, args: ScrapBasicArgument, encoding='utf-8') -> ScrapResult:
'''의원 상세약력 스크랩
def scrap_basic(url, cid, args: ScrapBasicArgument, encoding="utf-8") -> ScrapResult:
"""의원 상세약력 스크랩
:param url: 의원 목록 사이트 url
:param n: 의회 id
:param encoding: 받아온 soup 인코딩
:return: 의원들의 이름과 정당 데이터를 담은 ScrapResult 객체
'''
"""
soup = get_soup(url, verify=False, encoding=encoding)
councilors: list[Councilor] = []

profiles = get_profiles(soup, args.pf_elt, args.pf_cls,
args.pf_memlistelt, args.pf_memlistcls)
print(cid, '번째 의회에는,', len(profiles), '명의 의원이 있습니다.') # 디버깅용.
profiles = get_profiles(
soup, args.pf_elt, args.pf_cls, args.pf_memlistelt, args.pf_memlistcls
)
print(cid, "번째 의회에는,", len(profiles), "명의 의원이 있습니다.") # 디버깅용.

for profile in profiles:
name = party = ''
name = party = ""
try:
name = get_name(profile, args.name_elt, args.name_cls,
args.name_wrapelt, args.name_wrapcls)
name = get_name(
profile,
args.name_elt,
args.name_cls,
args.name_wrapelt,
args.name_wrapcls,
)
except Exception as e:
raise RuntimeError(
'[basic.py] 의원 이름을 가져오는데 실패했습니다. 이유 : ' + str(e))
raise RuntimeError("[basic.py] 의원 이름을 가져오는데 실패했습니다. 이유 : " + str(e))
try:
party = get_party(profile, args.pty_elt, args.pty_cls,
args.pty_wrapelt, args.pty_wrapcls, args.pty_wraptxt, url)
party = get_party(
profile,
args.pty_elt,
args.pty_cls,
args.pty_wrapelt,
args.pty_wrapcls,
args.pty_wraptxt,
url,
)
except Exception as e:
try:
party = get_party_easy(
profile, args.pty_wrapelt, args.pty_wrapcls, args.pty_wraptxt, url)
profile, args.pty_wrapelt, args.pty_wrapcls, args.pty_wraptxt, url
)
except Exception:
raise RuntimeError(
'[basic.py] 의원 정당을 가져오는데 실패했습니다. 이유: ' + str(e))
raise RuntimeError("[basic.py] 의원 정당을 가져오는데 실패했습니다. 이유: " + str(e))
councilors.append(Councilor(name=name, party=party))

return ScrapResult(
Expand All @@ -177,7 +193,9 @@ def scrap_basic(url, cid, args: ScrapBasicArgument, encoding='utf-8') -> ScrapRe
councilors=councilors,
)

if __name__ == '__main__':

if __name__ == "__main__":
args3 = ScrapBasicArgument(
pf_elt='div', pf_cls='profile', name_elt='em', name_cls='name', pty_elt='em')
print(scrap_basic('https://www.yscl.go.kr/kr/member/name.do', 3, args3)) # 서울 용산구
pf_elt="div", pf_cls="profile", name_elt="em", name_cls="name", pty_elt="em"
)
print(scrap_basic("https://www.yscl.go.kr/kr/member/name.do", 3, args3)) # 서울 용산구
2 changes: 1 addition & 1 deletion scrap/local_councils/gwangju.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"""
from scrap.utils.types import CouncilType, Councilor, ScrapResult
from scrap.utils.requests import get_soup
from scrap.local_councils.basic import *
from scrap.local_councils.basic import *
100 changes: 67 additions & 33 deletions scrap/local_councils/gyeonggi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,108 +4,142 @@
from scrap.utils.requests import get_soup
from scrap.local_councils.basic import *


def get_profiles_88(soup, element, class_, memberlistelement, memberlistclass_):
# 의원 목록 사이트에서 의원 프로필을 가져옴
if memberlistelement is not None:
try:
soup = soup.find_all(memberlistelement, id=memberlistclass_)[0]
except Exception:
raise RuntimeError('[basic.py] 의원 목록 사이트에서 의원 프로필을 가져오는데 실패했습니다.')
raise RuntimeError("[basic.py] 의원 목록 사이트에서 의원 프로필을 가져오는데 실패했습니다.")
return soup.find_all(element, class_)


def get_party_88(profile, element, class_, wrapper_element, wrapper_class_, url):
# 의원 프로필에서 의원이 몸담는 정당 이름을 가져옴
if wrapper_element is not None:
parsed_url = urlparse(url)
base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
# 프로필보기 링크 가져오기
profile_link = find(profile, wrapper_element, class_=wrapper_class_).find('a')
profile_url = base_url + profile_link['href']
profile = get_soup(profile_url, verify=False, encoding='euc-kr')
party_pulp_list = list(filter(lambda x: regex_pattern.search(str(x)), find_all(profile, element, class_)))
if party_pulp_list == []: raise RuntimeError('[basic.py] 정당정보 regex 실패')
profile_link = find(profile, wrapper_element, class_=wrapper_class_).find("a")
profile_url = base_url + profile_link["href"]
profile = get_soup(profile_url, verify=False, encoding="euc-kr")
party_pulp_list = list(
filter(
lambda x: regex_pattern.search(str(x)), find_all(profile, element, class_)
)
)
if party_pulp_list == []:
raise RuntimeError("[basic.py] 정당정보 regex 실패")
party_pulp = party_pulp_list[0]
party_string = party_pulp.get_text(strip=True).split(' ')[-1]
party_string = party_pulp.get_text(strip=True).split(" ")[-1]
while True:
if (party := extract_party(party_string)) is not None:
return party
if (party_pulp := party_pulp.find_next('span')) is not None:
party_string = party_pulp.text.strip().split(' ')[-1]
if (party_pulp := party_pulp.find_next("span")) is not None:
party_string = party_pulp.text.strip().split(" ")[-1]
else:
return "[basic.py] 정당 정보 파싱 불가"


def scrap_88(url, args: ScrapBasicArgument) -> ScrapResult:
'''의원 상세약력 스크랩
"""의원 상세약력 스크랩
:param url: 의원 목록 사이트 url
:param args: ScrapBasicArgument 객체
:return: 의원들의 이름과 정당 데이터를 담은 ScrapResult 객체
'''
"""
cid = 88
encoding = 'euc-kr'
encoding = "euc-kr"
soup = get_soup(url, verify=False, encoding=encoding)
councilors: list[Councilor] = []
party_in_main_page = any(keyword in soup.text for keyword in party_keywords)
profiles = get_profiles_88(soup, args.pf_elt, args.pf_cls, args.pf_memlistelt, args.pf_memlistcls)
print(cid, '번째 의회에는,', len(profiles), '명의 의원이 있습니다.') # 디버깅용.
profiles = get_profiles_88(
soup, args.pf_elt, args.pf_cls, args.pf_memlistelt, args.pf_memlistcls
)
print(cid, "번째 의회에는,", len(profiles), "명의 의원이 있습니다.") # 디버깅용.

for profile in profiles:
name = get_name(profile, args.name_elt, args.name_cls, args.name_wrapelt, args.name_wrapcls)
party = ''
name = get_name(
profile, args.name_elt, args.name_cls, args.name_wrapelt, args.name_wrapcls
)
party = ""
try:
party = get_party_88(profile, args.pty_elt, args.pty_cls, args.pty_wrapelt, args.pty_wrapcls, url)
party = get_party_88(
profile,
args.pty_elt,
args.pty_cls,
args.pty_wrapelt,
args.pty_wrapcls,
url,
)
except Exception:
party = get_party_easy(profile, args.pty_wrapelt, args.pty_wrapcls, args.pty_wraptxt, url)
party = get_party_easy(
profile, args.pty_wrapelt, args.pty_wrapcls, args.pty_wraptxt, url
)

councilors.append(Councilor(name=name, party=party))

return ScrapResult(
council_id=str(cid),
council_type=CouncilType.LOCAL_COUNCIL,
councilors=councilors
councilors=councilors,
)


def get_party_103(profile, element, class_, wrapper_element, wrapper_class_, url):
# 의원 프로필에서 의원이 몸담는 정당 이름을 가져옴
if wrapper_element is not None:
parsed_url = urlparse(url)
base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
# 프로필보기 링크 가져오기
profile_link = profile.find(wrapper_element, class_=wrapper_class_)
profile_url = base_url + '/member/' + profile_link['href']
profile_url = base_url + "/member/" + profile_link["href"]
profile = get_soup(profile_url, verify=False)
party_pulp_list = list(filter(lambda x: regex_pattern.search(str(x)), find_all(profile, element, class_)))
if party_pulp_list == []: raise RuntimeError('[basic.py] 정당정보 regex 실패')
party_pulp_list = list(
filter(
lambda x: regex_pattern.search(str(x)), find_all(profile, element, class_)
)
)
if party_pulp_list == []:
raise RuntimeError("[basic.py] 정당정보 regex 실패")
party_pulp = party_pulp_list[0]
party_string = party_pulp.get_text(strip=True).split(' ')[-1]
party_string = party_pulp.get_text(strip=True).split(" ")[-1]
while True:
if (party := extract_party(party_string)) is not None:
return party
if (party_pulp := party_pulp.find_next('span')) is not None:
party_string = party_pulp.text.strip().split(' ')[-1]
if (party_pulp := party_pulp.find_next("span")) is not None:
party_string = party_pulp.text.strip().split(" ")[-1]
else:
return "[basic.py] 정당 정보 파싱 불가"


def scrap_103(url, args: ScrapBasicArgument) -> ScrapResult:
'''의원 상세약력 스크랩
"""의원 상세약력 스크랩
:param url: 의원 목록 사이트 url
:param args: ScrapBasicArgument 객체
:return: 의원들의 이름과 정당 데이터를 담은 ScrapResult 객체
'''
"""
cid = 103
soup = get_soup(url, verify=False)
councilors: list[Councilor] = []
party_in_main_page = any(keyword in soup.text for keyword in party_keywords)
profiles = get_profiles_88(soup, args.pf_elt, args.pf_cls, args.pf_memlistelt, args.pf_memlistcls)
print(cid, '번째 의회에는,', len(profiles), '명의 의원이 있습니다.') # 디버깅용.
profiles = get_profiles_88(
soup, args.pf_elt, args.pf_cls, args.pf_memlistelt, args.pf_memlistcls
)
print(cid, "번째 의회에는,", len(profiles), "명의 의원이 있습니다.") # 디버깅용.

for profile in profiles:
name = get_name(profile, args.name_elt, args.name_cls, args.name_wrapelt, args.name_wrapcls)
party = get_party_103(profile, args.pty_elt, args.pty_cls, args.pty_wrapelt, args.pty_wrapcls, url)
name = get_name(
profile, args.name_elt, args.name_cls, args.name_wrapelt, args.name_wrapcls
)
party = get_party_103(
profile, args.pty_elt, args.pty_cls, args.pty_wrapelt, args.pty_wrapcls, url
)

councilors.append(Councilor(name=name, party=party))

return ScrapResult(
council_id=str(cid),
council_type=CouncilType.LOCAL_COUNCIL,
councilors=councilors
)
councilors=councilors,
)
Loading

0 comments on commit 59f1559

Please sign in to comment.