본문 바로가기

대외활동/ABC 지역주도형 청년 취업역량강화 ESG 지원산업

[ABC 220831 - 11일차] 웹 크롤링

반응형

타슈 크롤링

< 크롤링 순서 >

1. 크롤링할 사이트 접속(URL)

2. 크롤링할 화면의 HTML Tag 확인(내가 수집할 Data의 위치 또는 Tag)

    1) 페이지 소스 보기 → HTML Tag 확인

    2) 크롬 F12 개발자 모드 → Tag 확인

 

1. 라이브러리 임포트

from urllib.request import urlopen
from bs4 import BeautifulSoup

import pandas as pd

2. 타슈 크롤링

1) 데이터 프레임 생성

data = pd.DataFrame(columns=['Station 스테이션명', '위치', '상태정보', '위도', '경도'])

2) 타슈 사이트 접속주소 준비(url)

url = 'https://new.tashu.or.kr/stationList.do'

3) url 접속하여 html 가져오기

html = urlopen(url)

4) html 태그를 파싱(parsing)하여 변환

bsObject = BeautifulSoup(html, 'html.parser', from_encoding='UTF-8')

5) 타슈 정류장 정보가 있는 table만 가져오기

table = bsObject.find_all('table', {'class', 'board-tp-01 stationtable'})

6) 상세정보 추출

6-1) table 태그 내 tr 찾기

tr = table[0].find_all('tr')

6-2) 첫 tr(테이블의 컬럼 정보) 제외

tr = tr[1:len(tr)] # 0번째 인덱스 제외히고 다시 tr에 담기

6-3) 타슈 정류장 상세 정보 추출

for index_tr in range(0, len(tr)) :
  td = tr[index_tr].find_all('td')# 장소
  station = td[0].text.split('.')[1]

  # 위치
  location = td[1].text

  # 상태정보
  condition = td[2].text

  # 좌표 추출
  # 위도 Latitude
  lat = td[3].button.attrs['data-lat']

  # 경도 Longitude
  lon = td[3].button.attrs['data-ltd']

7) 타슈 정류장 상세 정보 DataFrame에 담기(append) ▶ 이 코드는 for문 안에 있어야 함.

  data = data.append({
      'Station 스테이션명':station,
      '위치':location,
      '상태정보' : condition,
      '위도' : float(lat),
      '경도' : float(lon)}, ignore_index = True)
  
  print('Complets of ' + station)

3. 데이터 정보 확인

data.info()

4. 크롤링한 데이터 저장하기 (핵심 중요)

data.to_csv('타슈크롤링_220830.csv', encoding='utf-8-sig', index=False)
# encoding 할때 utf-8로 하면 한글 깨지는 경우 많은데 utf-8-sig로 하면 안깨짐

5. 크롤링한 데이터를 활용한 지도 시각화

1) 데이터 준비하기

df = pd.read_csv('/content/타슈크롤링_220830.csv')
df.head()

df.info()
# 지도 시각화를 위해 위도, 경도가 float형태로 제대로 있는지를 확인.

2) 지도 시각화 ( 지도의 버전을 각각 다른 것으로 구현해보자.)

import folium

# 타슈 정류장의 상태에 따라서 Marker를 다른 색으로 표시 -> 정상 : 파랑, NETWORK 에러 : 빨강
df['상태정보'].unique()

# 1) 타슈 정류장 위치기반으로 중심좌표를 설정
t_map = folium.Map(location=[df['위도'].mean(),df['경도'].mean()], zoom_start=14)

# 2) 타슈 정류장의 상태에 따른 Marker 표시하기 위해서 상태정보를 준비
condition = df['상태정보']

# 3) 타슈 정류장 Marker 지도에 추가
for index_draw in range(0,len(condition)):
  if condition[index_draw] == '정상' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>', # <pre>태그는 popup창이 가로로 나오게 하기 위해서 추가
                  icon = folium.Icon(color='blue', icon='fa-bicycle', prefix='fa')).add_to(t_map)
  elif condition[index_draw] == 'NETWORK 에러' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>',
                  icon = folium.Icon(color='red', icon='fa-bicycle', prefix='fa')).add_to(t_map)
t_map

import folium

# 타슈 정류장의 상태에 따라서 Marker를 다른 색으로 표시 -> 정상 : 파랑, NETWORK 에러 : 빨강
df['상태정보'].unique()

# 1) 타슈 정류장 위치기반으로 중심좌표를 설정
t_map = folium.Map(location=[df['위도'].mean(),df['경도'].mean()], zoom_start=14, tiles='Stamen Terrain')

# 2) 타슈 정류장의 상태에 따른 Marker 표시하기 위해서 상태정보를 준비
condition = df['상태정보']

# 3) 타슈 정류장 Marker 지도에 추가
for index_draw in range(0,len(condition)):
  if condition[index_draw] == '정상' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>', # <pre>태그는 popup창이 가로로 나오게 하기 위해서 추가
                  icon = folium.Icon(color='blue', icon='fa-bicycle', prefix='fa')).add_to(t_map)
  elif condition[index_draw] == 'NETWORK 에러' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>',
                  icon = folium.Icon(color='red', icon='fa-bicycle', prefix='fa')).add_to(t_map)
t_map

import folium

# 타슈 정류장의 상태에 따라서 Marker를 다른 색으로 표시 -> 정상 : 파랑, NETWORK 에러 : 빨강
df['상태정보'].unique()

# 1) 타슈 정류장 위치기반으로 중심좌표를 설정
t_map = folium.Map(location=[df['위도'].mean(),df['경도'].mean()], zoom_start=14, tiles = 'Stamen Toner')

# 2) 타슈 정류장의 상태에 따른 Marker 표시하기 위해서 상태정보를 준비
condition = df['상태정보']

# 3) 타슈 정류장 Marker 지도에 추가
for index_draw in range(0,len(condition)):
  if condition[index_draw] == '정상' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>', # <pre>태그는 popup창이 가로로 나오게 하기 위해서 추가
                  icon = folium.Icon(color='blue', icon='fa-bicycle', prefix='fa')).add_to(t_map)
  elif condition[index_draw] == 'NETWORK 에러' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>',
                  icon = folium.Icon(color='red', icon='fa-bicycle', prefix='fa')).add_to(t_map)
t_map

import folium

# 타슈 정류장의 상태에 따라서 Marker를 다른 색으로 표시 -> 정상 : 파랑, NETWORK 에러 : 빨강
df['상태정보'].unique()

# 1) 타슈 정류장 위치기반으로 중심좌표를 설정
t_map = folium.Map(location=[df['위도'].mean(),df['경도'].mean()], zoom_start=14, tiles='Stamenwatercolor')

# 2) 타슈 정류장의 상태에 따른 Marker 표시하기 위해서 상태정보를 준비
condition = df['상태정보']

# 3) 타슈 정류장 Marker 지도에 추가
for index_draw in range(0,len(condition)):
  if condition[index_draw] == '정상' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>', # <pre>태그는 popup창이 가로로 나오게 하기 위해서 추가
                  icon = folium.Icon(color='blue', icon='fa-bicycle', prefix='fa')).add_to(t_map)
  elif condition[index_draw] == 'NETWORK 에러' :
    folium.Marker([df.loc[index_draw]['위도'],df.loc[index_draw]['경도']],
                  popup = '<pre>'+df.loc[index_draw]['Station 스테이션명']+'</pre>',
                  icon = folium.Icon(color='red', icon='fa-bicycle', prefix='fa')).add_to(t_map)
t_map

LIST