[데이터 크롤링] 위키피디아 표 데이터 크롤링 하기

이 글은 위키피디아에 존재하는 표 형태의 데이터를 크롤링 하는 방법에 관한 기록입니다.

실습 Code

먼저 필요한 라이브러리를 불러옵니다.

from bs4 import BeautifulSoup
from html_table_parser import parser_functions as parser
import pandas as pd
import requests

크롤링 하고자 하는 웹페이지 주소를 설정합니다. 아래의 경우 위키피디아에서 제공하는 2019년 대한민국 영화 목록을 크롤링 하고자 합니다.

# 크롤링 하고자 하는 웹페이지 주소 설정
url = 'https://ko.wikipedia.org/wiki/2019년_대한민국의_영화_목록'

이제 해당 url에 대하여 HTTP request를 통해 HTML response를 받습니다.

req = requests.get(url)
html = req.text
soup = BeautifulSoup(html, 'html.parser')

해당 웹페이지에서 크롤링 하고자 하는 표의 속성을 확인한 후 find_all() 함수를 통해 HTML에서 해당 표만을 추출합니다. 아래의 경우 HTML에서 classsortable wikitabletable 태그만을 추출하고자 합니다.

# 크롤링 하고자 하는 표 : <table class="sortable wikitable">
tables = soup.find_all('table', attrs={'class':'sortable wikitable'})

이제 변수 tables에 담겨있는 정보들을 데이터프레임 형태로 변환합니다.

# 데이터프레임 생성
temp = []
for table in tables:
    table = parser.make2d(table)
    table = pd.DataFrame(table[1:])
    temp.append(table)
df = pd.concat(temp)
df
0 1 2 3 4 5 6
0 1월 1일 〈언니〉 (주)제이앤씨미디어그룹 , TCO(주)더콘텐츠온 감독 임경택출연 이시영, 박세완, 이준혁, 최진호 액션 청소년 관람불가 (대한민국)
1 1월 9일 〈내안의 그놈〉 (주)메리크리스마스 감독 강효진출연 박성웅, 진영, 라미란 코미디, 판타지 15세 관람가 (대한민국)
2 1월 9일 〈말모이〉 롯데 엔터테인먼트 감독 엄유나출연 유해진, 윤계상 드라마 12세 관람가 (대한민국)
3 1월 16일 〈그대 이름은 장미〉 (주)리틀빅픽쳐스 감독 조석현출연 유호정, 박성웅, 오정세, 채수빈, 하연수 코미디 12세 관람가 (대한민국)
4 1월 16일 〈언더독〉 (주)NEW 감독 오성윤, 이춘백출연 도경수, 박소담, 박철민 애니메이션 전체 관람가 (대한민국)
... ... ... ... ... ... ... ...
56 12월 4일 〈너의 여자친구〉 (주)스톰픽쳐스코리아, 와이드 릴리즈(주) 감독 이장희 출연 이엘리야, 지일주, 허정민, 김기두, 이진이 코미디, 멜로, 로맨스 12세 관람가 (대한민국)
57 12월 12일 〈속물들〉 (주)삼백상회 300 & Co. 감독 신아가, 이상철 출연 유다인, 심희섭, 송재림 블랙코미디 15세 관람가 (대한민국)
58 12월 18일 〈시동〉 넥스트 엔터테인먼트 월드 감독 최정열 출연 마동석, 박정민, 정해인, 염정아 드라마 15세 관람가 (대한민국)
59 12월 19일 〈백두산〉 (주)CJ ENM 감독 이해준, 김병서출연 이병헌, 하정우, 마동석, 전혜진, 배수지 어드벤처, 드라마 12세 관람가 (대한민국)
60 12월 26일 〈천문: 하늘에 묻는다〉 롯데엔터테인먼트 감독 허진호 출연 최민식, 한석규 사극 12세 관람가 (대한민국)

121 rows × 7 columns

데이터프레임의 간략한 정보를 확인합니다.

df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 121 entries, 0 to 60
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   0       121 non-null    object
 1   1       114 non-null    object
 2   2       114 non-null    object
 3   3       114 non-null    object
 4   4       114 non-null    object
 5   5       114 non-null    object
 6   6       114 non-null    object
dtypes: object(7)
memory usage: 7.6+ KB

크롤링 후처리를 합니다.

df.columns = ['개봉월', '개봉일', '제목', '제작/배급', '출연/제작진', '장르', '등급'] # 컬럼명 변경
df.dropna(inplace=True) # 결측치 제거
df.reset_index(drop=True, inplace=True) # 인덱스 재설정

최종적인 데이터셋은 다음과 같습니다.

df
개봉월 개봉일 제목 제작/배급 출연/제작진 장르 등급
0 1월 1일 〈언니〉 (주)제이앤씨미디어그룹 , TCO(주)더콘텐츠온 감독 임경택출연 이시영, 박세완, 이준혁, 최진호 액션 청소년 관람불가 (대한민국)
1 1월 9일 〈내안의 그놈〉 (주)메리크리스마스 감독 강효진출연 박성웅, 진영, 라미란 코미디, 판타지 15세 관람가 (대한민국)
2 1월 9일 〈말모이〉 롯데 엔터테인먼트 감독 엄유나출연 유해진, 윤계상 드라마 12세 관람가 (대한민국)
3 1월 16일 〈그대 이름은 장미〉 (주)리틀빅픽쳐스 감독 조석현출연 유호정, 박성웅, 오정세, 채수빈, 하연수 코미디 12세 관람가 (대한민국)
4 1월 16일 〈언더독〉 (주)NEW 감독 오성윤, 이춘백출연 도경수, 박소담, 박철민 애니메이션 전체 관람가 (대한민국)
... ... ... ... ... ... ... ...
109 12월 4일 〈너의 여자친구〉 (주)스톰픽쳐스코리아, 와이드 릴리즈(주) 감독 이장희 출연 이엘리야, 지일주, 허정민, 김기두, 이진이 코미디, 멜로, 로맨스 12세 관람가 (대한민국)
110 12월 12일 〈속물들〉 (주)삼백상회 300 & Co. 감독 신아가, 이상철 출연 유다인, 심희섭, 송재림 블랙코미디 15세 관람가 (대한민국)
111 12월 18일 〈시동〉 넥스트 엔터테인먼트 월드 감독 최정열 출연 마동석, 박정민, 정해인, 염정아 드라마 15세 관람가 (대한민국)
112 12월 19일 〈백두산〉 (주)CJ ENM 감독 이해준, 김병서출연 이병헌, 하정우, 마동석, 전혜진, 배수지 어드벤처, 드라마 12세 관람가 (대한민국)
113 12월 26일 〈천문: 하늘에 묻는다〉 롯데엔터테인먼트 감독 허진호 출연 최민식, 한석규 사극 12세 관람가 (대한민국)

114 rows × 7 columns

이를 csv 파일로 저장합니다.

# 데이터프레임 저장
df.to_csv('WikipediaTable.csv')

전체 Code

### Crawling ###

# 위키피디아 표 데이터 크롤링 함수 #
def CrawlingWikipediaTable(url, tag, columns):
    """
    url -> str : 크롤링 하고자 하는 위키피디아 url
    tag -> str : 크롤링 하고자 하는 위키피디아 표 태그의 class
    columns -> list : 데이터프레임 컬럼명
    """
    
    import requests
    from bs4 import BeautifulSoup
    from html_table_parser import parser_functions as parser
    import pandas as pd

    req = requests.get(url)
    html = req.text
    soup = BeautifulSoup(html, 'html.parser')
    tables = soup.find_all('table', attrs={'class':tag})
    temp = []
    for table in tables:
        table = parser.make2d(table)
        table = pd.DataFrame(table[1:])
        temp.append(table)
    res = pd.concat(temp)

    res.columns = columns
    res.dropna(inplace=True)
    res.reset_index(drop=True, inplace=True)

    return res

댓글남기기