4 minute read

Overview

사실 베이지언 추론을 기반으로 하는 s/w 알고리즘을 개발하는 입장에서 웹 크롤링은 별 쓸모가 없을 수 도 있다. 머신 러닝 강의라길래 들으러 갔는데 pandas와 Beautiful Soup 라이브러리 기반 웹 크롤링 수업을 해서 간단하게 배운 점을 적어본다. (이전에는 selenium으로 web cawling을 간단하게 배워본 적이 있는데, 아마 정적/동적 등 페이지 환경에 따라서 다양한 라이브러리를 사용하는 듯 하다. scrapy라는 라이브러리도 있다고 한다.) 머신 러닝 기법에 대해서는 배우지 않았지만, 웹 크롤링을 통해 얻은 빅데이터는 머신 러닝을 하기 위한 좋은 재료가 된다. 영화 리뷰 내용을 input으로 하고 리뷰의 평점을 output으로 학습시켜 댓글 내용이 긍정/부정 인지 RNN을 통해 판단한다거나, 자동차 이미지를 input으로 하고 차종을 output으로 해서 CNN 기반으로 학습시키는 등을 생각해 볼 수 있을 것 같다.

Beautiful Soup Quick Guide

Beautiful Soup은 html 문서 속에서 키워드나 클래스 등으로 원하는 데이터를 리스트의 형태로 뽑아내는 역할을 수행하는 오픈소스 라이브러리이다. 예시로 우리가 크롤링할 프로젝트 목록은 아래 그림과 같다.

아래는 아파치 오픈소스 사이트에 나열된 프로젝트를 category 별, 이름 별로 뽑아내는 과정을 설명한 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def remove_special_characters(text):
### Import Libraries
import pandas as pd
import requests # enter치는 애
from bs4 import BeautifulSoup as bs

### Example of reques library usage
target_url = 'https://apache.org/'
# res 값이 406인 경우 서버가 크롤링한 주체가 로봇이라 파악하여 data 접근을 거부한 것이다. 
res = requests.get(target_url)

### From chrome F12, make a list of interest.
soup = bs(res.text, 'html.parser')
category_list = soup.select('#by_category > ul:nth-of-type(2) > li > a')

### Process a list with key value (text, href)
categories = []
urls = []
for category in category_list:
    categories.append(category.text)
    urls.append(category.attrs['href'])

### Make dataframe. 
# Make temporal dictionary for dataframe input
tmp_dict = {
    'categories' : categories,
    'urls' : urls
}
df = pd.DataFrame(tmp_dict)
df.head()


line_10: request.get(url)

먼저 BeautifulSoup가 웹페이지를 읽기 위한 형식을 제공하기 위해, request라는 library에서 get 함수를 사용한다. Request documentation을 참조하면 return 값은 response 형태의 변수로, 이 변수에 .text를 붙여서 BeautifulSoup이 읽게 된다. 쉽게 말하면 크롬에서 F12를 눌렀을 때 나타나는 html 코드 원문을 얻기 위한 함수라고 보면 된다.

line_13: BeautifulSoup(markup, “html.parser”)

markup은 앞에서 request.get으로 얻은 object의 text 속성에 해당한다. 이 함수는 그저 텍스트 형태로서 영혼이 없는 html 원문을 beautiful soupl이 읽기 좋은 형태로 변환하는 과정일 뿐이다.

line_14: BeautifulSoup.select(select)

select함수는 html 문서 내에서 class (.을 붙여서 참조)나 id(#을 붙여서 참조) 값을 읽어들여 이에 해당하는 모든 태그를 list 형태로 반환한다. 하위 항목의 경우 > 를 사용한다. 따라서 14번 라인의 경우 by_category라는 id 에 속하는 ul 태그 중 두 번째에 속하는 li 태그에 속하는 a 태그를 뜻한다.

참조하고자 하는 id나 클래스의 이름에 띄어쓰기가 포함되어있는 경우가 있을 수 있다. 그러나 soup에서 띄어쓰기는 하위항목으로 인식한다는 문제가 있다. 따라서 이를 표현하려면 띄어쓰기 대신에 .을 사용하면 된다. 만약에 id 이름이 ‘by_category’가 아니라 ‘by category’였다면 BeautifulSoup.select(‘#by.category’) 식으로 참조를 하면 된다.

반환된 list는 태그들로 이루어져 있으므로, 태그의 속성을 참조할 때는 21번 line과 같이 .attrs[‘원하는 속성’] 식으로 접근하면 된다.

line_29: Pandas.DataFrame(dictionary)

카테고리와 url 별로 파싱된 결과를 dictionary 형태로 바꾼뒤, dataframe 형식으로 저장한다. 코드를 실행한 결과는 아래와 같다.

Leave a comment