Data Science/자연어 처리 (NLP)

BeautifulSoup를 활용한 웹 크롤링(Web Crawling) - Python3, Windows 10 (1)

 

아마 웹 크롤링이라는 용어는 Data Science 분야가 활성화되면서 많이 떠오르고 있을 것이다.

크롤링 (Crawling)이란, 스크래핑 (Scraping)이라고도 하는데, 웹 페이지의 특정 부분을 가져와서(긁어와서) 필요한 데이터를 추출해내는 작업을 말한다.

빅 데이터 분야에서는 이를 유용하게 활용하고 있지만 약 10년 전 그리고 그 이전에는 크롤링 행위가 웹 해킹에 사용되기도 했다. 물론 지금은 웹 보안도 많이 발전해서 웬만한 크롤링 작업은 의미가 없다.

Python 언어는 데이터 분석 분야에서 웹 크롤링을 하는데 선두 주자로 볼 수 있다.

꼭 프로그래머나 개발자가 아니더라도 일반 학생, 일반인들도 쉽게 사용할 수 있도록 제작된 라이브러리가 제공되고 있다.

그것이 바로 BeautifulSoup이며 이 모듈을 사용하여 웹 페이지를 크롤링 후 필요 데이터만 추출해낼 것이다.

아직 Python3에 대해 잘 모르거나 Python이 설치도 되어 있지 않거나 편집기가 설치되어 있지 않다면 Language > Python 카테고리의 게시글들을 참고하길 바란다.

 

foreverhappiness.tistory.com/category/Language/Python3

 

'Language/Python3' 카테고리의 글 목록

 

foreverhappiness.tistory.com


 

운영체제는 Windows10에서 진행하였다.

 

먼저 BeautifulSoup 모듈을 설치해야 한다.

 

왼쪽 하단의 시작 옆 검색창에서 "CMD" 혹은 "명령 프롬프트"를 실행시킨 후 다음과 같이 입력한다.

 

pip install beautifulsoup4

 

그러면 아마 다음과 같은 오류를 만나게 될 것이다.

 

 

설치되어 있는 pip 명령어를 업데이트해주지 않아서 발생한 오류이다.

해결법은 간단하다. pip의 버전을 업그레이드시켜주면 된다.

다음과 같이 입력해보자.

 

python -m pip install --upgrade pip

 

그럼 업그레이드가 진행될 것이며 BeautifulSoup 모듈을 설치할 수 있을 것이다.

 

혹시 pip 명령어를 찾을 수 없다는 오류가 발생한다면 아래 링크를 참고하여 환경 변수(Path) 체크를 확인하자.

 

foreverhappiness.tistory.com/25

 

파이썬 3 (Python 3) 설치하기 (For Windows)

최근 들어 파이썬의 비중이 많이 높아지고 있다. 파이썬으로 게임을 제작하기도 하고, 인공지능, 빅데이터 분석에도 많은 라이브러리들이 제공되기도 한다. 삼성 SW 역량 평가에 Python 언어도 포

foreverhappiness.tistory.com

 


 

설치가 완료되었으면 이제 코드를 작성할 차례이다.

 

원하는 페이지 주소에 접근을 요청할 때 쓰는 모듈로는 urllib를 사용하는데 별도의 설치 없이 사용할 수 있다.

 

이제 사용 중인 편집기로 가서 파이썬 코드로 다음과 같이 입력해보자.

 

from urllib.request import urlopen
from bs4 import BeautifulSoup

 

위 코드를 입력했을 때 빨간 밑줄이나 에러가 없다면 설치가 제대로 진행된 것이다.

 


 

본격적으로 크롤링을 진행해보자.

 

크롤링을 진행할 홈페이지는 아래 링크로 걸어두었다.

 

https://icis.me.go.kr/main.do

 

화학물질종합정보시스템

화학물질정보 제공 건수 52,509 (NCIS : 45,839 / KISChem : 6,670) 중 고시기준 유독, 제한, 금지, 사고대비물질 건수 유독물질 고시 : 915 NCIS : 1,841 KISChem : 1,586 제한물질 고시 : 54 NCIS : 100 KISChem : 84 금지물질 고시 : 27 NCIS : 106 KISChem : 101 사고대비물질 고시 : 97 NCIS : 99 KISChem : 70 팝업창닫기 화관법민원24 민원처

icis.me.go.kr

 

위 페이지에서 활용(크롤링)할 수 있는 정보들은 많다.

확인한 후 어떤 페이지를 크롤링할 것인지 정해보자.

 


 

정했다면 이제 get_csv라는 함수를 하나 만들어줄 것이다.

get_csv 함수는 웹 페이지로부터 데이터를 크롤링한 후 이를 csv 파일에 저장하는 기능을 한다.

 

이때 csv 파일에 저장하기 위해 별도의 설치 없이 csv 모듈을 사용할 수도 있는데, pandas 모듈을 활용하면 데이터를 처리하는데 매우 편리하므로 pandas 모듈을 설치해줄 것이다.

 

csv 모듈을 사용하면 행(row)을 csv 파일에 입력해줄 때 행과 행 사이에 비어있는 행이 하나 더 생긴다.

즉, 행과 행을 띄워서 파일에 입력해주기 때문에 데이터를 처리할 때 불편함이 있다.

 

물론 해결 방법이 있기 때문에 여기서는 csv 모듈과 pandas 모듈 두 가지 방법 모두 설명할 것이다.

 

우선, pandas 모듈 설치를 위해 명령 프롬프트로 돌아가서 다음 명령을 입력하여 설치를 먼저 해두자.

 

pip install pandas

 

설치가 끝났다면 이제 get_csv 함수를 작성해보자.

 

# -*- encoding: utf-8 -*-
from urllib.request import urlopen
from bs4 import BeautifulSoup
import csv


# 웹 페이지로부터 데이터를 크롤링한 후 데이터를 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 함수에 두 개의 파라미터가 들어가있다.
            # 첫 번째 파라미터는 tag name, 두 번째 파라미터는 class name이다.
            for item in obj.find_all('div', 's_title'):
                row_list.append(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(str(item.find_all(text=True)))

        wr.writerow(row_list)

    file_name.close()


if __name__ == '__main__':
    get_csv()

 

각 내용들을 주석으로 달아두었지만 추가 설명이 필요하다.

 

우선 csv 모듈을 사용하기 위해 상단에 import csv를 선언해주었다.

 

get_csv 함수 내부에서는 csv 모듈의 약점인 행과 행 사이에 비어있는 행을 만들지 않게 하기 위해 newline 속성을 넣어 보완하였다.

 

반복문을 6770회 돌린 이유는 크롤링한 페이지를 참고해보면 알 수 있다.

해당 페이지에 6770가지 화학 물질에 대한 정보가 들어 있으며 이를 크롤링하였다.

 

BeautifulSoup 객체를 생성할 때 속성 값으로 넣어준 'html.paser'는 홈페이지의 해석기를 넣어준 것이며 BeautifulSoup에서는 기본적으로 해당 해석기를 지원하고 있다.

 

각 해석기마다 동일한 문서에 대해 다른 해석 트리를 만들어내기 때문에 이외의 해석기를 사용하고 싶을 수 있다.

이에 대한 내용은 밑에서 추가적으로 다루겠다.

 

find_all 함수에는 두 가지 파라미터가 들어가 있는데 각각 tag와 class명을 의미한다.

홈페이지에서 크롤링하고자 하는 데이터의 태그와 클래스명을 확인하려면 아래 링크를 참고하자.

 

foreverhappiness.tistory.com/29

 

XPath를 이용하여 문서의 XML 요소 ,경로 찾기

우리가 컴퓨터에서 어떤 문서를 찾을 때 "C:\Program Files\Android\Android Studio" 이와 같은 것을 경로, 즉 Path라고 말한다. XPath란, XML Path Language로 XML 문서의 어떤 경로에 접근하기 위해 사용된다. X..

foreverhappiness.tistory.com

 


 

위 코드를 실행시키면 csv 파일이 생성될 것이고 다음과 같이 저장될 것이다.

 

 

물론 6770회를 모두 실행하지는 않았고 중간에 종료하여 결과를 확인해보았다.

 

저장은 성공적으로 되었지만 쓸 데 없는 문자들이 많이 들어가 있다.

 

이를 필터링하기 위해서 정규 표현식이 사용된다.

 


 

정규 표현식을 통한 필터링을 살펴보기 전에 pandas 모듈을 사용한 방법도 알아보자.

 

# -*- encoding: utf-8 -*-
from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd


# 웹 페이지로부터 데이터를 크롤링한 후 데이터를 csv파일로 저장하는 함수
def get_csv() -> None:
    # pandas 모듈을 사용하게 되면 pandas에서 제공하는 DataFrame 객체의 형태로 저장하고 읽어들일 수 있다.
    # DataFrame에 저장할 각 행을 리스트 형태로 df_list에 담는다.
    df_list = []

    # 첫 번째 행에 해당하는 요소들을 title_list에 담을 것이다.
    title_list = []

    for page_num in range(1, 10):
        # 크롤링 할 홈페이지의 주소를 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 함수에 두 개의 파라미터가 들어가있다.
            # 첫 번째 파라미터는 tag name, 두 번째 파라미터는 class name이다.
            for item in obj.find_all('div', 's_title'):
                title_list.append(str(item.find_all(text=True)))

        row_list = []
        for item in obj.find_all('td', 'td_left td_wrap_max'):
            row_list.append(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_csv()

 

이번에는 파일을 열었다 닫았다 할 필요 없이 csv에 저장할 데이터들을 데이터 프레임 형식으로 만든다.

한번 직접 해보면 데이터 프레임 형식이 어떻게 되는지 느낌이 올 것이다.

 

결과물은 csv 모듈을 사용한 것과 동일하다.

 

csv형식으로 변환할 때는 to_csv 함수를 통해 데이터 프레임 자체를 한 번에 변환시킬 수 있다.

 

한 번에 변환시키기 때문에 데이터양이 많을 경우에는 메모리와 시간이 많이 소모될 수 있다.

그래서 개인적으로 데이터를 크롤링 후 저장하는 과정에서는 row를 읽어 들일 때마다 기록하는 csv 모듈을 사용하는 것을 추천한다.


글이 너무 길어져 다음 글에서 정규 표현식을 사용하여 필터를 제작하는 방법부터 시작하겠다.

 

foreverhappiness.tistory.com/28

 

BeautifulSoup를 활용한 웹 크롤링(Web Crawling) - Python3, Windows 10 (2)

아래 글에서 이어지는 내용이다. https://foreverhappiness.me/27 BeautifulSoup를 활용한 웹 크롤링(Web Crawling) - Python3, Windows 10 (1) 아마 웹 크롤링이라는 용어는 Data Science 분야가 활성화되면서 많..

foreverhappiness.tistory.com