파이썬-크롤링-스크래핑-문서-가져오기
우리가 원하는 정보만 가져오도록 돕는 웹 스크래핑

업무를 하시다가 우리가 원하는 정보를 깔끔하게 정리해서 결과만 가져오는 도구가 있으면 좋겠다는 생각 해보신 적 있으신가요? 한동안 유행했던 '알아서 잘 딱 깔끔하게 센스있게' 라는 말처럼, 단순하고 반복되는 작업을 프로그램이 대신 처리해주면 얼마나 효율적일까요? 우리는 프로그램의 도움을 받아 더 본질적이고 중요한 일에 우리의 소중한 시간을 쓸 수 있을 것입니다.

생산성
생산성 Kris - Unsplash

이를 가능하게 해주는 도구가 있습니다. 바로 우리가 배울 파이썬입니다. 우리는 파이썬을 통해 원하는 정보만을 우리가 원하는 방식대로 가공해서 가져올 수 있습니다. 이를 웹 스크래핑(web scraping)이라고 합니다.

웹 스크래핑? 웹 크롤링(web crawling) 아닌가요? 두 단어는 웹에서 정보를 가져오는 일을 할 때 자주 혼용되어 쓰입니다. 하지만 두 단어는 다릅니다. 웹 크롤링과 웹 스크래핑은 무엇이며 둘은 어떤 차이점이 있을까요?

이번 시간에는 웹 스크래핑과 웹 크롤링의 차이는 무엇인지 그리고 웹 스크래핑 실습을 위해 필요한 환경 설정과 준비 도구를 살펴보겠습니다. 웹 스크래핑을 위한 준비를 마치면 실제 예제 코드를 통해 우리가 웹에서 가져온 정보를 엑셀로 저장해보겠습니다. 그럼 시작해볼까요?

용어

웹 크롤링과 웹 스크래핑은 어떤 차이가 있을까요? 먼저 웹 크롤링을 살펴보겠습니다.

웹 크롤링

웹 크롤링은 'URL을 탐색해 반복적으로 링크를 찾고 가져오는 과정'입니다. '기어 다니다' 라는 뜻의 영어 단어 크롤링(crawling)을 사용한 것에서 알 수 있듯이, 웹 크롤링은 웹 페이지를 찾아다니며 정보를 수집합니다.

대표적인 웹 크롤링으로는 검색엔진의 웹 크롤러(web crawler)가 하는 일을 예로 들 수 있습니다. 웹 크롤러는 URL을 수집하고 웹 페이지를 복사하여, 수집한 웹 페이지에 색인(index)을 부여합니다. 사용자에게 더 신속하게 정보를 제공하기 위해서죠. 분류가 잘 되어있으면 그만큼 검색 속도가 올라갈 테니까요. 그럼 웹 스크래핑은 무엇일까요?

웹 스크래핑

웹 스크래핑은 '우리가 정한 특정 웹 페이지에서 데이터를 추출하는 것'입니다. 우리가 특정 주제의 뉴스만을 가져오거나, 인기 검색어 정보를 가져오는 것, 어떤 상품의 가격을 모니터링하는 것 모두 웹 스크래핑입니다. 우리가 원하는 특정 웹 사이트가 있고 그곳에서 우리가 필요한 정보만을 가져오는 것이니까요. 그래서 웹 스크래핑을 웹 데이터 추출(web data extraction), 웹 하베스팅(web harvesting)이라고도 부릅니다.

웹 크롤링과 웹 스크래핑 차이

웹 크롤링과 웹 스크래핑은 모두 정보를 추출해온다는 데서는 공통점을 지닙니다. 하지만 '타켓 웹 페이지의 유무'와 '중복 제거(deduplication)의 실행 여부'에서 차이가 납니다.

웹 크롤링은 특정 웹 페이지를 목표로 하지 않습니다. 일단 탐색부터 하고, 정보를 가져오죠. '선탐색 후추출'입니다. 반면 웹 스크래핑을 할 때는 목표로 하는 특정 웹페이지가 있습니다. 우리가 원하는 정보를 어디서 가져올지 타겟이 분명하고, 그 타겟에서 정보를 가져오죠. 그래서 '선결정 후추출'입니다.

또, 웹 크롤링에서는 중복 제거가 필수적입니다. 중복되거나 불필요한 정보를 가져와서 분류를 더 어렵게 할 필요는 없으니까요. 도서관의 책이 개별적으로 구분되는 색인이 있는 것처럼 웹 크롤링도 수집한 웹 페이지가 중복되지 않도록 서로 다른 색인을 남깁니다. 그래서 웹 크롤링을 웹 인덱싱(web indexing)이라고도 부릅니다.

반면 웹 스크래핑에서는 중복 제거가 필수는 아닙니다. 중복된 정보를 가지고 있을 필요는 없지만, 그렇다고 꼭 필수적으로 하는 일도 아니죠.

이번 글에서 우리가 다룰 주제는 웹 스크래핑입니다. 웹 스크래핑을 하기 위해서는 몇 가지 환경 설정을 해야 합니다.

환경 설정

파이썬으로 웹 스크랩핑을 하기 위해서는 기본적으로 텍스트 에디터, 브라우저, 개발자 도구가 필요합니다. 이 도구들이 준비되면 파이썬 패키지 매니저인 pip으로 웹 스크래핑 라이브러리를 설치하면 됩니다.

텍스트 에디터

저는 VS Code를 사용했습니다. 텍스트 에디터를 선택하는 것이 고민되신다면 통합 개발 환경(IDE), 텍스트 에디터 인기 순위 (2022년)에서 전 세계 개발자들이 사용하는 툴을 살펴보시고 개발 환경을 설정하셔도 됩니다.

브라우저

여기서는 구글 크롬을 사용했습니다.

개발자 도구

구글 크롬을 기준으로 개발자 도구를 여는 방법에는 크게 3가지가 있습니다.

  1. 직접 열기
  • 오른쪽 상단 모서리에 .이 수직 방향으로 3개 찍힌 부분을 클릭하시고 도구 더보기를 누른 다음 개발자 도구에 들어가시면 됩니다.
네이버 웹툰에서 우리가 가져오고 싶은 부분
네이버 웹툰에서 우리가 가져오고 싶은 부분  - Snug Archive
  1. 마우스 오른쪽 클릭 > 검사
  • 마우스 오른쪽 버튼을 클릭한 뒤 목록의 맨 하단에 나타난 검사를 누르면 개발자 도구를 열 수 있습니다.
네이버 웹툰에서 우리가 가져오고 싶은 부분
네이버 웹툰에서 우리가 가져오고 싶은 부분  - Snug Archive
  1. 단축키

저는 단축키를 사용합니다. 개발자 도구 단축키는 다음과 같습니다.

  • 윈도우: Ctrl + Shift + I
  • 맥: Alt(Option) + Command + I

다음은 패키지 설치입니다.

패키지 설치

웹 스크래핑을 하기 위해서는 requests, beautifulsoup4, lxml 패키지가 필요합니다. requests 라이브러리는 HTTP 프로토콜을 통해 웹 서버에 요청하고 응답 받는 과정을 처리하는 라이브러리고, beautifulsoup4는 웹 페이지에서 데이터를 추출해오는 라이브러리, 그리고 lxml은 가져온 html 문서를 파싱하는 라이브러리입니다.

참고로 파서로는 내장(built-in) html.parser를 사용할 수도 있습니다. 여기서는 html.parser 보다 속도가 빠른 lxml을 사용했습니다. 파서에 대해 더 자세히 알고 싶은 분들은 공식 홈페이지의 BeautifulSoup 파서 차이를 참조하시면 됩니다.

라이브러리를 설치하지 않고 라이브러리를 import 하면 오류가 발생할 것입니다. 아래는 requests 모듈이 설치되어 있지 않다(No module named 'requests')는 트레이스백(traceback)입니다. 트레이스백은 인터프리터가 코드를 실행하려다 문제가 생겼을 때 보여주는 기록입니다.

bash
Traceback (most recent call last):
File "d:\Python\practice.py", line 2, in <module>
import requests
ModuleNotFoundError: No module named 'requests'

패키지를 설치하려면 파워셸(PowerShell)이나 윈도우의 셸인 cmd에 다음과 같이 입력하시면 됩니다.

bash
pip install beautifulsoup4 lxml requests

위 코드는 세 라이브러리를 한 번에 설치하는 방식입니다. pip install을 세 번 사용해서 라이브러리를 하나씩 설치하셔도 됩니다.

텍스트 에디터, 브라우저, 개발자 도구, 그리고 패키지 설치가 모두 완료되셨으면 웹 스크래핑을 진행할 준비가 되신 겁니다. 마지막으로 웹 스크래핑을 하기 전에 한 가지 염두에 두셔야 할 점이 있습니다. 바로 Robots.txt와 사용자 에이전트(user agent)입니다.

Robots.txt와 사용자 에이전트(user agent)

Robots.txt는 웹 사이트 및 웹 페이지를 수집하는 로봇들의 무단 접근을 방지하기 위해 만들어진 로봇 배제 표준(robots exclusion standard)이자 국제 권고안입니다. 일부 스팸 봇이나 악성 목적을 지닌 가짜 클라이언트 로봇은 웹 사이트에 진짜 클라이언트처럼 접근합니다. 그리고 무단으로 웹 사이트 정보를 긁어가거나, 웹 서버에 부하를 줍니다. 이런 로봇들의 무분별한 접근을 통제하기 위해 마련된 것이 Robots.txt입니다.

그래서 가끔 웹 서버에 요청을 보내도 요청을 거부 당하는 일이 있습니다. 우리를 무단 봇으로 짐작하고 웹 서버에서 접근을 막는 것이죠. 그럼 우리는 브라우저에게 스팸 봇이 아니라 사람이라는 것을 알려주면 되겠죠? 이때 브라우저에게 전달하는 것이 사용자 에이전트(user agent) 정보입니다.

사용자 에이전트는 사용자를 대표하는 컴퓨터 프로그램입니다. 웹 맥락에서는 브라우저, 웹 페이지를 수집하는 봇, 다운로드 관리자, 웹에 접근하는 다른 앱 모두 사용자 에이전트지요. 웹 서버에 요청할 때 사용자 에이전트 HTTP 헤더(user agent HTTP header)에 나의 브라우저 정보를 전달하면 웹 서버가 나를 진짜 사용자로 인식할 수 있게 됩니다. 사용자 에이전트 헤더를 설정하는 방법은 아래 기본 코드 프레임에서 살펴보겠습니다.

요약하자면 웹 스크래핑을 할 때 원칙은 다음과 같습니다.

  • 서버에 과도한 부하를 주지 않는다.
  • 가져온 정보를 사용할 때(특히 상업적으로) 저작권과 데이터베이스권에 위배되지 않는지 주의한다.

이 원칙들을 잘 지킨다면 분별있는 사용자 에이전트가 될 수 있을 것입니다. 그럼 지금부터는 웹 스크래핑을 본격적으로 해보겠습니다. 기본 코드 프레임은 아래와 같습니다.

Robots.txt는 웹 페이지의 메인 주소에 '/robots.txt'를 입력하면 확인 할 수 있습니다. 예를 들어 naver의 경우에는 'www.naver.com/robots.txt'를 입력하면 됩니다. 여기서 'User-agent'는 규칙이 적용되는 대상 사용자 에이전트가 누구인지를 말합니다. 'Disallow'와 'Allow'는 각각 크롤링을 금지할 웹 페이지와 허용할 웹 페이지를 뜻합니다. 자세한 규약은 robots.txt 공식 홈페이지(www.robotstxt.org)를 참조해주세요.

기본 코드 프레임

기본 코드 프레임에는 크게 두 가지가 있습니다. 하나는 데이터를 추출하는 코드고 다른 하나는 데이터를 엑셀에 저장하는 코드입니다.

먼저 데이터를 추출하는 코드를 살펴보겠습니다. 아래 코드는 'requests'와 'bs4' 라이브러리 모듈을 사용해 html 문서를 가져온 뒤 이를 lxml로 파싱하여 soup 객체로 만드는 과정을 나타낸 코드입니다.

python
1 import requests
2 from bs4 import BeautifulSoup
3
4 url = "www.snugarchive.com"
5 res = requests.get(url)
6 res.raise_for_status() # 정상 200
7 soup = BeautifulSoup(res.text, "lxml")

각 줄에서 진행하는 작업은 다음과 같습니다.

  1. 파이썬 표준 라이브러리인 requests 모듈을 임포트(import)한다
  2. 표준 라이브러리 bs4 모듈에서 BeautifulSoup 클래스만 임포트한다.
  3. import 문과의 구분을 위한 빈 줄
  4. 실제 타겟 URL을 문자열 객체로 만들어 변수 url에 할당한다.
  5. 웹 서버에 GET 요청을 보내고 웹 서버가 응답한 내용을 변수 res에 할당한다(requests 모듈의 get() 함수에 url 인자를 넣고 그 결괏값을 res에 할당한다)
  6. 에러가 발생하면 에러를 반환한다.
  7. 웹 서버로부터 응답 받은 객체 중에서 text 속성(HTML 소스 코드)을 선택하고, 우리가 받은 HTML 소스 코드를 lxml 파서를 통해 BeautifulSoup 객체로 만든다(응답받은 데이터를 soup 변수에 할당한다)

6번에서 만약 403 에러가 뜬다면 앞서 말씀드린 것처럼 웹 서버측에서 우리의 접근을 거부한 것입니다. user agent 헤더를 설정하려면 다음과 같은 방법을 따르면 됩니다.

  1. WhatIsMyBrowser에 들어가서 나의 사용자 에이전트 정보를 확인합니다.
  2. 웹 스크래핑 시 headers 정보를 딕셔너리 형태로 만들어 변수에 할당합니다.
  3. 웹 서버에 요청시 이 header 정보를 함께 보냅니다.

코드로는 아래와 같습니다.

python
headers = {"User-Agent": "[WhatIsMyBrowser에 나타난 나의 유저 정보]"}
res = requests.get(url, headers=headers)

참고로 soup 객체가 전체적으로 어떻게 생겼는지 파악하고 싶다면 다음 코드를 사용할 수 있습니다.

python
print(type(soup)) # BeautifulSoup 객체의 자료형 출력
print(soup.head) # HTML 문서의 'head' 태그에 해당하는 내용 출력
print(soup.body) # HTML 문서의 'body' 태그에 해당하는 내용 출력
print(soup.title) # HTML 문서의 'title' 태그 내용 출력
print(soup.title.name) # HTML 문서의 'title' 태그명 출력
print(soup.title.string) # HTML 문서의 'title' 태그를 제외하고 태그 안에 표시되는 텍스트만 출력

다음은 데이터를 엑셀로 저장하는 기본 코드를 알아보겠습니다.

python
1 import csv
2
3 filename = "고양이 장난감.csv"
4 f = open(filename, "w", encoding="utf-8-sig", newline="")
5 writer = csv.writer(f)
6
7 columns_title = ["컬럼명1", "컬럼명2"]
8 writer.writerow(columns_title)
9
10 data = ["결과1", "결과2"] # [] 리스트 자료구조
11 writer.writerow(data)

위 코드를 한 줄씩 해석해보면 다음과 같습니다.

  1. 파이썬 표준 라이브러리 csv 모듈을 임포트한다
  2. 윗 줄과 코드를 분리하기 위한 빈 줄
  3. 파일명이 "고양이 장난감"이고 파일 확장자가 "csv"인 문자열 객체를 만들어 filename 이라는 변수에 할당한다.
  4. 파일을 여는 open 함수에 첫 번째 인자로 filename을, 두 번째 인자로 쓰기 모드인 "w"를, 세 번째 인자에 encoding은 "utf-8-sig" 방식으로, 마지막 인자에 csv에서 한 칸 띄어쓰기 옵션인 newline에 띄어쓰기 없음(enter 없음)을 뜻하는 "" 인자를 넣어 그 결괏값을 f에 할당한다.
  5. 파일을 쓴다(csv 모듈에서 writer 함수에 우리가 연 파일의 정보가 담긴 f 변수를 인자로 주고 그 결괏값을 writer에 할당한다).
  6. 윗 줄과 코드를 분리하기 위한 빈 줄
  7. 열의 이름을 리스트 형식으로 만들어 columns_title 변수에 할당한다.
  8. csv 파일에서 사용할 컬럼명으로 columns_title을 쓴다.
  9. 윗 줄과 코드를 분리하기 위한 빈 줄
  10. 우리가 csv 파일에 쓰고 싶은 데이터인 ["결과1", "결과2"]를 data 변수에 할당한다.
  11. 우리의 데이터를 csv 파일에 쓴다.

위 코드에서는 data를 한 줄만 csv 파일에 사용했는데 보통 반복문 형식을 만들어 row 형식으로 만든 데이터를 차례로 기록합니다. 실제 사용 예제는 아래 실습 코드를 참조하시면 됩니다.

표준 라이브러리(standard library)
파이썬을 설치할 때 포함된 프로그램
임포트(import)
프로그램에서 사용할 수 있도록 설정한다는 의미
utf-8-sig
유니코드를 위한 가변 길이 문자 인코딩 방식 중 하나인 UTF-8에 signature가 붙어서 문자열을 Byte Order Mark(BOM)으로 처리하는 인코딩 방식. utf-8-sig를 사용하면 한글이 깨지는 현상을 방지할 수 있음

지금까지 우리는 웹 스크래핑을 위한 기본 코드 프레임을 알아보았습니다. 그럼 지금부터는 본격적으로 웹 스크래핑을 실습해보겠습니다.

기초 예제

첫 번째 주제는 네이버 웹툰에서 실시간 인기 웹툰 순위를 가져오는 것입니다.

네이버 실시간 인기 웹툰 1위부터 10위까지 가져오기

네이버 웹툰에서 현 시각 가장 인기 있는 웹툰의 순위를 1위부터 10위까지 추출해보겠습니다. 우리가 가져오고 싶은 부분은 아래 '인기 급상승 웹툰'의 '제목' 텍스트입니다.

네이버 웹툰에서 우리가 가져오고 싶은 부분
네이버 웹툰에서 우리가 가져오고 싶은 부분  - Snug Archive

그리고 우리가 원하는 결과는 다음과 같습니다.

네이버 웹툰에서 가져온 데이터 결괏값
네이버 웹툰에서 가져온 데이터 결괏값  - Snug Archive

그럼 먼저 개발자 도구를 열어 해당 영역의 소스코드를 살펴보겠습니다. 아래 사진에서 빨간색 선으로 영역이 구분되어 있습니다. 오른쪽 영역을 보시면 개발자 도구가 열려있죠. 1번 영역은 우리가 가져오고 싶은 타겟 대상이고 2번 영역은 개발자 도구에 나타난 1번 영역의 소스 코드입니다.

문서와 데이터를 구조화하는 마크업 언어
문서와 데이터를 구조화하는 마크업 언어  - Snug Archive

개발자 도구에 있는 소스 코드에서 인기 급상승 웹툰은 'ol' 요소 중에서 class 명이 'assideBoxRank'인 부분에 담긴 것을 확인할 수 있습니다. 그중에서도 우리가 원하는 것은 웹툰의 제목입니다. 웹툰의 제목은 'ol' 영역 안의 'a'요소에서 속성이 'title'인 부분에 담겨있습니다.

문서와 데이터를 구조화하는 마크업 언어
문서와 데이터를 구조화하는 마크업 언어  - Snug Archive

우리는 이 'a'요소 10개를 가져와 반복문으로 제목을 하나씩 출력하면 되겠죠. 우리는 웹툰 제목을 터미널 cmd 창에서 출력하고 엑셀 파일로 저장해보겠습니다.

여기서 자주 사용하는 함수는 BeautifulSoup 클래스의 find() 메소드와 find_all() 메소드입니다. find() 함수는 HTML 문서에서 가장 처음으로 나오는 태그(우리가 선택한 태그) 1개를 반환합니다. find_all() 메소드는 HTML 문서에서 우리가 지정한 모든 태그를 찾아줍니다. 이들 함수 외에도 CSS Selector를 사용할 수도 있습니다. CSS Selector에 대한 자세한 설명은 공식 홈페이지의 CSS Selector 사용하기 부분을 참조하시면 됩니다.

그럼 전체 코드를 확인해볼까요?

python
# 라이브러리 준비하기
import csv
import requests
from bs4 import BeautifulSoup
url ="https://comic.naver.com/webtoon/weekday"
# 엑셀 파일로 저장하기
filename = "네이버 웹툰 인기 순위.csv"
f = open(filename, "w", encoding="utf-8-sig", newline="")
writer = csv.writer(f)
columns_name = ["순위", "웹툰명"] # 컬럼 속성명 만들기
writer.writerow(columns_name)
# 웹 서버에 요청하기
res = requests.get(url)
res.raise_for_status()
# soup 객체 만들기
soup = BeautifulSoup(res.text, "lxml")
cartoonsBox = soup.find('ol', attrs={"class": "asideBoxRank"}) # 전체 영역에서 'a' 태그를 찾지 않고 인기 급상승 영역으로 범위 제한
cartoons = cartoonsBox.find_all('a') # 인기 급상승 영역에서 'a'태그 모두 찾아 변수 cartoons에 할당
i = 1
# 반복문으로 제목 가져오기(터미널 창 출력 및 엑셀 저장)
for cartoon in cartoons:
title = cartoon.get("title")
print(f"{str(i)}위: {title}")
data = [str(i), title]
writer.writerow(data)
i += 1

위 코드를 실행하면 다음과 같은 csv 파일이 만들어집니다.

네이버 웹툰 인기 순위를 엑셀 파일로 저장
네이버 웹툰 인기 순위를 엑셀 파일로 저장  - Snug Archive

지금까지 우리는 원하는 정보를 웹 페이지에서 가져오는 실습을 해보았습니다. 그럼 같은 주제의 내용이 여러 페이지에 담겨있다면 어떻게 할까요? 여러 개의 웹 페이지를 이동하면서 위에서 배운 코드를 페이지의 숫자만큼 실행해야 할까요?

제목을 가져올 때 사용했던 반복문처럼 다시 반복문을 통해 이 문제를 해결할 수 있습니다. 이번에는 여러 페이지에서 정보를 한 번에 가져오는 실습을 해보겠습니다.

영화 사이트에서 드라마 정보 가져오기

우리는 영화 평점 사이트에서 셜록(Sherlock) 드라마 시리즈 정보를 가져오고 싶습니다. 드라마에는 총 4개의 시즌이 있고 각 시즌에는 3개에서 4개의 에피소드가 있습니다. 우리는 아래 화면에서 빨간색으로 표시된 부분에서처럼 시즌 차수, 에피소드명, 평점, 평점 수를 가져오려고 합니다. 그리고 이 작업을 총 4개 웹 페이지에서 해야 하죠.

IMDB 셜록(Sherlock) 시리즈 정보
IMDB 셜록(Sherlock) 시리즈 정보  - Snug Archive

그럼 url이 어떤 구성으로 이루어져 있는지를 파악해야 합니다. 이 웹페이지의 URL 주소를 보시면 아래와 같이 ?다음에 시즌을 표기하고 있습니다. 아래 season=1이라고 되어있는 것을 확인할 수 있죠?

IMDB 셜록 시즌 1 URL 주소
IMDB 셜록 시즌 1 URL 주소  - Snug Archive

우리는 이 url 주소가 season에 따라 총 4개 있다는 것을 짐작할 수 있습니다. 나머지 season의 url 주소는 season=1에서 숫자 부분만 바꾼 것일 것입니다. 그럼 우리는 시즌1에서 만든 웹 스크래핑 코드를 url 주소의 마지막 숫자 부분만 바꾸어서 반복문으로 가져오면 되겠네요. 이를 코드로 표현하면 다음과 같습니다.

python
# 시즌 1부터 4까지 url 주소를 반복문으로 가져오기
for i in range(1, 5):
url ="https://www.imdb.com/title/tt1475582/episodes?season={}".format(i)

여기서는 season(주황색 글씨로 표시된 url의 마지막 부분) 옆에 있는 대입 연산자 = 다음에, 시즌 차수가 들어갈 자리를 대괄호 {} 처리하고 반복문과 format함수를 통해 숫자만 바뀌도록 만들었습니다.

그럼 먼저 결과부터 확인해보겠습니다. 코드를 통해 만들어진 엑셀 파일을 열었을 때 아래와 같은 결과를 확인하면 성공하신 겁니다.

IMDB 셜록 시즌 1 URL 주소
IMDB 셜록 시즌 1 URL 주소  - Snug Archive

답을 확인하시기 전에 먼저 스스로 해보신다면 더 빠르게 스크래핑 코드를 익히실 수 있을 것입니다. 전체 코드는 다음과 같습니다.

python
import csv
import requests
from bs4 import BeautifulSoup
filename = "셜록 시즌 정보.csv"
f = open(filename, "w", encoding="utf-8-sig", newline="")
writer = csv.writer(f)
attributes = ["시즌", "제목", "리뷰수", "평점"]
writer.writerow(attributes)
# 시즌 1부터 시즌 4까지 url 중 숫자 부분만 바꿔서 반복문으로 가져오기
for season in range(1, 5):
url ="https://www.imdb.com/title/tt1475582/episodes?season={}".format(season)
res = requests.get(url)
res.raise_for_status()
soup = BeautifulSoup(res.text, "lxml")
season = soup.find("h3", {"id": "episode_top"}).get_text()[-1]
episodes = soup.find_all("div", attrs={"itemprop": "episodes"})
for episode in episodes:
title = episode.find("a", attrs={"itemprop": "name"}).get_text()
review = episode.find("span", attrs={"class": "ipl-rating-star__total-votes"}).get_text()[1:-1]
rate = episode.find("span", attrs={"class": "ipl-rating-star__rating"}).get_text()
data_rows = [season, title, review, rate]
# print(season)
# print(f"제목: {title}")
# print(f"리뷰수: {review}")
# print(f"평점: {rate}")
# print("-"*30)
writer.writerow(data_rows)

여기에 데이터 시각화 라이브러리인 Seaborn(씨본)을 이용해 시즌별 회차의 평점 분포와 평균을 시각화해보겠습니다. 각 시즌의 회차는 pandas의 cumcount 함수를 이용해 추가했습니다. Seaborn의 사용법은 다음 시리즈를 참조해주세요.

Seaborn을 이용해 만든 그래프는 다음과 같습니다.

Seaborn으로 시각화한 셜록(Sherlock) 시즌별 평점 그래프
Seaborn으로 시각화한 셜록(Sherlock) 시즌별 평점 그래프  - Snug Archive

그래프를 보면 셜록 시리즈의 전체 시즌 중 시즌2의 평균 평점이 가장 높은 것을 알 수 있습니다. 전체 에피소드 중에서는 시즌2의 3화(The Reichenbach Fall)가 가장 재미있는 회차로 평가되었네요.

지금까지 웹 크롤링과 웹 스크래핑의 정의 및 각 용어의 차이를 알아보고, 파이썬으로 웹 스크래핑을 하기 위한 기본 환경 설정과 웹 스크래핑 실습을 해보았습니다. 파이썬 외에도 자바스크립트(JavaScript) 언어로 웹 크롤링 및 웹 스크래핑을 할 수 있습니다. 자바스크립트를 이용하면 웹의 프론트엔드, 백엔드, 크롤러를 모두 동일한 언어로 구축할 수 있어 효율적입니다. 자바스크립트로 한 웹 크롤링 및 시각화 결과물은 다음 프로젝트를 참조해주세요.

자바스크립트로 웹 크롤링 및 시각화한 지진 모니터링 현황판
자바스크립트로 웹 크롤링 및 시각화한 지진 모니터링 현황판  - Snug Archive

파이썬으로 하는 웹 스크래핑에 대해 더 공부하고 싶은 분들은 나도코딩님의 웹 스크래핑 강의를 추천드립니다. 다음에는 또 다른 주제를 가지고 웹 스크래핑을 실습해보겠습니다. 감사합니다.

참고 문헌

...

©2023 Snug Archive. All rights reserved.

Contact me at snugarchive@gmail.com.