크롤링 (Crawling)
크롤링은 무엇인가?
크롤링 내용을 진행하기 전에 크롤링을 포함해서 데이터를 외부에서 자동화된 방법으로 가져오는 것에 대한 이해가 필요하다. 흔히 웹페이지에서 데이터를 가져오는 것을 크롤링이라고 하는데 모두 크롤링은 아니고 웹스크래핑, 피딩, 크롤링으로 나눌 수 있다. 크롤링에서 크롤(crawl)은 긁는다는 뜻이다. 데이터를 곡괭이나 갈퀴로 긁어 온다고는 의미에서 크롤이라는 이름을 붙인 것은 아니다. 크롤의 의미는 웹페이지의 내용을 수집하는 로봇인 스파이더와 관련이 있는데 오래전에 월드와이드앱이 나온 후에 웹 페이지를 사람들이 탐색하기 시작했지만 주소를 외외서 탐색하는 것이 어려워 웹사이트의 페이지를 자동으로 추출해서 제목, 내용물, 링크를 수집해서 웹페이지로 제공하거나 검색을 할 수 있는 서비스를 운영하게 되었다. 이때 웹의 페이지를 수집하는 소프트웨어를 거미줄 위에서 돌아다니는 거미에 비유해서 스파이더(Spider)라고 불렀다. 수집을 자동으로 하기 때문에 로봇의 줄임말로 봇(bot)이라고 부르기도 한며 합쳐서 스파이더봇(spiderbot)이라고 부르기도 한다. 크롤(crawl)이라는 용어는 거미가 거미줄 위에서 발로 거미줄을 긁으며 돌아다니는 행동에서 유래했다. 웹 크롤러가 인터넷을 탐색하는 방식이 이와 유사하여 이런 이름이 붙게 되었다.
크롤러(crawler)는 보통 구글, 빙, 네이버와 같은 검색 서비스에서 주로 운영한다. 검색 엔진에서 운영하는 크롤러는 작고 단순한 소프트웨어가 아니고 거대하고 복잡한 플랫폼이고 여러개를 분할해서 운영하는 경우가 많다. 크롤러는 크게 두 가지 일을 하는데 하나는 페이지에서 링크를 수집해서 저장하고 다른 하나는 수집한 링크에서 컨텐츠를 다운로드 해서 저장하는 것이다. 구조에 따라 링크만 수집하는 것과 컨텐츠를 다운로드 하는 것이 분리되어 있기도 하고 한 번에 같이 하기도 한다.
웹스크래핑과 크롤링 (web scraping and crawling)
데이터 분석에서 사용하는 데이터를 앞에서 말한 크롤러를 쓰는 것이 아닌 가져오고 싶은 자료가 있는 웹사이트에서 JSON 포맷이나, csv, excel등 을 바로 다운로드 받거나 REST API를 통해서 가져오는 것 또는 HTML 파일에서 텍스트를 추출하는 것이다. 이런 작업은 원래의 의미를 보면 크롤링이 아니라 웹스크랩핑(webscraping)이나 다운로드(download)라고 해야 맞다. 하지만 많은 사람들이 크롤링이라는 단어에 그런 것을 모두 포함해서 말하므로 이 책에서도 크롤링이라는 단어를 그런 의미로 사용하기로 한다.
API를 이용한 연동
API(Application Programming Interface) 소프트웨어나 서비스가 서로 데이터를 주고받거나 기능을 사용할 수 있도록 하는 규칙을 의미한다. 웹사이트나 애플리케이션에서 외부의 데이터를 자동으로 가져오거나 다른 서비스의 기능을 활용하고 싶을 때 API를 사용한다. 오래전에 API는 PC나 맥에서 작동한 애플리케이션 소프트웨어를 제어하고 다른 애플케이션과 연동하기 위해 고안되었지만 후에 웹 애플리케이션에도 사용되기 시작했다. 웹사이트 또는 웹서비스가 제공하는 API는 주로 HTTP 프로토콜을 통해 요청(request)과 응답(response) 방식으로 동작하는데 JSON, XML 등 다양한 데이터 포맷을 사용한다. 근래에는 JSON 포맷이 일반적이고 그 외에 다른 포맷도 있다. 데이터 분석에서 데이터 거래 사이트나 공공데이터 포털, 포털 사이트에서 자료를 제공할 때 이 방식을 갆이 이용한다. API를 사용하기 위해서 접근 허가를 위한 계정을 받거나 계정 대신 사용할 토큰과 같은 것을 받아야 하는 경우가 많다 또 유료인 경우도 있어 사용하기 확인해야 할 것이 있다. 그래서 API를 사용하기 위해서 먼저 확인해야 하는것들이 있다.
- API 문서 확인: 해당 API의 공식 문서를 통해 사용법, 제공 데이터 구조, 엔드포인트를 파악해야 한다.
- 인증 방식: API 키, OAuth, 토큰 등 어떤 인증 방식을 사용하는지와 발급 방법을 확인한다.
- 요청 제한(Rate Limit): 일일 또는 분당 요청 가능한 횟수가 제한하는 경우가 많으므로 확인이 필요하다.
- 응답 형식: JSON, XML 등 어떤 형식으로 데이터를 제공하는 확인한다.
- 필수 파라미터: API 호출 시 반드시 포함해야 하는 파라미터(parameter)를 확인한다.
- 비용 정책: 무료인지, 유료인지, 사용량에 따른 과금 방식은 어떤지 확인한다.
Python으로 공공데이터 API 활용 예제
아래는 한국 공공데이터 포털에서 제공하는 날씨 데이터를 API를 이용해서 가져오는 예제다.
((프롬프트)): 한국 내 데이터를 API를 이용해서 가져오는 간단한 Python 에제를 보여주세요 ((AI챗봇 답)):
import requests
import pandas as pd
# 공공데이터 API 호출 예제
def get_korea_weather():
# 기상청 단기예보 API URL
url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst"
# API 요청 파라미터
params = {
'serviceKey': '발급받은_API_키', # 공공데이터 포털에서 발급받은 키
'pageNo': '1',
'numOfRows': '10',
'dataType': 'JSON',
'base_date': '20230601', # 날짜(yyyyMMdd)
'base_time': '0500', # 시간(hhmm)
'nx': '60', # 좌표X (서울 강남구)
'ny': '127' # 좌표Y
}
# API 요청 보내기
response = requests.get(url, params=params)
# 응답 처리
if response.status_code == 200:
data = response.json()
# 데이터프레임으로 변환
items = data['response']['body']['items']['item']
df = pd.DataFrame(items)
return df
else:
print(f"API 요청 실패: {response.status_code}")
return None
# 사용 예시
weather_df = get_korea_weather()
if weather_df is not None:
print(weather_df.head())
이 예제는 기상청 단기예보 API를 사용하여 특정 지역의 날씨 데이터를 JSON 형식으로 받아와 Pandas dataframe 자료구조로 바꾼다. "발급받은_API_키"부분은 실제로 공공데이터 포털에서 API 키를 발급받고나서 받은 것으로 바꾸고 실행해야 한다. 웹사이트가 제공하는 API를 사용하기 위해서는 계정과 토큰이 빌도로 필요한 경우가 많고 유료인 경우도 많다. 그래서 API를 사용하기 위해서 먼저 확인해야 하는것들이 있다.
피딩 (Feeding)
피딩은 웹사이트나 온라인 서비스가 데이터를 일정한 형식으로 제공하는 방식을 말한다. RSS(Really Simple Syndication)나 Atom 피드가 대표적인 예다. 피딩은 웹사이트에서 새로운 콘텐츠가 업데이트되면 사용자에게 자동으로 알려주는 기능을 제공한다. 크롤링이나 스크래핑과 달리 피딩은 웹사이트 운영자가 의도적으로 데이터를 구조화하여 제공하기 때문에 데이터를 가져오는 과정이 상대적으로 간단하고 정확하다. 피드는 XML 형식으로 제공되는 경우가 많으며, 뉴스 사이트, 블로그, 팟캐스트 등에서 널리 사용된다. 데이터 분석가나 개발자는 이러한 피드를 구독하고 파싱하여 필요한 정보를 쉽게 추출할 수 있다.
왜 크롤링을 하는가?
데이터는 비교적 가치고 높다. 자기 조직의 데이터를 무료로 외부에 제공하는 경우는 법적으로든 비즈니스적으로든 일반적이지 않다. 웹서피잉흘 하다가 어떤 공개된 열린 정보를 웹사에트에서 보고 가져와 데이터베이스에 넣고 구조화해서 재사용하려고 하려고 할 것이다. 크롤링과 스크랩핑은 이런목적에서 시작되었지만 데이터를 가져와서 구조화하는데는 사람의 손이 들어가게 되고 비교적 단순한 일에 시간을 많이 쓰게 된다. 이런 작업을 자동화해서 바로 데이터베이스화하려고 하는 노력이 발전해서 크롤링, 웹스크래핑이 되었다.
크롤링을 할 때 주의할 점은 데이터를 가져가는 것은 괜찮지만 재활용해서 서비스에 노출하거나 상업적인 목적으로 이용하려고 할 때 데이터의 원 소유자에게 의해 법적 문제에 휘말릴 수 있다는 것이다.
크롤 제한과 robot.txt
robots.txt
파일은 웹사이트의 루트 디렉토리에 위치하는 텍스트 파일인데 크롤러(봇)에게 웹사이트 내의 페이지나 디렉토리에 접근이 허용되거나 금지되는지를 적어서 허용한 것만 가져가도록 웹사이트 쪽에서 제공하는 것이다. 이 파일은 웹 표준인 "Robots Exclusion Protocol"을 따르게 되어 있고 그에 따라 작성해야 한다.
크롤러의 목적을 정리하면
- 특정 콘텐츠를 크롤러가 가져가서 검색 엔진에서 서비스하지 다시 못하도록 막음
- 용량이 큰 콘텐츠를 가져가지 않도록 막아서 서버의 부하하 네트워크 사용량울 줄임
위와 같다. robot.txt 이 생긴 초기에는 인터넷의 네트워크 속도가 느린 시대였기 때문에 콘텐츠의 내용물을 보호하기 보다는 서버 부하를 줄이려고는 용도가 더 많았다. 요즘은 서버의 부하보다는 내용물을 가져가지 못하게 하는 내용 보호의 목적으로 더 많이 사용하는 것 같다.
예시를 보자. 아래는 robots.txt
파일의 예시이다.
User-agent: *
Disallow: /private/
Allow: /
참고로 앞서 얘기한 API 방식에는 robots.txt가 적용되지 않는다.
robots.txt의 법적 효력
모든 크롤러가 반드시 robots.txt를 지키는 것은 아니며 국내에서 법적으로 강제 사항은 아니다. 하지만 지키지 않은 경우에 업무 방해, 저작권 침해 등의 민사소송에 휘말릴 여지가 있으므로 지키는 것이 좋다. 대부분의 유명 검색 서비스인 구글, 네이버 등 주요 검색 엔진의 크롤러는 robots.txt를 지키는 것으로 알려져 있다.
크롤링을 위한 파이썬 도구
Scrapy(스크래피)
파이썬에는 scrapy라는 패키지가 있다. 크롤러를 개발하기 위한 프레임워크인데 비교적 사용하기 쉽고 유연성이 좋은 편이다. 이 책에서는 scrapy를 소개만 할 것이고 실제 사용법은 설명하지 않는다. scrapy는 초보자가 쓰기에는 학습하기 어려운 부분이 꽤 많다. 그리고 이 책은 크롤러를 개발을 위한 책이 아니다.
requests (리퀘스츠)
requests라는 패키지는 파이썬의 표준 http 패키지다. http 표준 패키지는 http 프로토콜를 이용해서 웹 페이지를 가져오거나 웹 서비스에 데이터를 등록할 수 있도록 한다.
http는 웹서버와 웹브라우저가 서로 요청과 내용물을 주고 받는 일에 대한 규칙을 정의한 프로토콜이고 웹서버와 웹브라우즈는 이 프로토콜을 이용한다. 그래서 자동화된 방법으로 웹페이지를 가져와서 csv파일을 만들거나 데이터프레임으로 바꾸려면 http프로토콜을 직접 다루거나 쉽게 다룰 수 있게 해주는 패키지를 사욤해야 하는데 python에서는 requests가 대표적이다. requests외에도 여러 패키지가 있는데 이 책에서는 다루지 않는다.
BeautifulSoup (뷰리풀숲)
BeautifulSoup은 파이썬에서 HTML, XML 문서를 파싱(구문 분석)하고 원하는 데이터를 쉽게 추출할 수 있도록 도와주는 패키지다. requests와 함께 자주 사용되는데 requests로 웹페이지의 HTML을 받아온 뒤 BeautifulSoup으로 구조를 분해해서 원하는 내용이 있는 태그, 속성, 텍스트 등을 손쉽게 찾아서 꺼내는데 필요한 기능을 제공한ㅇ다.
BeautifulSoup의 주요 특징
- HTML 문서의 구조를 트리 형태로 만들어서 원하는 요소를 쉽게 탐색할 수 있다.
- 태그 이름, 클래스, id, 속성 등 다양한 방법으로 원하는 데이터를 추출할 수 있다.
- HTML이 잘못 작성되어 있어도(문법 오류가 있어도) 유연하게 파싱할 수 있다.
아래는 BeautifulSoup을 이용해 웹페이지에서 제목을 추출하는 간단한 예시이다.
((프롬프트)): BeautifulSoup을 이용하는 간단한 예시를 설명과 함께 보여주세요. ((AI챗봇 답)):
# 아래는 requests와 BeautifulSoup을 이용하여 웹페이지의 제목(title 태그)을 추출하는 예시입니다.
import requests
from bs4 import BeautifulSoup
# 1. requests로 웹페이지의 HTML을 가져옵니다.
url = "https://www.example.com"
response = requests.get(url)
# 2. BeautifulSoup 객체로 HTML을 파싱합니다.
soup = BeautifulSoup(response.text, "html.parser")
# 3. title 태그를 찾아서 텍스트를 추출합니다.
title = soup.title.string
print("웹페이지의 제목:", title)
# 위 코드는 웹페이지의 HTML을 받아와서 BeautifulSoup으로 파싱한 뒤,
# <title> 태그의 내용을 추출하는 기본적인 예시입니다.
Selenium (셀레니엄)
Selenium은 웹 브라우저를 자동으로 제어할 수 있게 해주는 프레임워크다.
프레임워크는 소프트웨어 개발에 필요한 기본 구조와 도구들을 제공해서 개발을 더 쉽고 효율적으로 만들어주는 라이브러리다.
원래 Selenium은 웹 애플리케이션을 개발하고 난 뒤에 기능이 정상적으로 작동하는지 예상하지 못한 버그가 있는지 등을 테스트하기 위한 테스트 도구 용도로 만들어졌고 원래의 용도로 많이 사용하지만 웹브라우징을 자동화 할 수 있는 기능을 활용해서 웹페이지 크롤링이나 자동화 작업에도 많이 사용한다. 셀레니엄은 최초에 자바(Java)언어로 다룰 수 있게 만들어졌지만 후에 다른 여러가지 언어로도 다룰 수 있게 확장 모듈이 만들어졌고 Python 언어로도 selenium을 쓸 수 있다.
셀레니엄은 requests와 같은 http 프로토콜 라이브러리를 직접제어하지 않고 실제 웹브라우저(Chrome, Firefox 등)를 실행해서 사람이 직접 사용하는 것처럼 웹사이트를 탐색하고 버튼을 클릭하거나 입력 폼에 내용을 채우거나 하는 다양한 상호작용을 자동화할 수 있다.
그래서 Selenium에는 웹서비스를 테스트하는데 필요한 여러 라이브러리와 보조도구나 들어있고 활용해서 테스트 자동화 또는 콘텐츠 스크래핑에 사용할 수 있다.
Selenium의 주요 특징
- 실제 브라우저를 띄워서 웹페이지를 서핑하게 할 수 있다
- 동적으로 렌더링되는 웹페이지(자바스크립트로 생성되는 데이터 등)도 크롤링할 수 있다
- 버튼 클릭, 스크롤, 입력 등 다양한 사용자 행동을 자동화할 수 있다
- Chronme(크롬), Firefox(파이어폭스), Edge(엣지) 등 여러 브라우저를 지원한다
아래는 Selenium을 이용해 웹페이지의 제목을 추출하는 간단한 예제다.
((프롬프트)): Python으로 셀레니엄을 사용하는 예시를 보여주세요. ((AI챗봇 답))4
# 아래는 Selenium을 이용하여 웹페이지의 제목(title 태그)을 추출하는 간단한 예시입니다.
from selenium import webdriver
from selenium.webdriver.common.by import By
# 1. 크롬 드라이버를 실행합니다. (크롬 드라이버가 설치되어 있어야 합니다)
driver = webdriver.Chrome()
# 2. 원하는 웹페이지로 이동합니다.
driver.get("https://www.google.com")
# 3. title 태그의 텍스트를 가져옵니다.
title = driver.title
print("웹페이지의 제목:", title)
# 4. 작업이 끝나면 브라우저를 닫아줍니다.
driver.quit()
# 위 코드는 Selenium을 이용해 실제 브라우저를 띄우고,
# 해당 웹페이지의 제목을 추출하는 기본적인 예시입니다.
위의 예제는 Chrome 브라우저를 사용한 것인데 코드를 보면 Selenium을 불러온 후에 Chrome 웹드라이버를 초기화 한 후에 https://www.example.com 이라는 페이지를 불러온 후에 제목을 화면에 출력하고 종료하는 코드다. 위 코드는 Colab에서는 작동하지 않고 노트북이나 PC같은 로컬에서 실행해야 한다. Colab에서 안되는 이유는 Colab 서버에 있는 Python에 Selenium 패키지가 설치되어있지 않고
Selenium을 사용하는 이유
최근의 웹애플리케이션은 콘텐츠를 웹서버에서 모두 한 번에 내보내는 방식이 아닌 필요한 내용만 그때그때 요청해서 표현하는 동적 생성 방식을 많이 사용하는데 이 방식은 Javascript 언어를 사용해서 실시간으로 HTML 내용물을 바꾸고 조절한다. Javascript는 웹브라우저내에 내장된 Javascript 엔진을 사용한다. 이 웹브라우저와 비슷한 것을 만드려면 HTML 받아서 구조화해서 표현하는 렌더링 엔진과 Javascript 엔진을 비롯해서 매우 많은 기능들이 필요하다. 그런 것들을 구현하게 되면 결국 웹브라우저를 만드는 것과 같아지므로 낭비가 된다. 그래서 이미 개발된 웹브라우저를 이용하려고 하려는 시도가 있었고 프로그래밍 언어로 웹브라우저를 움직일 수 있게 만드는 도구로 웹드라이버라는 것이 개발되었다. 웹브라우저는 외부에서 직접 웹브라우저를 움직일 수 있는 도구를 제공하지 않는데 웹드라이버가 그 역할을 하도록 개발되었다.