아래 글에서 이어지는 내용이다.
foreverhappiness.tistory.com/27
BeautifulSoup를 활용한 웹 크롤링(Web Crawling) - Python3, Windows 10 (1)
아마 웹 크롤링이라는 용어는 Data Science 분야가 활성화되면서 많이 떠오르고 있을 것이다. 크롤링 (Crawling)이란, 스크래핑 (Scraping)이라고도 하는데, 웹 페이지의 특정 부분을 가져
foreverhappiness.tistory.com
정규 표현식을 사용하여 문자 필터링을 할 때는 re 모듈을 사용한다.
별도의 설치는 필요 없으며 filtering 함수를 다음과 같이 만든다.
# 문자열에서 원하는 문자만 필터링하는 함수이다.
def filtering(string: str) -> str:
# 필터링을 위해 re 모듈을 사용하였으며
# 해당 정규 표현식은 한글만 추출한다.
# findall 함수는 string에서 정규 표현식에 해당하는 부분을 추출해내며
# compile 함수를 통해 list 형식으로 반환시켜준다.
string = re.compile('[가-힣]+').findall(string)
# join 함수를 통해 list의 모든 요소들을 공백으로 구분하여 하나의 문자열로 반환한다.
return ' '.join(string)
정규 표현식에 대한 자세한 내용은 여기서 다루지 않을 것이다.
추후에 Python 문법을 정리하면서 생각나면 링크를 걸겠다.
filtering 함수는 각 행을 읽어 들여 row_list에 저장하는 과정에서 사용한다.
filtering 함수를 적용한 최종 프로그램은 다음과 같다.
# -*- encoding: utf-8 -*-
from urllib.request import urlopen
from bs4 import BeautifulSoup
import csv
import re
# 문자열에서 원하는 문자만 필터링하는 함수이다.
def filtering(string: str) -> str:
# 필터링을 위해 re 모듈을 사용하였으며
# 해당 정규 표현식은 한글만 추출한다.
# findall 함수는 string에서 정규 표현식에 해당하는 부분을 추출해내며
# compile 함수를 통해 list 형식으로 반환시켜준다.
string = re.compile('[가-힣]+').findall(string)
# join 함수를 통해 list의 모든 요소들을 공백으로 구분하여 하나의 문자열로 반환한다.
return ' '.join(string)
# 웹 페이지로부터 데이터를 크롤링한 후 데이터를 csv파일로 저장하는 함수
def get_csv() -> None:
# 크롤링 후 저장할 csv 파일을 경로로 지정
# mode를 'w' (write)로 선언
# newline을 사용하지 않으면 열과 열 사이의 비어있는 열이 하나 생긴다.
file_name = open('D:\crawling\crawling_data.csv', 'w', encoding='utf-8-sig', newline='')
# csv 모듈을 사용하여 지정한 파일의 writer 객체를 가져온다.
wr = csv.writer(file_name)
for page_num in range(1, 6771):
# 크롤링 할 홈페이지의 주소를 url 변수에 담는다.
url = 'https://icis.me.go.kr/chmCls/chmClsView.do?hlhsn_sn=' + str(page_num)
# BeautifulSoup 객체 생성
# urlopen 함수를 통해 지정한 주소에 접근할 수 있다.
# parser의 종류는 기본적으로 BeautifulSoup에서 제공하는 html.paser을 사용한다.
obj = BeautifulSoup(urlopen(url), 'html.parser')
if page_num == 1:
row_list = [] # csv 파일에 들어갈 열(row) 하나의 리스트이다.
# find_all 함수에 두 개의 파라미터가 들어가있다.
# 첫 번째 파라미터는 메타 태그, 두 번째 파라미터는 class name이다.
for item in obj.find_all('div', 's_title'):
row_list.append(filtering(str(item.find_all(text=True))))
# writerow 함수를 통해 열(row)를 삽입한다.
wr.writerow(row_list)
row_list = []
for item in obj.find_all('td', 'td_left td_wrap_max'):
row_list.append(filtering(str(item.find_all(text=True))))
wr.writerow(row_list)
file_name.close()
if __name__ == '__main__':
get_csv()
pandas를 사용한 프로그램도 역시 동일한 형태로 적용된다.
# -*- encoding: utf-8 -*-
from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import re
# 문자열에서 원하는 문자만 필터링하는 함수이다.
def filtering(string: str) -> str:
# 필터링을 위해 re 모듈을 사용하였으며
# 해당 정규 표현식은 한글만 추출한다.
# findall 함수는 string에서 정규 표현식에 해당하는 부분을 추출해내며
# compile 함수를 통해 list 형식으로 반환시켜준다.
string = re.compile('[가-힣]+').findall(string)
# join 함수를 통해 list의 모든 요소들을 공백으로 구분하여 하나의 문자열로 반환한다.
return ' '.join(string)
# 웹 페이지로부터 데이터를 크롤링한 후 데이터를 csv파일로 저장하는 함수
def get_text() -> None:
# pandas 모듈을 사용하게 되면 pandas에서 제공하는 DataFrame 객체의 형태로 저장하고 읽어들일 수 있다.
# DataFrame에 저장할 각 행을 리스트 형태로 df_list에 담는다.
df_list = []
# 첫 번째 행에 해당하는 요소들을 title_list에 담을 것이다.
title_list = []
for page_num in range(1, 6771):
# 크롤링 할 홈페이지의 주소를 url 변수에 담는다.
url = 'https://icis.me.go.kr/chmCls/chmClsView.do?hlhsn_sn=' + str(page_num)
# BeautifulSoup 객체 생성
# urlopen 함수를 통해 지정한 주소에 접근할 수 있다.
# parser의 종류는 기본적으로 BeautifulSoup에서 제공하는 html.paser을 사용한다.
obj = BeautifulSoup(urlopen(url), 'html.parser')
if page_num == 1:
# find_all 함수에 두 개의 파라미터가 들어가있다.
# 첫 번째 파라미터는 메타 태그, 두 번째 파라미터는 class name이다.
for item in obj.find_all('div', 's_title'):
title_list.append(filtering(str(item.find_all(text=True))))
row_list = []
for item in obj.find_all('td', 'td_left td_wrap_max'):
row_list.append(filtering(str(item.find_all(text=True))))
df_list.append(row_list)
# pandas 모듈의 DataFrame 객체를 통해 csv 파일에 입력할 데이터 프레임을 만든다.
# 이 때, 첫 행은 columns로 각 열에 대한 정보를 표시할 수 있다.
df = pd.DataFrame(df_list, columns=title_list)
# 간단하게 to_csv 함수로 경로를 지정해주면 csv 파일로 변환시켜준다.
# 그냥 변환시키면 자동으로 각 행에 대한 인덱스가 0부터 지정된다.
# 이를 제거하려면 index 속성을 False로 준다. 필요에 따라 True 혹은 리스트로 지정해줄 수 있다.
df.to_csv('D:\crawling\crawling_pandas_data.csv', index=False, encoding='utf-8-sig')
if __name__ == '__main__':
get_text()
이제 기본적인 내용들은 모두 끝났다.
이제 추가적으로 알아두면 좋은 몇 가지 내용들을 소개하고자 한다.
만약 encoding으로 utf-16을 사용하고 싶다면 csv 모듈을 사용한 코드에서 file_name과 wr을 다음과 같이 수정하면 된다.
file_name = open('D:\crawling\crawling_data.csv', 'w', encoding='utf-16', newline='')
wr = csv.writer(file_name, delimiter="\t")
pandas를 사용한다면 df.to_csv 부분을 다음과 같이 바꿔주면 된다.
df.to_csv('D:\crawling\crawling_pandas_data.csv', index=False, encoding='utf-16', sep='\t')
이제 parser에 대한 내용을 다루고자 한다.
지금까지는 BeautifulSoup에서 지원하는 "html.parser"를 사용했지만 이보다 더 빠른 해석기가 있다.
바로 "lxml"이라는 것이다.
하지만 별도의 설치가 필요하므로 시작 버튼 옆의 검색창에 "CMD" 혹은 "명령 프롬프트"를 입력 후 실행시켜주자.
그리고 다음과 같이 입력한다.
pip install lxml
설치가 완료되었으면 이제 html.parser 부분에 다음과 같이 lxml을 사용할 수 있다.
obj = BeautifulSoup(urlopen(url), 'lxml')
lxml은 속도가 매우 빠르고 xml로 제작된 웹 페이지는 html parser로 해석이 안되기 때문에 lxml을 사용해야 한다.
이외에도 필요에 따라 다를 수 있는데 html5lib parser도 있다.
pip install html5lib
속도가 매우 느려 쓸 데가 있을지 모르겠지만 방식은 똑같으니 필요하다면 별도의 설치를 통해 사용하면 된다.
BeautifulSoup 모듈을 사용한 웹 페이지 크롤링이 끝났다.
이제 이렇게 뽑아낸 데이터를 어떻게 가공할 것인가 어떻게 처리를 할 것인가 생각해볼 필요가 있다.
BeautifulSoup에 대해 더 자세한 내용을 알고 싶다면 아래 링크를 참고하길 바란다. (한글 문서도 있다.)
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation
Non-pretty printing If you just want a string, with no fancy formatting, you can call unicode() or str() on a BeautifulSoup object, or a Tag within it: str(soup) # ' I linked to example.com ' unicode(soup.a) # u' I linked to example.com ' The str() functio
www.crummy.com
다음 글에서는 크롤링한 데이터로 형태소 분석을 통해 DTM(Document-Term Matrix, 문서 단어 행렬)을 만드는 방법을 알아보겠다.