[python] 파이썬 웹 크롤링(7): 데이터 클리닝
업데이트:
파이썬 웹 크롤링(7): 데이터 클리닝
본 포스팅은 Web Scraping with Python by Ryan Mitchell을 참고하였습니다.
참고 링크
- 파이썬 웹 크롤링(1): 크롤링의 기본구조와 BeautifulSoup 설치
- 파이썬 웹 크롤링(2): 데이터 파싱하기
- 파이썬 웹 크롤링(3): 본격적인 크롤링
- 파이썬 웹 크롤링(4): API 활용하기
- 파이썬 웹 크롤링(5): 데이터 저장하기
- 파이썬 웹 크롤링(6): 데이터 읽기
Chapter 7: 데이터 클리닝
7.1 코드 내에서 클리닝하기
아래 코드는 위키피디아 문서에서 2-grams의 리스트를 찾아 리턴하는 코드 입니다. 언어학에서 n-grma이란 n개의 단어 시퀀스를 의미합니다.
from urllib.request import urlopen
from bs4 import BeautifulSoup
def ngrams(input, n):
input = input.split(' ')
output = []
for i in range(len(input)-n+1):
output.append(input[i:i+n])
return output
html = urlopen("http://en.wikipedia.org/wiki/Python_(programming_language)")
bsObj = BeautifulSoup(html)
content = bsObj.find("div", {"id":"mw-content-text"}).get_text()
ngrams = ngrams(content, 2)
print(ngrams)
print("2-grams count is: "+str(len(ngrams)))
ngrams 함수는 인풋 문자를 가지고 단어의 시퀀스를 공백을 기준으로 분리합니다. 그리고 n-grma을 더합니다. 위 코드는 아래와 같은 결과를 보여주지만
['of', 'free'], ['free', 'and'], ['and', 'open-source'], ['open-source', 'software']
다음과 같은 쓸데없는 것도 많이 나옵니다.
['software\nOutline\nSPDX\n\n\n\n\n\n\n\n\nOperating', 'system\nfamilies\n\n\n\n
AROS\nBSD\nDarwin\neCos\nFreeDOS\nGNU\nHaiku\nInferno\nLinux\nMach\nMINIX\nOpenS
olaris\nPlan'], ['system\nfamilies\n\n\n\nAROS\nBSD\nDarwin\neCos\nFreeDOS\nGNU\
nHaiku\nInferno\nLinux\nMach\nMINIX\nOpenSolaris\nPlan', '9\nReactOS\nTUD:OS\n\n
\n\n\n\n\n\n\nDevelopment\n\n\n\nBasic'], ['9\nReactOS\nTUD:OS\n\n\n\n\n\n\n\n\n
Development\n\n\n\nBasic', 'For']
아래 코드와 같이 정규표현식을 이용하면 유니코드 문자를 제거할 수 있습니다.
def ngrams(input, n):
content = re.sub('\n+', " ", content)
content = re.sub(' +', " ", content)
content = bytes(content, "UTF-8")
content = content.decode("ascii", "ignore")
print(content)
input = input.split(' ')
output = []
for i in range(len(input)-n+1):
output.append(input[i:i+n])
return output
이는 결과를 개선해주지만 여전히 이슈가 남아있습니다.
['Pythoneers.[43][44]', 'Syntax'], ['7', '/'], ['/', '3'], ['3', '=='], ['==', '2']
이를 해결하기 위해 좀 더 여러가지 룰이 필요합니다.
- i와 a를 제외한 오직 하나로 구성된 문자는 버립니다.
- 위키피디아의 인용 마크는 버립니다.
- 마침표는 버립니다.
자, 이제 cleaning task가 더 길어집니다.
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
import string
def cleanInput(input):
input = re.sub('\n+', " ", input)
input = re.sub('\[[0-9]*\]', "", input)
input = re.sub(' +', " ", input)
input = bytes(input, "UTF-8")
input = input.decode("ascii", "ignore")
cleanInput = []
input = input.split(' ')
for item in input:
item = item.strip(string.punctuation)
if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'):
cleanInput.append(item)
return cleanInput
def ngrams(input, n):
input = cleanInput(input)
output = []
for i in range(len(input)-n+1):
output.append(input[i:i+n])
return output
['Linux', 'Foundation'], ['Foundation', 'Mozilla'], ['Mozilla', 'Foundation'],
['Foundation', 'Open'], ['Open', 'Knowledge'], ['Knowledge', 'Foundation'],
['Foundation', 'Open'], ['Open', 'Source']
7.1.1 Data Normalization
데이터 표준화란 데이터의 형식을 맞추는 것을 말합니다. 예를 들어, 전화번호를 입력한다고 하면, (555) 123-4567 혹은 555.123.4567과 같이 똑같은 형태로 입력하는 것입니다. 전화번호의 경우 사람마다 입력하는 방식이 다르기 때문입니다.