IT

★Python: Requests와 Beautiful Soup를 이용한 파싱(parsing)

유병혁 2021. 4. 13. 05:14

안녕하세요? 이번 글은 Python에서 Requests와 Beautiful Soup를 이용한 파싱(parsing) 예제를 정리해 보겠습니다. 파싱은 어떤 페이지(문서, html 등)에서 내가 원하는 데이터를 특정 패턴이나 순서로 추출해 가공하는 것을 의미합니다(참고로, 크롤링(crawling)은 여러 웹 사이트를 돌아다니며 홈페이지의 정보들을 수집하고 검색 대상의 색인으로 포함시키는 기술로 정의됩니다).

 

Requests는 Python HTTP 라이브러리입니다.

 

Requests: HTTP for Humans™ — Requests 2.25.1 documentation

Requests: HTTP for Humans™ Release v2.25.1. (Installation) Requests is an elegant and simple HTTP library for Python, built for human beings. Behold, the power of Requests: >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.

docs.python-requests.org

pip을 통한 설치 방법은 다음과 같습니다.

pip install requests

Request를 통해 네이버 뉴스에서 '국립공원'을 검색한 결과를 호출해 보겠습니다.

 

국립공원 : 네이버 뉴스검색

'국립공원'의 네이버 뉴스검색 결과입니다.

search.naver.com

다음과 같이 Requests 라이브러리를 호출한 후, 위 URL을 지정해줍니다.

print(html_doc)을 통해 해당 페이지의 HTML을 확인하실 수 있겠습니다.

import requests
r = requests.get('https://search.naver.com/search.naver?query=%EA%B5%AD%EB%A6%BD%EA%B3%B5%EC%9B%90&where=news&ie=utf8&sm=nws_hty')
html_doc = r.text
print(html_doc)

Beautiful Soup는 HTML과 XML 문서 파싱을 위한 파이썬 패키지로 pip 설치 명령어는 아래와 같습니다.

pip install beautifulsoup4
 

Beautiful Soup Documentation — Beautiful Soup 4.9.0 documentation

Non-pretty printing If you just want a string, with no fancy formatting, you can call str() on a BeautifulSoup object (unicode() in Python 2), or on a Tag within it: str(soup) # ' I linked to example.com ' str(soup.a) # ' I linked to example.com ' The str(

www.crummy.com

 

위에서 정의한 html_doc을 Beautiful Soup를 통해 열어봅니다.

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.prettify())

 

아래와 같이 find_all 함수를 사용하면, <a> 태그를 모두 검색할 수 있습니다.

soup.find_all('a')

<a> 태그의 href 속성(링크된 페이지의 URL 명시)을 출력하는 구문은 다음과 같습니다.

for link in soup.find_all('a'):
    print(link.get('href'))

 

이 페이지에서 뉴스 제목(title)만을 출력하고 싶다면 어떻게 해야 할까요?

일단, 크롬 브라우저에서 제목을 우클릭한 후 '검사'버튼을 클릭해 봅니다.

아래와 같이 <a> 태그에 class = "news_tit" 속성을 확인하실 수 있는데요,

이 정보를 기반으로 검색해 보시면 되겠습니다. 간단하죠?!

news_tit = soup.findAll("a", {"class":"news_tit"})
print(news_tit)

웹 구조의 이해를 돕기 위해 '0번째 값'만 읽어와 봅니다.

news_tit[0]

0번째 값의 href 속성은 다음과 같이 가져올 수 있습니다.

news_tit[0].get('href')

마찬가지로 0번째 값의 title 속성도 다음과 같이 가져올 수 있습니다.

*스터디용으로 작성한 글이라 의도적으로 코드를 나눠 작성했습니다.

news_tit[0].get('title')

전체 뉴스는 몇 개일까요?! len 함수를 이용해 총 길이를 구해봅니다.

len(news_tit)

자, 이제 반복문을 통해 기사 제목만을 호출해 보겠습니다. 구문은 다음과 같습니다.

for i in range(len(news_tit)):
    print(news_tit[i].get('title'))

결과는 아래와 같습니다. 파싱이나 크롤링의 핵심은 웹 구조 이해력에 있을 듯 합니다.

속리산국립공원, 늦은 벚꽃 만개
낮기온 20도…강원 국립공원·관광지마다 나들이 인파
소백산국립공원, 봄철 탐방로 주변 급경사지 낙석점검 제거 나서
소백산국립공원사무소 봄철 낙석사고 예방 총력
"변산반도국립공원-선운산 거리 7.5km 단축 100억절감"
서천 브라운필드 밑그림 '생태복원 국립공원'
구례경찰서·국립공원공단, 불법카메라 설치 점검
무등산 국립공원서 멸종위기 '황금박쥐' 발견
소백산국립공원, 봄철 탐방객 안전관리 강화에 힘써
월악산국립공원 봄철 불법행위 집중단속 실시