[python library] 크롤링 with requests & BeautifulSoup

·2024년 8월 5일
1

python library

목록 보기
1/3
post-thumbnail

1. 크롤링(Crawling)과 스크래핑(Scraping)

▲ 나무위키 - 크롤링


▲ 나무위키 - 스크래핑


구분 없이 용어를 사용하는 경우가 많다고 하지만 엄밀하게 말하자면 크롤링이 스크래핑보다 더 큰 개념의 용어이다.

  • 크롤링 (Crawling) : 웹 페이지 정보를 가져오는 것
  • 스크래핑 (Scraping) : (크롤링한) 웹 페이지에서 데이터를 추출하는 것

이번 글에서는 python의 BeautifulSouprequests 라이브러리를 사용한 크롤링을 다루고, 더 나아가 스크래핑까지 다룰 예정이다.



2. requests 라이브러리로 html 소스코드 불러오기

우선 requests 에 대하여, python에서 http를 다루기 위해 사용되는 라이브러리이다.

import requests
 
response = requests.get('url')

사실 requests 라이브러리의 .get( 'url' ) 함수 하나면 해당 url의 html 소스코드를 불러올 수 있다.

print(response)
>>> <Response [200]>

print(response.status_code)
>>> 200

print(response.text)
>>> <!doctype html> <head> <meta charset="utf-8"> ... </body></html>

위와 같이 .status_code의 값이 200일 경우 해당 url에 정상적으로 접근했다는 걸 뜻하기에 앞으로 다음과 같이 사용하도록 하자.

import requests
import sys
 
response = requests.get('url')

# status_code가 200이 아니면 status_code를 출력하며 프로그램 종료
if response.status_code != 200:
    sys.exit("status code of response is " + str(response.status_code))
    



3. User - Agent를 사용하여 안전하게 접근하기

위 과정을 반복하다보면, 어느 순간 똑같은 url에 접근함에도 불구하고 status_code가 200이 나오지 않는 순간이 찾아온다. 반복된 비정상적인 접근을 서버가 탐지하고 차단한 것이라고 볼 수 있다. 따라서, 비정상적인 접근으로 간주되지 않기 위해서 User-Agent를 활용해서 정상적인 접근을 시도해보자.

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'}
response = requests.get('url', headers=headers)

이때 'User-Agent'의 값은 m.avalon.co.kr에서 확인할 수 있다.



4. BeautifulSoup를 이용한 HTML 소스코드 파싱

파싱(Parsing)
: 언어의 구문을 분석하는 것

따라서 BeautifulSoup 라이브러리를 활용해서 HTML 소스코드를 HTML 문법에 따라 분석하고 활용하자.

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# 혹은 BeautifulSoup(response.text, 'lxml')

HTML은 태그(Tag)속성(Attribute), 그리고 속성 정보 등으로 구성되어 있다. 따라서 특정 함수를 통해서 원하는 정보를 추출할 수 있다.

soup.find(<Tag>)		# HTML 문서의 위에서부터 첫 번째 <Tag>를 반환
soup.find_all(<Tag>)	# HTML 문서의 모든 <Tag>를 반환
soup.get(<Attr>)		# soup가 가리키는 첫 Tag의 속성(Attribute)들 중
  						# <Attr>에 해당하는 값을 반환
soup.text				# soup가 가리키는 첫 Tag의 text를 반환
# <Tag>와 <Attr>를 동시에 활용하여 검색하기
soup.find(<Tag>, attrs = {<Attr> : ... }
soup.find_all(<Tag>, attrs = {<Attr> : ... }

Example

soup.find("div")		# body, div, span, a, li, ul, table, ...
soup.find_all("div", attrs = {"class" : "Toastify"})
soup.find("a")
soup.get("href")
>>> "/write?id=fe2612d2-a18b-47c6-bcda-21715ee42316"
soup.find("span")
soup.text
>>> "동시대 미술이 선사하는\n극한의 깊이와 파격"



5. re 정규식 연산 라이브러리

정규표현식(정규식) : 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어
find 혹은 find_all 함수를 사용하여 원하는 태그를 찾을 때 attrs을 사용하여 속성을 함께 검색할 수 있는데, 특정 단어를 포함한 모든 속성을 찾고 싶을 때 사용할 수 있다. 예를 들어서 설명해보겠다.

soup.find_all("div", attrs = {"class" : "language"}

위 코드는 Tagdiv이며 속성 중 "class"의 값이 "language"인 태그가 반환된다.

하지만 만약 "language_markdown""language_null"처럼 "language"라는 단어를 포함한 "class" 속성 값을 가진 div Tag를 반환받고 싶다면 다음과 같이 re 라이브러리의 re.compile() 함수를 활용할 수 있다.

soup.find_all("div", attrs = {"class" : re.compile("language")})



결과물

import requests
from bs4 import BeautifulSoup
import sys
import re

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36'}
response = requests.get('url', headers=headers)

if response.status_code != 200:
    sys.exit("status code of response is " + str(response.status_code))

soup = BeautifulSoup(response.text, 'html.parser')
td_list = soup.find_all("td", attrs = {"class" : re.compile("cell")})

text_list = []
for td in td_list:
	text_list.append(td.text)
# text_list = list(map(lambda x: x.text, td_list))
profile
납작복숭아 먹고 싶어요

0개의 댓글