JJUNNAK's

[ Android ] "급똥" _ 04. 데이터 분석 (2) 본문

PROJECT/급똥

[ Android ] "급똥" _ 04. 데이터 분석 (2)

최낙준 2023. 1. 10. 01:24

[ 이전 글 ]

https://jjunnak.tistory.com/16

이전 글에서 발견된 문제들을 고려해서 코드를 작성했다.


데이터 분할

 
import pandas as pd
from bs4 import BeautifulSoup
from urllib.request import urlopen

# [ 옵션 설정 ]
print(" 원하는 노선을 선택하세요.")
print(" [ 1~9 호선 : 1~9 ] , [ 경의중앙 : K4 ] , [ 분당선 : D1 ]")
line = str(input("노선 : "))

# [ 변수 지정 ]
result_list = [] # 출력할 결과물 리스트
oper = [] # 기관코드
st = [] # 역 코드
name = [] # 역 이름
# 담당기관이 2곳일 경우 대비
st1 = []
name1 = []
st2 = []
name2 = []

# 엑셀에서 원하는 노선의 데이터만 부르는 함수
def filter(a,b,c,d):
    if a != 0:
        oper.append(d)
        for i in b:
            st.append(i)
        for y in c:
            name.append(y)
# [ 엑셀 데이터 분할 ]
# 운영기관,역사 코드정보 엑셀파일
data = pd.read_excel("C:/Users/nackjun/Crolling_DataFile/info_subway_api.xlsx", engine='openpyxl')
# 노선 별 데이터
data = data[data["LN_CD"]==line]

 

 

우선 엑셀을 불러오고나서 내가 원하는 노선의 모든데이터를 data변수에 담았다

그 후 내가 사용할 1~9호선 , 경의중앙선, 분당선의 담당기관 코드인

( 코레일 : KR ) ( 서울교통공사 : S1, S5 ) ( 서울메트로9 : S9 ), ( DX라인 : DX ) 별로

데이터를 분할해 두었다.

 

# S1 : 서울교통공사
S1 = data[data["RAIL_OPR_ISTT_CD"]=="S1"]
try:
    S1_oper = list(S1["RAIL_OPR_ISTT_CD"])[0]
except:
    S1_oper = ""
S1_ln = len(list(S1["LN_CD"]))
S1_name = list(S1["STIN_NM"]) #역이름
S1_st = list(S1["STIN_CD"]) # 역코드


# KR : 코레일
KR = data[data["RAIL_OPR_ISTT_CD"]=="KR"]
try:
    KR_oper = list(KR["RAIL_OPR_ISTT_CD"])[0]
except:
    KR_oper = ""
KR_ln = len(list(KR["LN_CD"]))
KR_name = list(KR["STIN_NM"])
KR_st = list(KR["STIN_CD"])

# S5 : 서울도시철도
S5 = data[data["RAIL_OPR_ISTT_CD"]=="S5"]
try:
    S5_oper = list(S5["RAIL_OPR_ISTT_CD"])[0]
except:
    S5_oper = ""
S5_ln = len(list(S5["LN_CD"]))
S5_name = list(S5["STIN_NM"])
S5_st = list(S5["STIN_CD"])

# S9 : 서울 메트로9
S9 = data[data["RAIL_OPR_ISTT_CD"]=="S9"]
try:
    S9_oper = list(S9["RAIL_OPR_ISTT_CD"])[0]
except:
    S9_oper = ""
S9_ln = len(list(S9["LN_CD"]))
S9_name = list(S9["STIN_NM"])
S9_st = list(S9["STIN_CD"])

# DX : DX라인 (분당선)
DX = data[data["RAIL_OPR_ISTT_CD"]=="DX"]
try:
    DX_oper = list(DX["RAIL_OPR_ISTT_CD"])[0]
except:
    DX_oper = ""
DX_ln = len(list(DX["LN_CD"]))
DX_name = list(DX["STIN_NM"])
DX_st = list(DX["STIN_CD"])

 

])

위의 try문은 내가 선택한 노선을 담당하지 않는 기관의 경우에는 데이터가 들어있지 않아

??_oper = list(??["RAIL_OPR_ISTT_CD"])[0] 부분에서

리스트 인덱스 오류가 발생하기 때문에 예외처리를 해두었다.

 
# 엑셀에서 원하는 노선의 데이터만 부르는 함수
def filter(a,b,c,d):
    if a != 0:
        oper.append(d)
        for i in b:
            st.append(i)
        for y in c:
            name.append(y)
# 엑셀에서 원하는 노선의 데이터 설정
filter(KR_ln,KR_st,KR_name,KR_oper)
filter(S1_ln,S1_st,S1_name,S1_oper)
filter(S5_ln,S5_st,S5_name,S5_oper)
filter(S9_ln,S9_st,S9_name,S9_oper)
filter(DX_ln,DX_st,DX_name,DX_oper)

 

정의한 filter 함수에서 매개변수 a 인 ??_ln 에는 내가 설정한 노선의 모든 데이터에서

?? 기관 부분의 정보가 담겨있는데

이 a 가 != 0 이라면 정보가 담겨있다는 뜻이니까 후에 데이터 크롤링할때 사용할

oper 리스트에 정보를 저장한다.

또한 ?? 기관의 분할된 데이터들을 st(역코드), name(역이름) 에 저장한다


데이터 추출

이제 대망의 데이터를 추출할 차례이다.

출력 형태를 다음글에서 사용할 안드로이드 스튜디오의 listview 에 데이터를 추가할 코드 형식으로

만들었다

( 이게 아니였다면 아직도 일일히 데이터 집어넣고 있었겟지.. 킹갓파이썬!)

 
# [ 요청 변수 ]
endpoint = "https://openapi.kric.go.kr/openapi/convenientInfo/stationToilet"
key = "서비스키"
format = "&format=xml"
line_code = "&lnCd=" + line
st_code ="&stinCd="
# [ 데이터 추출 ]
# >> 관할 공사가 한곳인 경우 (st,name,oper[0]) <<
if len(oper) < 2:
    for i in range(len(st)):
        rail_oper = "&railOprIsttCd="
        url = endpoint + key + format + rail_oper + oper[0] + line_code + st_code + st[i]
        html = urlopen(url)
        obj = BeautifulSoup(html, "html.parser")

        try:  # api 안에 정보가 없는경우 예외처리
            gate = obj.find("gateinotdvnm").text + "부"  # 게이트 내외
            location = obj.find('dtlloc').text  # 화장실 위치
        except:
            gate = "정보없음"
            location = "정보없음"
        # 노선이름 재설정
        if line == "D1":
            line = "분당"
        elif line == "K4":
            line = "경의중앙"
        # 입력할 코드 양식 a
        a = "list.add(" + '"' + "[" + line + "] " + "{ " + name[
            i] + " } " + " " + "게이트 " + gate + " / " + location + ' ");'
        result_list.append(a) #최종적으로 출력할 리스트에 추가

해당 노선의 담당 기관이 한곳인 경우이다.

위에서 저장한 oper의 갯수가 2보다 작은경우에

st : 역 코드 갯수 만큼 반복해서 요청변수에 담당기관코드 : oper와 st를 대입하여

데이터를 추출해서 형식에 맞게 result_list 변수에 저장한다.

# >> 관할 공사가 2곳 인경우 <<
elif len(oper) > 1:
    # 위에서 정의된 리스트 oper에 기관에 따라서 입력변수로 들어갈 값 설정.
    if oper[0] == "S1":
        st1 = S1_st
        name1 = S1_name
    elif oper[0] == "KR":
        st1 = KR_st
        name1 = KR_name
    elif oper[0] == "S5":
        st1 = S5_st
        name1 = S5_name
    elif oper[0] == "S9":
        st1 = S9_st
        name1 = S9_name
    elif oper[0] == "DX":
        st1 = DX_st
        name1 = DX_name

담당기관이 2곳인경우에는 oper에 두개의 담당기관코드가 들어있다.

따라서 oper[0] 에 들어있는 기관코드에 맞는 역코드(st1) 와 역이름(name1) 을 사용해야한다.

# >>> 첫번째 기관 (st1,name1,oper[0]) <<<
    for i in range(len(st1)):
        rail_oper = "&railOprIsttCd="
        url = endpoint + key + format + rail_oper + oper[0] + line_code + st_code + st1[i]
        html = urlopen(url)
        obj = BeautifulSoup(html, "html.parser")
        try:
            gate = obj.find("gateinotdvnm").text + "부"
            location = obj.find('dtlloc').text
        except:
            gate = "정보없음"
            location = "정보없음"

        if line == "D1":
            line = "분당"
        elif line == "K4":
            line = "경의중앙"

        a = "list.add(" + '"' + "[" + line + "호선] " + "{ " + name1[
            i] + " } " + " " + "게이트 " + gate + " / " + location + ' ");'
        result_list.append(a)

해서 위와 같은 코드로 oper[0] 에 맞는 데이터를 result_lsit 에 저장한다

두번째 기관인 oper[1] 도 같은 형식으로 진행하여 출력하면 된다.


출력 결과

원하는 노선을 선택하세요.
 [ 1~9 호선 : 1~9 ] , [ 경의중앙 : K4 ] , [ 분당선 : D1 ]
노선 : 3

list.add("[3호선] { 대화 }  게이트 외부 / 2번과3번출구사이 ");
list.add("[3호선] { 주엽 }  게이트 외부 / 2번출구와3번출구사이 ");
list.add("[3호선] { 정발산 }  게이트 외부 / 2번출구근접 ");
list.add("[3호선] { 마두 }  게이트 외부 / 3번출구 ");
list.add("[3호선] { 백석 }  게이트 외부 / 3,4번출구옆 ");
list.add("[3호선] { 대곡 }  게이트 외부 / 1층5번출구(엘리베이터뒤) ");
list.add("[3호선] { 화정 }  게이트 외부 / 4번출구 ");
list.add("[3호선] { 원당 }  게이트 외부 / 5,6번출구방향 ");
list.add("[3호선] { 원흥 }  게이트 외부 / 4번 출구와 6번 출구 사이 ");
list.add("[3호선] { 삼송 }  게이트 외부 / 1.2번출구에서북쪽으로50m ");
list.add("[3호선] { 지축 }  게이트 내부 / 2번출입구 ");
list.add("[3호선] { 구파발 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 연신내 }  게이트 내부 / 3번출입구 ");
list.add("[3호선] { 불광 }  게이트 외부 / 3번출입구 ");
list.add("[3호선] { 녹번 }  게이트 외부 / 4,5번출입구 ");
list.add("[3호선] { 홍제 }  게이트 외부 / 2번출입구 ");
list.add("[3호선] { 무악재 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 독립문 }  게이트 내부 / 4번출입구 ");
list.add("[3호선] { 경복궁(정부서울청사) }  게이트 내부 / 1,2,3,3-1,7번출입구 ");
list.add("[3호선] { 안국 }  게이트 외부 / 2,3,4,5번 출입구 ");
list.add("[3호선] { 종로3가 }  게이트 내부 / 7,8번출입구 ");
list.add("[3호선] { 을지로3가 }  게이트 내부 / 3,4,5,6번 출입구 ");
list.add("[3호선] { 충무로 }  게이트 내부 / 1번 출구 ");
list.add("[3호선] { 동대입구 }  게이트 내부 / 6번출입구 ");
list.add("[3호선] { 약수 }  게이트 내부 / 3번출입구 ");
list.add("[3호선] { 금호 }  게이트 내부 / 1번출입구 ");
list.add("[3호선] { 옥수 }  게이트 내부 / 3번 출입구 ");
list.add("[3호선] { 압구정 }  게이트 외부 / 5번출입구 ");
list.add("[3호선] { 신사 }  게이트 외부 / 2번출입구 ");
list.add("[3호선] { 잠원 }  게이트 내부 / 4번출입구 ");
list.add("[3호선] { 고속터미널 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 교대(법원·검찰청) }  게이트 외부 / 14번출입구 ");
list.add("[3호선] { 남부터미널(예술의전당) }  게이트 내부 / 1번출입구 ");
list.add("[3호선] { 양재(서초구청) }  게이트 내부 / 4번출입구 ");
list.add("[3호선] { 매봉 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 도곡 }  게이트 외부 / 4번출구 ");
list.add("[3호선] { 대치 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 학여울 }  게이트 외부 / 1번출구 ");
list.add("[3호선] { 대청 }  게이트 내부 / 4번출구 ");
list.add("[3호선] { 일원 }  게이트 외부 / 7번출구 ");
list.add("[3호선] { 수서 }  게이트 내부 / 3번출구 ");
list.add("[3호선] { 가락시장 }  게이트 내부 / 7번출구 ");
list.add("[3호선] { 경찰병원 }  게이트 정보없음 / 정보없음 ");
list.add("[3호선] { 오금 }  게이트 내부 / 2번출구 ");

Process finished with exit code 0

Comments