본문 바로가기
Python

Python으로 크롤링(Crawling)하기

by yu901 2021. 6. 7.

이번 포스팅은 Python으로 크롤링하기 위해 함수 몇 가지를 다뤄볼 것이다.

그전에 이전 포스팅에서 작성한 HTTP 요청(GET, POST)과 태그 구조를 보고 오자.

2021.05.29 - [분류 전체보기] - 웹 기본 지식

 

웹 기본 지식

웹사이트와 관련된 기본 용어를 알아보자. HTML(Hyper Text Markup Language): 웹사이트를 생성하기 위한 언어로 문서와 문서가 링크로 연결되어 있고, 태그를 사용하는 언어 HTTP(Hyper Text Transfer Protocol):..

memoleeyu.tistory.com

 

HTML 문서에서 원하는 내용을 크롤링하기 위해서는 아래와 같이 세 단계의 과정이 필요하다.

  1. HTTP 요청
  2. 태그 검색
  3. 내용 추출 

HTTP 요청을 해서 크롤링할 페이지의 HTML 코드를 응답받고, 원하는 내용이 들어있는 태그를 검색하여 추출하면 된다. 태그를 검색하기 위해서는 크롤링할 대상이 어떤 태그, 속성, 속성 값을 가지는 지 알기 위해서는 직접 해당 페이지의 elements를 확인해야 한다.

[그림 1] 태그 구조

이제 각 과정에서 사용되는 함수를 배워보자!

 

 

 


 

1. requests 모듈을 이용한 HTTP 요청


import requests

# GET 요청
url = 'https://ko.wikipedia.org/wiki/웹_크롤러'
resp = requests.get(url)

# POST 요청
url = 'https://webhacking.kr/login.php?login'
data = {
    'id': 'test_id',
    'pw': 'test_pw'
}
resp = requests.post(url, data=data)

print("상태코드: ", resp.status_code)
print("HTML코드: ", resp.text)
​
상태코드: 200
HTML코드: <!DOCTYPE html>
<html class="client-nojs" lang="ko" dir="ltr">
<head>
<meta charset="UTF-8"/>
<title>웹 크롤러 - 위키백과, 우리 모두의 백과사전</title>
...


GET 요청은 url을 함수에 입력하고, POST 요청은 url과 Form Data 값을 함수에 입력한다. 클라이언트가 서버에 요청(request)을 보내면 서버가 클라이언트에게 요청에 대한 응답(response)을 보낸다. 응답받은 것에 대하여 HTTP 상태 코드를 확인하기 위해 resp.status, HTML 코드를 출력하기 위해 resp.text 함수를 사용하였다. 

 

 

HTTP 상태 코드는 특정 HTTP 요청이 성공적으로 완료되었는지 알려주는 코드이다. 

  • 1xx (정보): 요청을 받았으며 프로세스를 계속한다.
  • 2xx (성공): 요청을 성공적으로 받았으며 인식했고 수용하였다.
  • 3xx (리다이렉션): 요청 완료를 위해 추가 작업 조치가 필요하다.
  • 4xx (클라이언트 오류): 요청의 문법이 잘못되었거나 요청을 처리할 수 없다.
  • 5xx (서버 오류): 서버가 명백히 유효한 요청에 대해 충족을 실패했다.

HTTP 상태 코드가 200이 아닌 경우, Request Headers의 정보를 dict로 구성하여 요청할 때 같이 전달하면 응답에 성공할 수 있다.

[그림 2] Requests Headers

# Request Headers 포함 GET 요청
url = 'https://ko.wikipedia.org/wiki/웹_크롤러'

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
    'cache-control': 'max-age=0',
    'cookie': 'WMF-Last-Access=06-Jun-2021; WMF-Last-Access-Global=06-Jun-2021; GeoIP=KR:41:Anyang-si:37.39:126.92:v4; kowikimwuser-sessionId=cb418ad2ca834af1e060; kowikiwmE-sessionTickLastTickTime=1622984189793; kowikiwmE-sessionTickTickCount=4; kowikiel-sessionId=de1c565fa813ddc88216',
    'referer': 'https://www.google.com/',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}

resp = requests.get(url, headers = headers)

 

 

 

2. Session 객체를 이용하여 세션 유지


로그인을 한 이후 접근할 수 있는 페이지를 크롤링할 경우, GET 요청 만으로는 원하는 페이지를 크롤링할 수 없다. 이때, 세션을 사용하면 되는데 방법은 아래와 같다. 

1) Session 객체를 생성하여 POST 요청으로 로그인
2) 해당 Session 객체로 원하는 페이지를 크롤링

import requests

s = requests.Session()

url = 'https://webhacking.kr/login.php?login'
data = {
    'id': 'test_id',
    'pw': 'test_pw'
}

resp = s.post(url, data=data)

info_url = 'https://webhacking.kr/info.php'
resp = s.get(info_url)​

 

위 코드는 계정 정보를 보는 페이지를 크롤링하기 위해 세션을 생성하여 로그인(POST 요청)과 Info 페이지 요청(GET 요청)을 순서대로 진행한 내용이다.

 

 

 

3. BeautifulSoup 모듈을 이용한 태그 검색(find, find_all)


import requests
from bs4 import BeautifulSoup

url = 'https://ko.wikipedia.org/wiki/웹_크롤러'
resp = requests.get(url)

soup = BeautifulSoup(resp.text)

# 예시 1. 첫 번째 <p> 태그 검색
soup.find('p')

# 예시 2. class 속성이 'mw-parser-output'인 첫 번째 <div> 태그 검색
soup.find('div', class_='mw-parser-output')

# 예시 3. class 속성이 'navbox', aria-labelledby 속성이 '웹_크롤러'인 첫 번째 <div> 태그 검색
attrs = {'class': 'navbox', 'aria-labelledby': '웹_크롤러'}
soup.find('div', attrs=attrs)

# 예시 4. 모든 <p> 태그를 리스트로 반환
soup.find_all('p')

# 예시 5. find 로 검색한 <div> 태그에서 <p> 태그 검색
info = soup.find('div', class_='mw-parser-output')
info.find_all('p')
​


html문자열을 파라미터로 가지는 soup객체를 생성하고 find, find_all 함수를 사용하여 tag를 검색한다. find 함수는 조건을 만족하는 하나의 tag를 검색하고, find_all 함수는 조건에 맞는 tag들을 list형태로 반환한다. 그리고 '예시 5'와 같이 검색한 태그에서 다시 검색할 수 있다.

 

 

태그명, 속성, 속성 값 등 값이 문자열인 부분에 정규표현식을 사용할 수 있다. 

import requests
from bs4 import BeautifulSoup
import re

url = 'https://ko.wikipedia.org/wiki/웹_크롤러'
resp = requests.get(url)
soup = BeautifulSoup(resp.text)
    
soup.find_all('img', attrs={'src': re.compile('.+\.png')})​

 

re.complie('.+\.png')는 {한 개 이상의 문자}+'.png'에 해당하는 정규표현식이다. 즉, png 형식의 이미지 태그를 검색하는 코드이다.

 

 

 

4. BeautifulSoup 모듈을 이용한 태그 검색(select, select_one)


import requests
from bs4 import BeautifulSoup

url = 'https://ko.wikipedia.org/wiki/웹_크롤러'
resp = requests.get(url)

soup = BeautifulSoup(resp.text)

# 예시 1. 첫 번째 <p> 태그 검색
soup.select_one('p')

# 예시 2. class 속성이 'mw-parser-output'인 첫 번째 <div> 태그 검색
soup.select_one('div.mw-parser-output')

# 예시 3. aria-laballedby 속성이 'navbox'인 첫 번째 <div> 태그 검색
soup.select_one('div[aria-laballedby="navbox"]')

# 예시 4. 모든 <p> 태그를 리스트로 반환
soup.select('p')

# 예시 5. find 로 검색한 <div> 태그의 자식태그 중 <p> 태그 검색
soup.select('div.mw-parser-output > p')

 

select_one, select 함수는 CSS selector를 이용하여 태그를 검색하는 함수이다. select_one 함수는 조건을 만족하는 하나의 tag를 검색하고, select 함수는 조건에 맞는 tag들을 list형태로 반환한다. 


CSS는 HTML 문서의 스타일을 지정하는데 사용하는 언어이고, CSS selector는 스타일 속성을 선택하는 데 사용되는 패턴이다. 자주 사용되는 CSS selector는 아래 표에 있다.

선택자 예시 의미
tag div 태그명 찾기
tag tag div p 자손 태그 찾기
tag > tag div > p 자식 태그 찾기(direct) 
#id #firstname 아이디 찾기
.class .intro 클래스 찾기
[attribute='value'] [target='_blank'] 속성 값 찾기
[attribute ^= 'value'] [href^='http'] 속성 값 prefix 찾기
[attribute $= 'value'] [href$='.pdf'] 속성 값 suffix 찾기
[attribute *= 'value'] [href*='w3schools'] 속성 값 substring 찾기
:nth-child(n) p:nth-child(2) n번째 자식 태그 찾기

 

 

5. 태그의 내용, 속성값 추출


원하는 태그를 검색했으니 이제 태그에서 사용할 내용, 속성 값을 추출할 것이다.

import requests
from bs4 import BeautifulSoup

url = 'https://ko.wikipedia.org/wiki/웹_크롤러'
resp = requests.get(url)
soup = BeautifulSoup(resp.text)

# 내용 추출
tag1 = soup.find('p')
print("태그 내용: ", tag1.get_text())

# 속성값 추출
tag2 = soup.find('div', class_ = 'navbox')
print("aria-labelledby 속성값: ", tag2['aria-labelledby'])
태그 내용: 웹 크롤러(web crawler)는 조직적, 자동화된 방법으로 월드 와이드 웹을 탐색하는 컴퓨터 프로그램이다.\n
aria-labelledby 속성값: 웹_크롤러

 

검색한 태그에서 get_text 함수를 사용하여 태그의 내용을 추출할 수 있고, 태그[속성]으로 속성에 해당하는 속성 값을 추출할 수 있다.

 

 


 

Python으로 크롤링하는데 필요한 함수를 정리했다. 이 함수들을 응용하면 HTML 문서에서 원하는 내용을 (아마도) 무엇이든 크롤링할 수 있을 것이다. 

 

 

다음 포스팅에서는 셀레니움 모듈을 사용한 웹 브라우저 자동화를 다룰 것이다. 

 

 


참고자료

'Python' 카테고리의 다른 글

알쓸코드 - 데이터 분석  (1) 2023.11.04
[Python] 리스트 컴프리헨션(list comprehension)  (0) 2021.10.12
Python으로 잔여백신 상태 확인하기  (5) 2021.07.25
영화 리뷰 크롤링  (2) 2021.06.19
웹 기본 지식  (2) 2021.05.29

댓글