Molybdenum의 개발기록

[TIL] 17일차_Seoul_Call_Center_120_View of major complaints_Scrapping 본문

TIL

[TIL] 17일차_Seoul_Call_Center_120_View of major complaints_Scrapping

Molybdenum_j 2023. 3. 7. 14:52

서울특별시 다산콜센터(☎120)의 주요 민원(자주 묻는 질문)에 대한 답변정보

 

▶ 라이브러리 로드

  • pandas : 파이썬에서 사용할 수 있는 엑셀과 유사한 데이터분석 도구
  • requests : 매우 작은 브라우저로 웹사이트의 내용과 정보를 불러옴
  • BeautifulSoup : request로 가져온 웹사이트의 html 태그를 찾기 위해 사용
  • time : 한 번에 많은 양의 데이터를 가져오게 되면 서버에서 부담을주기 때문에 시간 간격을 두고 가져오기 위해 사용
import pandas as pd
import numpy as np
import requests
from bs4 import BeautifulSoup as bs

 

1) 데이터 불러오기

df = pd.read_csv("data/seoul-120/seoul-120-list.csv")
df.shape
  • 일부데이터를 우선 수집

- 모든 데이터를 수집해야 하지만 모든 데이터 수집 시 서버에 부담

- 잘못 수집 시 처음부터 다시 수집해야 하기 때문에 일부데이터만 우선 수집

df = df.head(10)

-> 일단 10개만 불러왔다.

 

 

2) 특정 내용만 읽어오기

no = df["내용번호"][0]
url = f"https://opengov.seoul.go.kr/civilappeal/{no}"
print(url)

 

3) request 요청하기

response = requests.get(url)

 

4) html을 bs 사용해 내용태그 찾음

html = bs(response.text)
  • read_html을 통해 문서정보 일어오기
df_desc = pd.read_html(response.text)[-1]

 

 

5) 데이터프레임 다루기

  • set_index()를 사용해 데이터 프레임의 인덱스를 지정한다
tb01 = df_desc[[0,1]].set_index(0).T
print(tb01.index, tb01.columns)
display(tb01)

tb02 = df_desc[[2,3]].set_index(2).T
tb02.index = tb01.index
display(tb02)

pd.concat([tb01, tb02], axis=1)

 

  • transpose() == T를 사용해서 전치행렬을 만든다

- 전치행렬 했을 때 index <=> columns 위치가 변경되기 때문에 인덱스로 설정해 주었다.

  • concat()을 사용해서 데이터프레임을 합친다
def get_desc(response):

    df_desc = pd.read_html(response.text)[-1]
    tb01 = df_desc[[0, 1]].set_index(0).T.reset_index(drop=True)
    tb02 = df_desc[[2, 3]].set_index(2).T.reset_index(drop=True)

    df_desc_tb = pd.concat([tb01, tb02], axis=1)
    return df_desc_tb

get_desc(response)

 

6) 내용 parsing

  • %time => 한번만 측정
  • %timeit => 여러번 측정 후 평균을 구함select 활용
  • select
%time html.select("div.line-all")[0].text.strip()
  • find
%time html.find("div", {"class": "line-all"}).text.strip()

 


▶ 내용 수집함수 만들기

def get_view_page(view_no):
   
    try:
        url = f"https://opengov.seoul.go.kr/civilappeal/{view_no}"
        response = requests.get(url)
        desc = get_desc(response)
        html = bs(response.text)
        content = html.find("div", {"class": "line-all"}).text.strip()
        desc["내용"] = content
        desc["내용번호"] = view_no
        return desc
        time.sleep(0.01)
        
    except Exception as e:
        print(f"오류 게시물 번호 : {view_no}, 오류 메시지 : {e}")

get_view_page(df["내용번호"][0])

 

7) 전체 내용 가져오기

- tqdm : 수집 진행상황을 확인한다.

from tqdm.notebook import tqdm
tqdm.pandas()

view_detail = df["내용번호"].head(10).progress_map(get_view_page)

 

8) 수집한 내용 확인

일부 데이터만 슬라이싱
view_detail[:2]

하나만 가져오기
view_detail[1]

 

9) 하나로 병합하기

df_view = pd.concat(view_detail.to_list(), ignore_index=True)
df_view
  • how="left" 내용번호가 중간에 누락되어 수집되지 않은 건이 있다면 결측치로 보이게 한다.
  • how="right" 내용번호는 수집되었지만 목록에 없는 경우 목록 내용이 결측치로 보이게 한다.
  • merge는 컬럼, 혹은 인덱스를 기준으로 병합한다.
  • join은 인덱스 기준으로 병합한다.
df_detail = df.merge(df_view, on=["내용번호","생산일"], how = "left")

 

10) 사용할 컬럼만 남긴다

cols = ['번호', '분류', '제목', '내용', '내용번호']

df = df[cols]

 

 

▶ 파일로 저장하고 확인

file_name = "data/seoul-120/seoul-120-sample.csv"

df.to_csv(file_name, index=False)

pd.read_csv(file_name)

 

 

 

출처 - 멋쟁이사자처럼_AISCHOOL_박조은강사님

Comments