데이터/크롤러

requests와 BeautifulSoup으로 웹 크롤러 만들기

나모장 2022. 6. 20. 18:53

https://beomi.github.io/gb-crawling/posts/2017-01-20-HowToMakeWebCrawler.html

 

requests와 BeautifulSoup으로 웹 크롤러 만들기 · GitBook

No results matching ""

beomi.github.io

위의 글을 보고 따라하며 작성한 게시글 입니다.


Request 라이브러리

python - request 라는 http request 라이브러리 설치

저는 m1 맥북 유저로써, iterms 를 이용하여 Request 라이브러리를 설치했습니다.

다음 명령어를 입력해주시면 됩니다.

pip install requests
## parser.py
import requests

## HTTP GET request
req = requests.get('https;//beomi.github.io./beomi.gitub.io_old/')

## HTML 소스 가져오기
html = req.text
## HTTP Header 가져오기
header = req.headers
## HTTP Status 가져오기 (200 : 정상)
status = req.status_code
## HTTP 정상 여부 (True/False)
is_ok = req.ok

하지만 Request는 html를 python이 이해하는 객체 구조로 만들어주지 못합니다.

req.text는 python의 문자열(str) 객체를 반환할 뿐이기 때문에 정보 추출에 어려움이 있습니다.

따라서 BeautifulSoup 라이브러리를 이용합니다.

BeautifulSoup 라이브러리

BeautifulSoup은 html 코드를 Python이 이해하는 객체 구조로 변환하는 Parsing을 맡고있습니다.

pip install bs4

저는 bs4라는 wrapper 라이브러리를 통해 설치했습니다.

라이브러리를 설치했다면, python 파일을 만들어줍니다.

## parser.py
import requests
from bs4 import BeautifulSoup

## HTTP GET Request
req = requests.get('https://beomi.github.io/beomi.github.io_old/')

## HTML 소스 가져오기
html = req.text

## BeautifulSoup으로 html소스를 python객체로 변환하기
## 첫 인자는 html소스코드, 두 번째 인자는 어떤 parser를 이용할지 명시.
## 이 글에서는 Python 내장 html.parser를 이용했다.
soup = BeautifulSoup(html, 'html.parser')

이제 soup 객체에서 원하는 정보를 찾아낼 수 있습니다.

BeautifulSoup에서 select 를 이용하여 CSS Selector를 이용하여 조건과 일치하는 모든 객체를 list로 반환합니다.
이를 활용하여 블로그의 모든 제목을 가져오는 예시를 해보도록 하겠습니다.

블로그의 제목 가져오기

개발자 도구 보는 법

1) m1 맥북 pro 13인치 기준 하단 맨 왼쪽을 보시면 fn키를 누르면 터치바에 f1 ~ f12키가 뜹니다. f12를 누르시면 개발자도구를 보실 수 있습니다.

2) option + command + I

3) 보기 > 개발자 정보 > 개발자 도구 클릭

블로그에서 제목은 어떤 태그로 묶여 있는지를 알아야 합니다.

마우스로 움직여서 제목을 보면 a 태그로 묶여 있다는 것을 알 수 있습니다.

정확하게 가져오기 위해서 CSS Selector를 확인해봅니다.

아래와 같은 코드가 클립보드에 복사됩니다.

body > h3:nth-child(4) > a

다른 제목도 copy selector를 해보면

body > h3:nth-child(7) > a

이렇게 나옵니다. 따라서 nth-child(숫자) 는 블로그의 제목 중 하나를 특정하고 있습니다.

따라서 아래와 같이 selector를 변경합니다.

h3 > a

python파일을 수정해줍니다.

## parser.py
import requests
from bs4 import BeautifulSoup

## HTTP GET Request
req = requests.get('https://beomi.github.io/beomi.github.io_old/')

## HTML 소스 가져오기
html = req.text

## BeautifulSoup으로 html소스를 python객체로 변환하기
## 첫 인자는 html소스코드, 두 번째 인자는 어떤 parser를 이용할지 명시.
## 이 글에서는 Python 내장 html.parser를 이용했다.
soup = BeautifulSoup(html, 'html.parser')

## CSS Selector를 통해 html 요소 찾아내기
my_titles = soup.select(

    'h3 > a'
)

my_titles는 string의 list가 아니라, soup 객체들의 list입니다. 따라서 태그의 속성을 이용할 수 있습니다.
a 태그의 경우, href 속성이 대표적인 예시입니다.
<태그></태그> 로 구성된 요소를 python이 이해하는 상태로 바꾼 것으로 볼 수 있습니다.

## parser.py
import requests
from bs4 import BeautifulSoup

## HTTP GET Request
req = requests.get('https://beomi.github.io/beomi.github.io_old/')

## HTML 소스 가져오기
html = req.text

## BeautifulSoup으로 html소스를 python객체로 변환하기
## 첫 인자는 html소스코드, 두 번째 인자는 어떤 parser를 이용할지 명시.
## 이 글에서는 Python 내장 html.parser를 이용했다.
soup = BeautifulSoup(html, 'html.parser')

## CSS Selector를 통해 html 요소 찾아내기
my_titles = soup.select(
    'h3 > a'
)

## my_titles는 list 객체
for title in my_titles:
    ## Tag안의 텍스트
    print(title.text)
    ## Tag의 속성을 가져오기(ex: href속성)
    print(title.get('href'))

위의 경우, a 태그 안의 텍스트, href속성값을 가져오게 됩니다.
select를 통해 요소를 가져온 이후에는, 자신이 원하는 방식으로 python 코드를 이용하여 저장하면 됩니다.

 

json 파일

JSON(JavaScript Object Notation) 은 문자열 형태로 존재하기 때문에 네트워크를 통하여 데이터 전송시에 유용합니다.

 

크롤링한 데이터를 python파일과 같은 위치에 result.json을 만들어 저장하는 예제를 작성해보겠습니다.

## parser.py
import requests
from bs4 import BeautifulSoup
import json
import os

## python파일의 위치
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

## HTTP GET Request
req = requests.get('https://beomi.github.io/beomi.github.io_old/')
## HTML 소스 가져오기
html = req.text
## BeautifulSoup으로 html소스를 python객체로 변환하기
## 첫 인자는 html소스코드, 두 번째 인자는 어떤 parser를 이용할지 명시.
## 이 글에서는 Python 내장 html.parser를 이용했다.
soup = BeautifulSoup(html, 'html.parser')
## CSS Selector를 통해 html 요소 찾아내기
my_titles = soup.select(
    'h3 > a'
    )

data = {}

for title in my_titles:
    data[title.text] = title.get('href')

with open(os.path.join(BASE_DIR, 'result.json'), 'w+') as json_file:
    json.dump(data, json_file)

result.json파일이 생긴 것을 볼 수 있습니다.