본문 바로가기
Back-end/Python

[크롤링] 무작정 시작하기 (1) - 패키지 선택

by 허도치 2019. 11. 19.

  웹에는 방대한 양의 데이터들이 존재한다. 원하는 정보를 얻기위해 하나하나 검색해가며 데이터를 수집하는 것은 비효율적인 일이다. 이 때, 우리에게 필요한 것이 바로 '웹 크롤러(Web Crawler)'이다.

  웹 크롤러(이하 크롤러)는 웹에서 특정 데이터들을 수집하는 일을 자동화한 프로그램이며, web-scraping, spidering이라고도 불리운다. 크롤러는 크게 수집(Scrapping)과 가공(Parsing) 두개의 단계로 구분되어진다.

 

 

  수집(Scrapping)은 웹페이지의 HTML 소스를 긁어오는 것으로 urllib, requests, selenium 등의 라이브러리가 사용된다.

 

1. urllib

  python 기본 라이브러리이며 request를 작성하는 방식이 사용자 친화적이지 않아서 불편하지만, URL을 핸들링하기 위한 모듈들이 내장되어 있어서 종종 사용한다.

1
2
3
4
5
6
7
import urllib.request
import urllib.parse
 
post_data = urllib.parse.urlencode( { 'name''heodolf''job''programmer' } ).encode('utf-8')
request = urllib.request.Request( 'https://heodolf.tistory.com', post_data )
request.add_header('Content-Type', 'application/json; charset=utf-8')
response = urllib.request.urlopen( request )
body = response.read() # return type bytes
cs

 

2. requests( Requests: HTTP for humans )

  풀네임에서도 알 수 있듯이 사용자 친화적인 문법을 사용하여 다루기 쉬우면서도 안정성이 뛰어나다.

1
2
3
4
5
6
import requests
 
headers = {'Content-Type''application/json; charset=utf-8'}
post_data = {'name''hoedolf''job':'programmer'}
response = requests.post('https://heodolf.tistory.com', headers=headers, data=post_data )
body = response.text # return type str
cs

 

3. selenium

  이 라이브러리는 HTTP요청을 위한 라이브러리가 아니라 웹 어플리케이션을 테스트하기위한 라이브러리로 webdriver를 이용하여 웹 브라우저를 실행하고 출력된 화면을 response로 받는다. 이번에 만들 크롤러는 이 라이브러리를 사용할 것이며, selenium이 제공하는 많은 기능(자동 입력, 로그인 등)중에 주로 request를 사용할 계획이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
 
CHROMEDRIVER_PATH = 'drivers/chromedriver_78' # Windows는 chromedriver_78.exe
WINDOW_SIZE = "1920,1080"
 
chrome_options = Options()
chrome_options.add_argument(f"--window-size={ WINDOW_SIZE }")
chrome_options.add_argument('Content-Type=application/json; charset=utf-8')
 
driver = webdriver.Chrome( executable_path=CHROMEDRIVER_PATH, chrome_options=chrome_options )
driver.get( 'https://heodolf.tistory.com' )
 
body = driver.page_source # return type str
cs

  지금은 HTTP요청(requests, urllib)과 selenium의 차이가 느껴지지 않을 것이다. 가장 큰 차이점만 비교하자면 HTTP요청은 request를 던지는 즉시 response를 받지만, selenium은 페이지가 로드된 후에 response를 받는다. HTML이 한번만 로드되는 정적 웹페이지를 수집할 때는 크게 차이를 느끼지 못하지만, HTML이 로드되고 Javascript로 화면을 한번 더 렌더링하는 동적 웹페이지는 HTTP요청으로는 수집할 수 없다.

  정리하면 HTTP요청은 수집 속도가 빠르지만 동적 웹페이지를 수집할 수 없고, selenium은 수집 속도는 HTTP요청에 비해 느리지만 동적 웹페이지까지 수집이 가능하다는 장점이 있다.

 

 

  가공(Parsing)에는 흔하게 사용되는 것이 BeautifulSoup4와 Scrapy가 있다.

 

1. BeautifulSoup4(이하 bs4)

  사용방법이 간단하고 예제들이 많아서 배우기 쉽다. requests와 함께 사용하면 단 몇줄만으로 크롤러를 만들 수 있으며 parsing로 선호도가 가장 높은 편이다.

1
2
3
4
5
6
7
8
9
10
import requests
from bs4 import BeautifulSoup as bs
 
response = requests.get('https://www.google.com/')
html = bs( response.text, 'html.parser')
 
google_logo = html.find('img', {'id':'hplogo'})
 
# output
<img alt="Google" height="92" id="hplogo" src="/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png" style="padding:28px 0 14px" width="272"/>
cs

 

2. Scrapy

  scrapy은 parsing만을 위한 라이브러리가 아니라 수집과 가공을 모두 할 수 있는 웹 크롤링 프레임워크이다. bs4처럼 단순하지 않아서 진입장벽이 높지만 이미지 또는 파일 다운로드( MediaPipeline )와 API호출( scrapyd, scrapyrt ) 등 강력한 기능들을 제공해주고 커스터마이징이 가능하기 때문에 이 라이브러리를 사용할 계획이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ scrapy startproject crawler
│  scrapy.cfg
└─crawler
    │  items.py
    │  middlewares.py
    │  pipelines.py
    │  settings.py
    │  __init__.py
    │
    ├─spiders
    │  │  __init__.py
    │  │
    │  └─__pycache__
    └─__pycache__
cs

 

  bs4와 scrapy의 가공(parsing)기능만 놓고보았을 때의 차이점은 XPATH의 사용여부이다. 크롤링에 있어서 XPATH는 필수적인 요소는 아니지만 데이터의 가공을 편하게 해주는 것에는 틀림없다. XPATH는 scrapy에서만 지원하고 bs4에서는 CSS Selector를 기반으로 가공해야한다.

( XPATH와 CSS Selector는 다른 포스트에서 비교하여 보도록한다. )

 

 

마치며...

  지금까지 크롤러를 만들기위한 수집(Scraping)과 가공(Parsing) 라이브러리들을 살펴보았다. 정리하자면 단순하게 글의 목록이나 본문의 내용을 수집하는 크롤러를 만들고자 한다면 requests와 bs4를 조합하여 만드는 것을 추천하며, 좀 더 자동화된 강력한 기능을 제공하는 크롤러를 만들고자 한다면 Selenium과 Scrapy를 함께 사용하는 것을 추천한다.

  

 

이번 크롤러는 Selenium과 Scrapy를 조합하여 만들도록 하겠다.

댓글