본문 바로가기
프로젝트/(공모전)순환경제 활성화를 위한 서울시 스마트수거함 입지선정

공모전 참여 케이스 스터디 -1 (크롤링 / 워드클라우드)

by 규딩코딩 2023. 10. 4.

이번에 좋은 기회로 훌륭한 팀원들과 함께 "2023 서울시 빅데이터캠퍼스 공모전"에 참여하고자 한다.

 

경험이 많이 부족하기 때문에 기수상작에 대한 분석을 먼저 진행하는 것으로 계획을 세웠다.

 

다행히도 공모전 수상작들에 대한 사례들이 누리집 자료실에 존재하여 해당 페이지에서 제목들과 수상내역들을 크롤링하고, 최종적으로는 워드 클라우드로 만들어 주목할만한 키워드가 있는지 찾아보려고 한다.

 

1. 수상내역 페이지 크롤링

- 서울 빅데이터 캠퍼스 누리집의 https://bigdata.seoul.go.kr/noti/selectPageListTabNoti.do?r_id=P260&bbs_seq=&ac_type=A1 해당 링크에서 관련 내용을 찾아볼 수 있다.

 

- 크롤링 코드는 다음의 코드를 사용하면 된다.

# 빈 데이터프레임 생성(제목을 저장할 df)
df = pd.DataFrame(columns = ['Title'])

# 1에서 10까지의 페이지에 대한 반복문
for page_number in range(1, 11):
    url = f"https://bigdata.seoul.go.kr/noti/selectPageListTabNoti.do?r_id=P260&bbs_seq=&ac_type=A1&sch_type=&sch_text=&currentPage={page_number}"
    response = requests.get(url)
    
    tree = html.fromstring(response.text)

    # XPath를 사용하여 모든 게시물 제목 선택
    page_post_titles = tree.xpath('//*[@id="aform"]/div[1]/div/table/tbody/tr/td[2]/a/@title')

    # df 에 저장
    df = pd.concat([df, pd.DataFrame({'Title':page_post_titles})], ignore_index = True)

# df 출력(주피터랩)
df

위에서 보았던 실제 페이지 목록과 비교해보면 잘 불러와진 것을 확인할 수 있음.

2. DF 편집하기

2-1 제목을 속성별로 분리하여 새로운 칼럼 만들기

- 제목을 자세히 들어다보면 다음의 구조를 가지고 있다.

- 주제명 - [ - 연도 - 공모전명 - 수상내역

지하철 9호선 신설역 수요인원 예측모델 개발 및 정책 제안 [2022 빅데이터캠퍼스 공모전 - 서울창조경제혁신센터장상 수상]

 

- 워드 클라우드 제작 및 데이터 파악이 용이하도록 다음의 코드를 사용하여 분리하고 새로운 칼럼으로 만들어주자.

# 기존 title에서 main title, 즉 실제 주제명을 [ 문자 기준으로 분리
df['Main_Title'] = df['Title'].str.split('[').str[0].str.strip()

#  '[' 다음에 연속된 숫자를 추출
df['Year'] = df['Title'].str.extract(r'\[([\d]+)')

# '-'와 ']' 사이의 모든 문자열을 추출
df['Award'] = df['Title'].str.extract(r' - ([^\]]+)')

df.head()

코드 결과

 

반응형

* 위에서 사용된 문자들??? = 정규표현식

더보기

정규표현식(Regular Expression 또는 간단히 Regex)은 특정한 규칙을 가진 문자열 패턴을 매칭시키기 위해 사용되는 문자열의 집합이다. 문자열 처리 작업에서 매우 강력한 도구이다.

 

정규표현식의 대표적인 사용 목적은 다음과 같다.

문자열 검색과 매칭: 특정한 패턴을 가진 문자열을 찾거나 매칭

문자열 대체: 특정 패턴을 다른 문자열로 대체

문자열 추출: 특정 부분을 추출하고 싶을 때 사용

문자열 검증 및 유효성 검사: 주어진 문자열이 특정한 규칙에 맞는지 확인

 

다음은 위의 정규표현식 해석이다.

1. r ' \ [ ( [ \ d] + ) '

r: 이 부분은 Python에서 raw 문자열을 나타냅니다. raw 문자열은 이스케이프 문자 (예: \n, \t)를 해석하지 않고 그대로 표시합니다. 

\[  : 이 부분은 [ 문자를 매칭합니다. 그리고 \[에서 [는 정규표현식에서 특별한 의미를 갖기 때문에 \로 이스케이프되었습니다. 따라서 이 부분은 [ 문자를 찾습니다. 

(  : 이 부분은 패턴 그룹을 시작합니다. 패턴 그룹은 추출하고자 하는 부분을 나타냅니다. 

[\d]+  : 이 부분은 하나 이상의 숫자를 나타내는 패턴입니다.

[\d]  : 대괄호 [] 안에 있는 \d는 숫자를 나타냅니다. \d는 정규표현식에서 숫자에 대응됩니다.

+  : 앞의 패턴이 하나 이상 나타날 수 있음을 나타냅니다. 즉, 하나 이상의 숫자를 의미합니다.

)  : 이 부분은 패턴 그룹을 종료합니다.

 

2. r ' - ( [ ^ \ ] ] + ) '     = 중복되는 설명은 제외

- : 이 부분은 문자열에서 공백, 하이픈, 공백을 매칭합니다.

[^\]]+  : 이 부분은 대괄호 안에 있는 것을 제외한 모든 문자를 나타내는 패턴입니다.

[^\]]  : 대괄호 [] 안에서 ^는 부정을 나타냅니다. 여기서는 ]를 제외한 모든 문자를 의미합니다. ]는 정규표현식에서 특별한 의미를 가지므로 \]로 이스케이프되었습니다.

 

by chat-gpt 231005

 

2-2 기존 칼럼 삭제 후 저장

df.drop('Title', axis = 1, inplace = True)
df.to_csv('BigdataContest_Award_list.csv', index = False, encoding = 'utf-8 sig')

 

3. 워드클라우드 만들기

3-0 준비하기

- 기본적으로 " !pip install wordcloud " 코드를 실행하는 방법 등으로 라이브러리를 설치해야하고,

 

- 한글 폰트를 설정해주어야한다. 필자는 나눔고딕체를 사용하도록 하겠다. font_path는 아래에서도 사용되니 기억.

from matplotlib import rc, font_manager as fm

# 나눔고딕 폰트 경로 설정
font_path = '../나눔고딕/NanumFontSetup_TTF_GOTHIC/NanumGothic.ttf'
font_name = fm.FontProperties(fname=font_path).get_name()

# 폰트 설정
rc('font', family=font_name)

 

3-1 워드 클라우드 제작을 위한 " text " 저장

- .join 메서드를 사용하여 모든 제목들을 하나의 문자열로 만들어주기 위해 다음의 코드를 사용하면,

# 선택된 열의 각 행(row)에 있는 데이터를 공백으로 구분하여 하나의 큰 문자열로 결합
text = ' '.join(df['Main_Title'])
text[:200]

 

- 아래의 결과가 나오게 된다.

 

3-2 워드 클라우드 제작

- 다음과 같이 기본적인 코드만 알고 있으면, 어려운 작업은 아니다.

from wordcloud import WordCloud
import matplotlib.pyplot as plt

# WordCloud 객체 생성
wordcloud = WordCloud(width=1000, height=500, background_color='white', font_path = font_path).generate(text)

# 워드클라우드 시각화
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()

워드 클라우드 결과

3-3 워드 클라우드 보완

- 그러나 위의 워드클라우드는 서울시, 분석 등의 단어처럼 사실상 워드 클라우드 제작의 목적을 방해하는 단어들이 많이 보인다.

- 다음의 stopwords 매개변수를 이용하면 이전보다 조금 더 목적에 맞는 워드 클라우드를 만들어볼 수 있다.

from wordcloud import WordCloud
import matplotlib.pyplot as plt

# 무시할 단어 리스트
stopwords = ["서울시", "분석", "분석을", "및", "위한", "통한"]

# WordCloud 객체 생성
wordcloud = WordCloud(width=1000, height=500, background_color='white', font_path=font_path, stopwords=stopwords).generate(text)

# 워드클라우드 시각화
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()

 

* 워드 클라우드 매개변수

더보기

width (기본값: 400): 워드클라우드의 가로 크기를 지정합니다.

height (기본값: 200): 워드클라우드의 세로 크기를 지정합니다.

background_color (기본값: 'black'): 워드클라우드의 배경 색상을 지정합니다.

colormap (기본값: 'viridis'): 단어별로 색상을 지정하는 컬러맵을 선택합니다.

font_path (기본값: None): 사용할 폰트의 파일 경로를 지정합니다. 이를 통해 워드클라우드의 텍스트 스타일을 지정할 수 있습니다.

max_words (기본값: 200): 워드클라우드에 표시할 최대 단어 수를 지정합니다.

mask (기본값: None): 워드클라우드의 모양을 결정하는 마스크 이미지를 사용할 수 있습니다.

contour_width (기본값: 0): 외곽선의 너비를 지정합니다.

contour_color (기본값: 'black'): 외곽선의 색상을 지정합니다.

prefer_horizontal (기본값: 0.90): 단어의 가로 방향으로 더 자주 나오게 하는 비율을 설정합니다. 값이 클수록 가로 방향으로 더 자주 나오게 됩니다.

scale (기본값: 1): 단어의 크기를 조절합니다.

relative_scaling (기본값: 'auto'): 단어 크기의 스케일을 지정합니다. 'auto'로 설정하면 max_words 매개변수를 기준으로 자동으로 조절합니다.

stopwords (기본값: None): 워드클라우드에서 무시할 불용어(stop words)를 지정합니다.

regexp (기본값: None): 정규표현식을 사용하여 단어를 추출할 수 있습니다.

mask_color (기본값: 'white'): 마스크의 배경 색상을 지정합니다.

random_state (기본값: None): 랜덤 시드를 설정합니다.

min_font_size (기본값: 4): 표시할 단어의 최소 글꼴 크기를 지정합니다.

font_step (기본값: 1): 글꼴 크기 간격을 조정합니다.

mode (기본값: 'RGB'): 워드클라우드의 색상 모드를 지정합니다.

relative_scaling (기본값: 'auto'): 단어의 상대적인 크기를 설정합니다.

 

 

반응형