1. 웹스크래핑(Web Scraping)이란?
우리는 웹 페이지에서 많은 정보를 얻는다. 이 정보들을 추출, 정리할 필요성을 느낄 때가 있는데, 이를 스크래핑이라고 한다.
즉, 웹 페이지의 정보를 가져오고(크롤링;Crawling), 데이터들을 추출(스크래핑;Scraping)해 DB에 저장하고 사용하는 것을 이야기한다.
2. Python으로 웹 크롤링하기
2-1. 준비하기
기본적으로 웹 크롤링은 HTML로 작성된 문서를 긁어서 가져오는 일이기 때문에, 파이썬에서 그 정보를 가져오도록 요청해야 한다.
따라서 Requests
라이브러리로 요청하고, BeautifulSoup
라이브러리로 필요한 정보만 추출할 것이다.
requests 라이브러리 설치
나는 venv 가상환경을 사용하기 때문에 간단하게 VSCode 터미널에
pip install requests
만 입력해줬다. (반드시 가상환경이 활성화된 상태에서 진행해야 한다)
▼ venv 가상환경? 그게 뭐지?
Requests 라이브러리 사용
가져오고 싶은 페이지나 API 주소가 있다면,
import requests
r = requests.get('url')
하면 된다!
2-2. beautifulsoup4 패키지 설치하기
자 이제 Requests
라이브러리로 가져온 정보를 추출하기 위해 beautifulsoup4
패키지를 설치할 거다.
역시나 가상환경을 사용중이기 때문에 터미널에
pip install bs4 #beautifulsoup4
만 입력해주면 끝!
그리고 파이썬으로,
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('스크래핑할 주소',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
# 이 이후로 필요한 부분 추출
이러면 스크래핑 준비는 모두 끝났다.
**참고 : User Agent
request header의 종류 중 하나인데, 요청하는 쪽의 식별 정보를 담고 있다고 이해하면 된다.
User-Agent: <product> / <product-version> <comment>
기본 코드는 이렇게 되며, 위 코드는 Chrome 인 경우이다.
2-3. 스크래핑할 사이트 뜯어보기
지금부터 스크래핑 해 볼 것은 멜론 TOP 100!
F12
(또는 오른쪽마우스 - 검사)로 우리에게 필요한 정보를 찾자.
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://www.melon.com/chart/',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
print(soup)
을 입력해보면
해당 HTML이 잘 긁혀진 것을 확인할 수 있다.
2-4. 본격적으로 코딩하기
가져오려는 정보가 담긴 HTML에서 오른쪽 마우스 > 복사 > selector 복사
(보기 쉬우라고 한글로 바꿔놓긴 했는데, 영어 그대로라면 copy
> copy selector
선택하면 된다)
원하는 정보 추출은 beautiful soup
의 select
, 선택자를 사용한다.
beautiful soup 선택자 사용법
soup.select('태그명')
soup.select('.클래스명')
soup.select('#아이디명')
soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')
soup.select('태그명[속성="값"]')
soup.select_one('위와 동일')
제목이 있는 selector을 복사했으니
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://www.melon.com/chart/',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
title = soup.select_one('#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank01 > span > a ')
print(title)
하면
보이는 대로 노래 제목이 있는 부분이 잘 추출된 걸 확인할 수 있고,
출력 부분을 print(title.text)
라고 하면
제목만 가져올 수 있다!
여러 데이터 추출해서 나열하기
#lst50 > td:nth-child(2) > div > span.rank --> 1번랭킹
#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank01 > span > a --> 1번 제목
#lst50 > td:nth-child(2) > div > span.rank --> 2번 랭킹
#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank01 > span > a --> 2번 제목
추출한 데이터들을 보면,
#lst50 > td:nth-child(2) > div
까지가 공통부분이므로 이들을 묶은 list
를 만들어서 for
문으로 돌리면 된다.
top_100 = soup.select('#lst50 > td > div') #tr로 이루어진 list
for tr in top_100 :
rank = tr.select_one('span.rank')
title = tr.select('div > div.ellipsis.rank01 > span > a ')
print(rank, title)
이렇게만 해보고 실행했을 때,
보이는 것 처럼 None 값이 많은데,
이는 여러 컨텐츠(wrapper, 구분선 등등) 때문에 #lst50 > td > div
내에 rank와 title만 있진 않기 때문이다. 따라서
for tr in top_100 :
rank = tr.select_one('span.rank')
if rank is not None:
print(rank.text, end=" ")
title = tr.select_one('div > div.ellipsis.rank01 > span > a')
if title is not None:
print(title.text)
for
문 안을 이렇게 바꿔주면
잘 나온당!
이제 가수도 추가해서 완성해보자.
<완성코드>
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://www.melon.com/chart/',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
top_100 = soup.select('#lst50 > td > div') #tr로 이루어진 list
for tr in top_100 :
rank = tr.select_one('span.rank')
if rank is not None:
print(rank.text, end=". ")
title = tr.select_one('div > div.ellipsis.rank01 > span > a')
if title is not None:
artist = tr.select_one('div.ellipsis.rank02 > a').text
print(artist,'-', title.text)
#lst50 > td:nth-child(6) > div > div > div.ellipsis.rank02 > a --> 가수
<출력화면>
정말 정말 정말 정말 간단한 스크래핑 기초였는데, 사실 이정도만 알아둬도 개인의 필요성에 따라 적절히 응용하면 뭐든 가능할 듯 하다.
개인적으로 개발에서 가장 중요한 건 응용이라고 생각하기 때문에, 기초라고 절대 무시하지 말것...
이 다음엔 이렇게 추출한 데이터를 DB에 저장하는 방법을 알아도록 하자. 오늘은 여기서 끝!
GitHub 댓글