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

[python] requests와 BeautifulSoup으로 웹 크롤러 만들기 updated_at: 2024-03-20 16:15

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

Requests

Requests 설치

pip install requests

Requests 를 이용하여 데이타 가져오기

import requests
..........
req = requests.get('https://onstory.fun')

requests timeout 설정 및 retry

검색을 해보면 좀더 고급진 방법들도 많은데 여기서는 BeautifulSoup과 함께 간단히 사용하는 함수를 소개새 드립니다.

def get_bs_obj(self, url):
  # url = "https://finance.naver.com

  session = requests.Session()
  for _ in range(5): # 5 번 시도
    try:
      result = session.get(url, headers=headers(), timeout=3) # time out 설정
      bs_obj = BeautifulSoup(result.content.decode('euc-kr', 'replace'), "html.parser")  # html.parser 로 파이썬에서 쓸 수 있는 형태로 변환
      return bs_obj
    except requests.exceptions.ConnectTimeout:
      time.sleep(5)
    except requests.exceptions.ConnectionError: # 네이버 크롤링시 종종 발생
      time.sleep(5)

  return f"Could not process {url}"

BeautifulSoup

BeautifulSoup 설치하기

pip install bs4

예제

import requests
from bs4 import BeautifulSoup

## HTTP GET Request
req = requests.get('https://onstory.fun')

## HTML 소스 가져오기
html = req.text
## BeautifulSoup으로 html소스를 python객체로 변환하기
## 첫 인자는 html소스코드, 두 번째 인자는 어떤 parser를 이용할지 명시.
soup = BeautifulSoup(html, 'html.parser')

## Selector를 통해 html요소들을 찾아낸다.
links = soup.select('a')
    
for link in links:
  ## Tag안의 텍스트
  print(link.text)
  ## Tag의 속성을 가져오기(ex: href속성)
  print(link.get('href'))

select : HTML 내 필요한 부분 선택하기

# 원하는 정보가 있는 위치 찾기 

soup.select('원하는 정보')  # select('원하는 정보') -->  단 하나만 있더라도, 복수 가능한 형태로 되어있음

soup.select('태그명')
soup.select('.클래스명')
soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')    # 바로 아래의(자식) 태그를 선택시에는 > 기호를 사용
soup.select('상위태그명.클래스명 하~위태그명')              # 아래의(자손) 태그를 선택시에는   띄어쓰기 사용
soup.select('상위태그명 > 바로아래태그명 하~위태그명')     
soup.select('.클래스명')
soup.select('#아이디명')                  # 태그는 여러개에 사용 가능하나 아이디는 한번만 사용 가능함! ==> 선택하기 좋음
soup.select('태그명.클래스명)
soup.select('#아이디명 > 태그명.클래스명)
soup.select('태그명[속성1=값1]')

select_one

select와 사용법은 동일하나 하나의 결과만 가져온다.

find

Find 는 태그만을 가져온다.
여러개의 값이 있더라도 처음 하나만을 가져온다.

from bs4 import BeautifulSoup

html = "<div class='my-class' id='my-id'> Hello World! </div>" \
       "<p class='my-class'>Welcome To Python</p>"

soup = BeautifulSoup(html, 'html.parser')

# 태그 특정
result1 = soup.find('div')
print(result1)
# 태그 속성만 특정
result2 = soup.find(class_='my-class')
print(result2)
# 속성을 이용하여 특정
result3 = soup.find(attrs = {'id':'my-id'})
print(result3)
# 태그 이름과 클라스 모두 특정
result4 = soup.find('p', class_='my-class')
print(result4)

결과

<div class="my-class" id="my-id"> Hello World! </div> # result1
<div class="my-class" id="my-id"> Hello World! </div> # result2
<div class="my-class" id="my-id"> Hello World! </div> # result3
<p class="my-class">Welcome To Python</p> # result4

find_all

find와 사용법은 동일하나 find가 하나만 가져오는 반면 find_all은 일치하는 모든 것을 가져온다.

Find를 이용해 가져온 태그의 속성들을 출력

#태그의 이름
print(result1.name) # 결과: 'div'

#태그에 담긴 텍스트
print(result1.text) # 결과: ' Hello World! '

# 태그의 속성과 속성값
print(result1.attrs) # 결과: {'class': ['my-class'], 'id': 'my-id'}
평점을 남겨주세요
평점 : 5.0
총 투표수 : 1

질문 및 답글