(220906) 가까운 의료기관 지도 시각화 및 공감별 랭킹 뉴스 크롤링 및 워드클라우드 시각화

이은경·2022년 9월 6일
0

1. 의료기관 워드 클라우드 시각화

와이파이 실습 때와 같이 의료기관 공공데이터를 활용하여 현황을 분석하고 지도 시각화를 진행했다. 유사한 내용은 제외하고 한 번 더 짚어봐야 할 내용과 처음 배운 내용을 기록하고자 한다.

1) 집계함수: counts와 size

  • counts: 특정 컬럼의 데이터별 갯수를 확인할 수 있다. 오직 확인만 가능
  • groupby+size: 시리즈 형태이며 숫자(no_name)를 제외한 모든 값이 인덱스이다. 현 형태로는 차트 그릴 수 없음
  • groupby+size+리셋 인덱스: 데이터 프레임 형태로 변환이 되며 인덱스를 새로이 만들어 데이터들이 인덱스가 아닌 컬럼에 속함

참고. groupby를 하면, NaN값은 제외하고 계산하기 때문에 원시자료의 데이터 수와 다른 값이 나올 수 있다. 이처럼 분석할 때는 차이가 왜 발생하는지 이유를 파악하고 있어야 한다.

2) 컬럼 내 최댓값과 최솟값.

  • df.['컬럼명'].max(): 컬럼 내 최댓값 출력
  • df.['컬럼명'].min(): 컬럼 내 최솟값 출력
    ps. 이러한 사소한 것도 모르고 있는 스스로를 보며... A to Z 스스로 공부해야겠다고 생각했다.

3) format 함수

워드클라우드를 그리기에 앞서 의료기관별 진료과목명을 모두 끌어와 하나의 text로 만들었다. 그리고 진료과목명의 워드클라우드를 그리게 되는 진료과목명이 몇개나 들어있는지 확인했다.

먼저 단순히 text의 갯수를 구하면 그 text를 이루고 있는 문자의 갯수를 가져온다. 따라서 우리가 특수문자를 공백으로 치환한 후 각 의료기관별 진료과목을 공백으로 구분하여 join했기 때문에 공백을 기준으로 스플릿한다면, 진료과목의 개수를 구할 수 있다.

이 과정에서 우리는 저 {} 중괄호 안에 len(text)를 넣기 위해 format 함수를 활용한다. format함수는 중괄호로 인덱스를 만들고 format함수 인자에 그 값을 넣어주는 것이다.

참고. 중괄호의 갯수는 1개 이상일 수 있다. 여러개의 값을 format함수로 넣을 때 첫 인덱스 값은 0이며 1, 2값을 주면 인덱스 순서에 맞게 값을 대입시켜 준다.

(1) print('총 {} 개 데이터가 있습니다.'.format(len(text)))
(2) print('총 {0} 개 데이터가 있습니다{1}.'.format(len(text)),'!')

2. 의료기관 지도 시각화

1) 의료기관 지도 시각화 아이디어

  • 1) 아이디어는 사용자 입력값인 현위치 그리고 현위치와 가깝고 영업 중인 의료기관을 표시하는 것이다.
  • 2) 그리고 이 아이디어를 실현하기 위한 필수 정보는 의료기관명과 좌표값(위도, 경도), 영업상태이다.
  • 3) popup에 추가적으로 제공하고자 하는 정보는 진료과목과 전화번호이다.
  • 4) 데이터 전처리를 하기 전에 df.info()로 확인해보면, 필수정보 중 좌표값은 1개가 null값이고 추가정보인 진료과목과 전화번호는 수백건이 null값이었다.
  • 5) 보통 데이터 전처리를 할 때, df.isna().sum()으로 결측치를 확인하고 필요할 경우 df.dropna(axis=0, inplace = True)를 이용해 해당되는 행을 모두 한 번에 지운다.
  • 6) 하지만 의료기관을 찾는 사람들에게 서비스를 하는 경우라면, 추가정보가 결측치여도 필수정보가 있는 의료기관을 지도에 표시해주는 게 좋을 것 같다는 생각이 들었다.

2) 결측치 삭제 등 데이터 전처리

#3. 데이터 전처리

#3-1. 유효한 데이터 수집(NaN 값은 '-'로 바꾸고 좌표값이 없는 의료기관은 삭제)
mdf = df.replace(np.nan, '-', regex=True) 
d = mdf[mdf['위도'] == '-'].index
mdf.drop(d, axis='index', inplace=True) 
# 기타 정보가 없어도 영업중인 의료기관은 모두 표시되도록 처리

#3-2. 영업 중인 의료기관만 수집
op_df = mdf.loc[mdf['상세영업상태명']=='영업중']
op_df.reset_index(drop=True, inplace=True)

NaN데이터를 모두 삭제하면, 수백 건 이상의 의료기관 데이터가 없어지기 때문에 필수정보를 포함하고 있지 않은 데이터만 삭제하기로 결정했다.

  • 1) df 데이터 프레임에 NaN 값을 모두 '-'로 바꾼 후
  • 2) 위도에 '-' 값을 가진 index를 d로 정의한다.
  • 3) 이후 d에 포함된 index를 모두 삭제한다.

그 다음 우리가 원하는 지도 시각화 대상은 영업중인 의료기관임에 따라 상세영업상태명이 영업중인 의료기관만 추출해 새로운 op_df에 담았다.

3) 사용자의 입력값(도로명 주소)을 좌표로 변환하기

#4. 주소를 좌표로 변환할 함수 준비
def geocoding(address):
    geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
    geo = geolocoder.geocode(address)
    crd = {"lat": float(geo.latitude), "lng": float(geo.longitude)}
    return crd

#5. 사용자에게 주소 입력받기 
address = input('도로명주소를 입력하세요.')
start = time.time() # 사용자 입력 시각 측정(Shout out to 세종)
  • 사용자가 도로명 주소를 입력하면 해당 주소를 좌표로 변화하는 함수를 이용한다. 이 때, 원칙적으로 crd에 포함된 lat과 lng의 데이터 형태는 실수(float)형태여야 한다.
  • 추가적으로 소요시간을 확인하기 위해 사용자가 주소를 입력한 시점을 기록한다.
#6. 사용자 주소를 좌표로 변환 후, 튜플 형태로 변수에 담기
crd = geocoding(address)
IMHERE = (crd['lat'], crd['lng']) 

#7. 데이터프레임 새로 생성 후, 필요한 컬럼 및 입력 주소와의 거리 계산하여 담기
c_hosp = pd.DataFrame(columns=['사업장명', '의료기관종명', '진료과목', 
                               '전화번호', '영업상태','위도', '경도', '거리']) 
for n in op_df.index:
  h_loc = (op_df.loc[n, '위도'], op_df.loc[n, '경도']) 
  c_hosp.loc[n] = [op_df.loc[n, '사업장명'], op_df.loc[n, '의료기관종별명'], 
                   op_df.loc[n, '진료과목내용명'], op_df.loc[n, '소재지전화'], 
                   op_df.loc[n, '상세영업상태명'], op_df.loc[n, '위도'], 
                   op_df.loc[n, '경도'], geodesic(IMHERE, h_loc).kilometers]
  • 1) 사용자가 입력한 도로명 주소의 좌표값을 'IMHERE'이라는 변수에 담는다.
  • 2) 지도에 시각화하고자 하는 값을 담는 새로운 데이터 프레임을 c_hosp로 선언한다.
  • 3) 거리를 계산하기 위해 의료기관의 좌표는 h_loc에 추가로 담고 'geodesic'이라는 함수로 사용자가 입력한 주소와 각 의료기관 간의 거리를 km 기준으로 계산해 담게 한다.
#8. 입력 주소와 가장 가까운 영업중인 의료기관 상위 5곳 구하기
c_hosp = c_hosp.sort_values(by=['거리']).head(5)

#9. 의료기관 자료의 평균 위치를 중심좌표로 지도 준비
h_map = folium.Map(location=[op_df['위도'].mean(), op_df['경도'].mean()], zoom_start=10)

#10. 입력 주소와 상위 5곳의 의료기관 마커 올리기
folium.Marker([crd['lat'], crd['lng']], icon=folium.Icon(color='red', icon='glyphicon 
                                                         glyphicon-home')).add_to(h_map)

for n in c_hosp.index:
  folium.Marker([c_hosp.loc[n, '위도'], c_hosp.loc[n, '경도']],
                 popup='<pre>'+'병원명: '+c_hosp.loc[n, '사업장명']+', 진료과목: '
                 +c_hosp.loc[n, '진료과목']+', 전화번호: '+c_hosp.loc[n, '전화번호']+
                 '</pre>', icon=folium.Icon(color='cadetblue',icon='fa-hospital-o' 
                 ,prefix='fa')).add_to(h_map)

#11. 실행에 소요된 시간 표시 및 지도 시각화
print('실행시간:', (round(time.time()-start)),'초')
h_map
  • 1) 거리를 기준으로 의료기관들을 오름차순 정렬한다.
  • 2) 영업중인 의료기관(op_df)의 모든 위도 및 경도 값을 평균내어 지도의 중심을 설정한다.
  • 3) 원하는 정보를 팝업에 설정한다.
  • 4) print하는 시점의 시각에서 초반에 사용자 입력시점 시각을 빼서 소용된 실행시간을 구한다. 이 때 round로 감싸서 소요시간을 정수로 얻기 위해 반올림한다.

3. 공감별 랭킹 뉴스 크롤링 및 워드 클라우드 시각화

네이버 공감별 연예랭킹 뉴스가 있다😊 좋아요부터 슬퍼요까지 여섯가지의 공감별 높은 공감을 받은 뉴스들을 순서대로 랭킹을 매겨놓은 뉴스이다.

아이디어는 이 각각의 공감별 뉴스를 크롤링하고 사용자가 공감값을 입력하면 그 공감 랭킹 뉴스 제목으로 워드클라우드를 만드는 것이다.

그런데 어떻게 만들지...🤔라는 고민이 이어졌고 기존에 배웠던 뉴스 크롤링과 다른 점을 구별해보았다.

  • 첫째로 공감종류와 공감수를 크롤링해와야 한다는 점
  • 둘째로 사용자로부터 공감 입력값을 받아야 한다는 점
  • 셋째로 6개의 사이트를 한 크롤링 과정에 넣어야 한다는 점

미리 구조를 설계하고 들어가면 좋으련만 방법을 모르니 일단 실습했었던 크롤링 과정에서 하나씩 확장해야겠다고 생각했다. 공감별 뉴스는 총 6개 부문이지만, 합치는 건 나중에 정 어려우면 머지를 하면 되니 차후 문제라 판단했고, 한 공감을 기준으로 공감종류와 공감수를 크롤링해오고자 했다.

1) 6개의 DF 머지 버전

  • 첫 아이디어는 단순하게 공감별로 데이터 프레임을 각각 만들어 6개의 데이터 프레임을 머지한 후 그 새로운 데이터 프레임에서 워드클라우드를 그리는 것이었다.
  • sym_df1 ~ sym_df6까지 동일한 컬럼명을 포함시켜 데이터를 담도록 선언한다. 이 때 각각 수집하기 때문에 공감별 랭킹뉴스의 주소가 달라도 문제가 없어 driver.get("주소")는 고민할 필요가 없었다😅
    (ps. 이게 하드코딩이라는 건가... 생각이 절로 들었지만 우선 이렇게라도 해놓아야 추가로 아이디어가 떠오를 것 같았다.)
sym_df1 = pd.DataFrame(columns=['공감종류', '순위', '기사제목', 
                                  '기사링크', '기사내용', '공감수', '수집일자'])
driver.get("https://entertain.naver.com/ranking/sympathy")
driver.implicitly_wait(3) # 바로 움직이면 컴퓨터로 인식하니까 잠시 멈춤
time.sleep(1.5)

driver.execute_script('window.scrollTo(0,800)') 
time.sleep(3)
  • 먼저 좋아요 공감이 가장 많은 기사 순으로 크롤링하기 위해 페이지 소스를 확인했다. 기사들은 ul(unordered list) 태그에 속한 여러 개의 li태그(class명: li._inc_news_lst3_rank_reply)에 각각 담겨있어 그 부분의 HTML 소스를 모두 li_list에 담았다.
html_source = driver.page_source 
soup = BeautifulSoup(html_source, 'html.parser')
li_list= soup.select('li._inc_news_lst3_rank_reply')
  • 1) 좋아요 공감 많은 기사 리스트가 있는 웹페이지 소스

  • 2) li_list로 담은 후 출력되는 값:
    좋아요 공감이 많은 순으로 총 30개의 기사 리스트의 HTML 소스가 담겨있다.

  • li_list에 담긴 li 태그 수만큼 for문을 돌리면서 각 기사별 '공감종류와 순위, 기사제목, 기사링크, 기사 내용, 공감 수'를 추출하고 처음에 만든 sym_df1에 append한다.

  • 가장 고민했던 컬럼은 공감 종류였다. 다른 컬럼들처럼 태그 안에서 값을 추출하고 싶다는 생각에 공감별로 페이지 소스를 확인해봤다. 살펴보니 a 태그 중 'likeitnews_item_likeit like'라는 클래스명을 가진 태그가 있었고, 다른 공감 페이지도 'likeitnews_item_likeit cheer'와 같이 마지막 단어만 다르게 클래스 명을 가지고 있어 이를 가져와 스플릿한 후 활용했다.

for li in range(0,len(li_list)):
  try:
    #공감종류
    a = li_list[li].find('a',{'class', 'likeitnews_item_likeit like'}).attrs['class'] 
    kind = str(a).split("'")[3]
    #순위
    rank = li_list[li].find('em',{'class', 'blind'}).text.replace('\n','')
           .replace('\t','').strip() 
    #기사 제목
    title = li_list[li].find('a',{'class', 'tit'}).text.replace('\n','')
            .replace('\t','').strip()
    #기사 링크
    link = li_list[li].find('a').attrs['href']
    #기사 내용
    summary = li_list[li].find('p',{'class', 'summary'}).text.replace('\n','')
              .replace('\t','').strip() 
    #공감 수
    num = li_list[li].find('a',{'class', 'likeitnews_item_likeit like'})
          .text.replace('\n','').replace('\t','').replace(',', '').strip()  
    symnum = str(num)[3:]
    #dataframe 저장(append)
    sym_df1 = sym_df1.append({'공감종류': kind,
                            '순위': rank, 
                            '기사제목': title, 
                            '기사링크': 'https://entertain.naver.com'+link, 
                            '기사내용': summary, 
                            '공감수': symnum, 
                            '수집일자' : datetime.datetime.now(timezone('Asia/Seoul'))
                                       .strftime('%Y-%m-%d %H:%M:%S')}, ignore_index=True) 
  except:
    pass 
  • 이후 아래와 같이 각각의 데이터 프레임을 하나의 df로 병합해 사용자로부터 input을 받고 해당하는 기사들로 워드클라우드를 그렸다.
sym_df = pd.concat([sym_df1,sym_df2,sym_df3,sym_df4,sym_df5,sym_df6])
sym_df.reset_index(drop=True, inplace=True)
  • 공감별로 각각 df를 만들고 머지하는 이 방식은 6개의 웹페이지를 파싱하는 과정에서 6배의 시간이 소요된다는 단점이 있다.

2) 선인풋 버전

이 코드는 우리 팀 PL의 아이디어이다😍 사용자로부터 먼저 input을 받은 후 해당하는 주소에만 접근해 선택적으로 크롤링한다. 감정별로 변수를 선언하고 크롤링 프로그램이 접근할 주소에 붙여서 if문에 넣고 input값과 일치하는 기사 리스트만 추출한다.

sym_df = pd.DataFrame(columns=['공감종류', '순위', '기사제목', '기사링크', 
                               '기사내용', '공감수', '수집일자'])
driver = webdriver.Chrome('chromedriver', options=options) 
input_sympathy = input('보고싶은 공감 랭킹뉴스를 입력하세요 
                      [like, cheer, congrats, expect, surprise, sad] ')

#5. 입력값에 따라 해당하는 공감 기사만 파싱해오기
site = 'https://entertain.naver.com/ranking/sympathy'
emo1 = '/like'
emo2 = '/cheer'
emo3 = '/congrats'
emo4 = '/expect'
emo5 = '/surprise'
emo6 = '/sad'

if input_sympathy == 'like':
  driver.get(site)
elif input_sympathy == 'cheer':
  driver.get(site+emo2)
elif input_sympathy == 'congrats':
  driver.get(site++emo3)
elif input_sympathy == 'expect':
  driver.get(site+emo4)
elif input_sympathy == 'surprise':
  driver.get(site+emo5)
else:
  driver.get(site+emo6)

장점은 한 개의 공감 리스트만 크롤링하기 때문에 소요되는 시간이 대폭 줄어든다는 것이다.
(ps. 정말 창의적이라고 생각했다...😲 난 왜 구조를 변경할 생각을 못했을까😭)

3) 리스트활용 1DF 버전

  • 이 코드는 첫번째 방식에서 모든 공감 기사를 공감별로 각각 크롤링하는 단점을 보완하기 위해 고안했다. 첫번째 코드는 코드 줄 수가 328줄이나 된다^^; 진짜 봐줄 수 없는 수준이라 코드를 짧게 쓰는 데에 방법을 강구했고 각 컬럼 자료를 for문을 통해 얻는 것처럼 공감종류도 for문을 통해 처리하고자 하는 게 목표였다.
  • 마침 각 공감 기사의 웹사이트 주소가 좋아요를 제외하고 모두 같은 양식이었고 그 값이 공감종류 컬럼을 할 때 추출했던 클래스명의 구분과 같았다.
  • 먼저 감정이라는 리스트에 각각의 공감 종류를 넣어 만들었다. 하지만 여기서 또 위기봉착... 왜 좋아요 주소는 저렇게 sympathy하고 끝나는 거죠...?
  • 이를 해결하기 위해 if문을 사용했다. '만약 Emotions의 값이 like라면 내가 준 주소를 그대로 사용하고 그렇지 않다면 내가 준 주소에 '/'와 'Emotions' 값을 순서대로 넣어서 접근해줘'라고.
sym_df = pd.DataFrame(columns=['공감종류', '순위', '기사제목', 
                               '기사링크', '기사내용', '공감수', '수집일자'])

site = 'https://entertain.naver.com/ranking/sympathy'
Emotions = ["like","cheer","congrats","expect","surprise","sad"]  

#3. 감정별 데이터 파싱 위한 for문 설정

for n in range(0, len(Emotions)): # 좋아요와 그밖의 공감 간 다른 주소형식을 감안
  if Emotions[n] == 'like':
    driver.get(site)
  else:
    driver.get(site+'/'+ str(Emotions[n]))
  driver.implicitly_wait(3) 
  time.sleep(1.5)

  driver.execute_script('window.scrollTo(0,800)') 
  time.sleep(3)

  html_source = driver.page_source 
  # print(html_source)
  soup = BeautifulSoup(html_source, 'html.parser')
  li_list= soup.select('li._inc_news_lst3_rank_reply')
  • 원래 아래와 같이 리스트를 df형태로 만들어 for문을 돌렸는데 교수님 코드를 확인한 후 그냥 리스트로 for문을 돌렸는데 실행이 되었다. 아니 분명 리스트로 시도했을 때는 오류가 났는데 말이죠...😅
Emotions = ["like","cheer","congrats","expect","surprise","sad"]  
Emo_df = pd.DataFrame(Emotions, columns = ['감정'])

#3. 감정별 데이터 파싱 위한 for문 설정
e_name = Emo_df['감정']

for n in range(0, len(e_name)): # 좋아요와 그밖의 공감 간 다른 주소형식을 감안
  if Emo_df['감정'][n] == 'like':
    driver.get(site)
  else:
    driver.get(site+'/'+ str(Emo_df['감정'][n]))
  driver.implicitly_wait(3) 
  time.sleep(1.5)
  • 참고. 아래는 리스트 형태일 때와 데이터 프레임일 때 출력되는 값이다.
  • 여튼... 프로그램이 두 개의 for문을 돌아 모든 자료를 sym_df에 담으면 아래와 같이 사용자로부터 공감종류를 입력받고 그에 해당하는 기사만 df에서 찾아 워드클라우드를 그리게 한다.
  • join 함수 뒤의 for는 우리가 아는 for문이고 wc는 일반적인 변수로서 사용자의 입력값과 일치하는 기사의 기사제목을 순서대로 join하게 한다.
#5. 사용자로부터 공감 입력값 받기
input_sympathy = input('보고싶은 공감 랭킹뉴스를 입력하세요 
                 [like, cheer, congrats, expect, surprise, sad] ')

#6. 입력값에 해당하는 공감 기사제목만 join
text = " ".join(wc for wc in sym_df[sym_df.공감종류 == input_sympathy].기사제목.astype(str))

4) 교수님 버전

  • 대망의 교수님 코드... 교수님께서 설명해주시는 코드 중 나와 다른 코드를 받아적고 복원을 해보았다.
  • 충격적이었던(?) 코드는 sympathy 초기 값으로 좋아요를 선언한 것과 url을 for문에 넣어 리셋한 것 그리고 공감종류를 '=sympathy'로 append한 부분이었다.
def clean_text(inputString): # 특수문자 삭제 
  text_rmv = re.sub('[-=+,#/\?:^.@*\"※~ㆍ!』‘|\(\)\[\]`\'…》\”\“\’·]', ' ', inputString)
  return text_rmv

#2. 데이터 프레임 생성 및 데이터 수집 위한 변수 설정
sym_df = pd.DataFrame(columns=['공감종류', '순위', '기사제목', 
                               '기사링크', '기사내용', '공감수', '수집일자'])

url_list = ['','/cheer','/congrats','/expect','/surprise','/sad']
#url = 'https://entertain.naver.com/ranking/sympathy'

sympathy = 'like' # 초기값을 줘버림

#3. 감정별 데이터 파싱 위한 for문 설정

for n in range(0, len(url_list)): # 좋아요와 그밖의 공감 간 다른 주소형식을 감안
  url = 'https://entertain.naver.com/ranking/sympathy' #진짜 감동: url 리셋
  url += url_list[n] # 자기자신에게 더하는 것

  if url_list[n] != '':
    sympathy = url_list[n].replace('/','')    
  driver.get(url)
  
  ... ... (중략)
  
  print(' 수집 중... '+url+' sympathy:' + sympathy)
  • 1) 워드클라우드 시각화를 대비하여 특수문자를 제거하는 함수를 먼저 정의한다.
  • 2) 크롤링한 데이터를 담을 df를 선언한다.
  • 3) url_list라는 리스트에 공감종류이자 주소인 값들을 '/'와 함께 담는다.
    단, 좋아요 기사 리스트는 주소에 추가되는 값이 없으므로 ''로 넣는다.
  • 4) sympathy의 초기값을 like로 선언한다.
  • 5) url_list에 있는 데이터값 갯수 만큼 for문을 돈다.
  • 6) 가장 기본 주소인 좋아요 url을 url로 정의하고 다음 코드에서 url_list값을 더한 값이 다시 새로운 url이 되도록 한다. 이 때, 처음에는 주소에 더해지는 값이 없기 때문에 첫 for문은 좋아요 기사를 크롤링한다.
  • 7) 이후 if문에서 url_list값이 ''이 아니라면 sympathy는 url_list에서 '/'를 제외한 값이 되도록 선언한다. 이 때 좋아요는 이 if문을 지나가기 때문에 초기값인 like를 가지게 된다.(교수님 정말...찐 천재...)
  • 8) 처음에 코드를 혼자 복원해보다가 url을 for문 보다 위쪽에 배치했는데(위쪽에 주석처리한 코드), 이상하게 congrats부터는 수집이 되지 않는 것이었다...(주소가 ...sympathy/cheer/congrats^^;가 되어버림) 이 문제를 해결을 위해 10분 정도 고민해보니... 교수님이 말씀하셨던 것 중에 '리셋을 해준다'라는 표현이 기억나서 url을 for문 안에 넣었고 그 결과 for문을 새로 돌면서 기본 값 url이 들어오니 주소를 정상적으로 만들 수 있었다😭
  for index_1 in range(0, len(li_list)):
    try:
      #공감종류
      kind = sympathy
      ... ... (중략)
      #공감 수
      temp_cnt = li_list[index_1].find('a',{'class', 'likeitnews_item_likeit '+str(sympathy)})
                 .text.replace('\n','').replace('\t','').strip()  
      cnt = re.sub(r'[^0-9]','', temp_cnt)
      #dataframe 저장(append)
      sym_df = sym_df.append({'공감종류': kind, 
                            '순위': rank, 
                            '기사제목': title, 
                            '기사링크': 'https://entertain.naver.com'+link, 
                            '기사내용': summary, 
                            '공감수': cnt, 
                            '수집일자' : datetime.datetime.now(timezone('Asia/Seoul'))
                                       .strftime('%Y-%m-%d %H:%M:%S')}, ignore_index=True) 
    except:
      pass 
  • 1) 공감 종류를 가져온 방법이 너무나도 감동적이었다. ★초간단★ for문을 순차적으로 돌 때마다, sympathy가 정해졌기 때문에 그대로 사용하면 되고 별도로 HTML에서 가져올 필요가 없었다. ★초간단★
  • 2) 마지막으로 공감수는... 기존처럼 a 태그의 텍스트에서 가져오되, 숫자 이외에 모든 값을 제외하는 정규식 코드를 활용했다. 텍스트는 '공감수4,566'과 같은 형식이었고 re.sub(r'[^0-9]','',텍스트)를 활용하면 0-9가 아닌 값은 빼도록 할 수 있다.

4. 이번 과제를 하며 느낀 점

앞으로 코드 작성 시 닥치는 대로 문제를 해결하려 애를 쓰기 전에 먼저 체계적으로 로직을 구상하고, 시도한 코드는 오류가 나도 기록해놔야겠다는 생각이 들었다.

이번 과제 초반 코드 중 그 이유가 있다. 데이터프레임이 아닌 리스트로 len 함수를 활용했을 때 분명 오류가 났는데 교수님 코드가 동일한 방식으로 작성되어 있어 다시 시도해보니 코드가 정상적으로 실행되었다. 물론 다른 부분에서 오류가 났던 것이겠지만 기록이 없으니 무작정 리스트 형태로는 len함수가 돌아가지 않는 것이라고 오판을 했으니 말이다.

0개의 댓글