20230419 TIL - 파이썬의 HTML Parser, BeautifulSoup

ohyujeong·2023년 4월 19일
0

TIL

목록 보기
8/27
post-thumbnail

📖 오늘의 학습

  • 파이썬의 HTML Parser, BeautifulSoup

HTML을 분석해주는 BeautifulSoup

  • 긴 text로 반환되는 html을 분석해주는 라이브러리
  • 주피터노트북 환경에서 pip install bs4 로 설치

BeautifulSoup 객체 만들기

# 라이브러리 가져오기
import requests
from bs4 import BeautifulSoup

# www.example.com 사이트를 요청한 후 응답 받아보기
res = requests.get("http://www.example.com")

# 첫번째 인자: response의 body를 텍스트로 전달
# 두번째 인자: "html"로 분석한다는 것을 명시
soup = BeautifulSoup(res.text, "html.parser")

# 분석된 HTML을 보기 편하게 반환 (indent 맞춰서)
print(soup.prettify())

원하는 요소 가져오기

# title 가져오기
soup.title

# head 가져오기
soup.head

# body 가져오기
soup.body

# <h1> 태그로 감싸진 요소 하나 찾기
# find("태그 이름") : 지정한 첫번째 태그를 가져옴 
h1 = soup.find("h1")

# <p> 태그로 감싸진 모든 요소들 찾기
p = soup.find_all("p")

# 태그 이름 가져오기
h1.name

# 태그 내용(콘텐츠) 가져오기
h1.text

# <h1> 태그 안에 <a>태그로 감싸진 내용(콘텐츠) 가져오기
h1.a.text

# <h1> 태그 안에 <a>태그로 감싸진 title 속성 값 가져오기
h1.a["title"]

HTML의 Locator로 원하는 요소 찾기

idclass

태그는 자신의 이름 뿐만 아니라 고유한 속성 또한 가질 수 있다.
이 중에서 idclass는 Locator로서, 특정 태그를 지칭하는 데에 사용된다.

  • tagname: 태그의 이름
  • id: 하나의 고유 태그를 가리키는 라벨
  • class: 여러 태그를 묶는 라벨
<p>This element has only tagname</p>
<p id="target">This element has tagname and id</p>
<p class="targets">This element has tagname and class</p>

id를 이용해서 요소 가져오기

  • id 는 요소 하나를 지칭하는 특별한 별명으로 고유해야한다.
# id 없이 div 태그찾기
soup.find("div")
# id가 results인 div 태그를 찾기
soup.find("div", id="results")

class를 이용해서 요소(들) 가져오기

  • class 는 유사한 요소들을 구분짓는 별명이다.
  • id 와 달리 중복으로 사용이 가능하다.
# class가 "page-header"인 div 태그 찾기
find_result = soup.find("div", "page_header")

깊은 depth에 있는 요소 가져오기

import requests
from bs4 import BeautifulSoup as bs

# 2번째 인자는 header
res = requests.get("https://hashcode.co.kr/", user_agent)

# BeautifulSoup 객체 생성
soup = bs(res.text, "html.parser")

# 태그가 <li>이고 클래스 명이 "question-list-item" 인 모든 요소 찾기
questions = soup.find_all("li", "question-list-item") 

# questions 리스트를 순회하면서 깊이 들어가 있는 요소들을 출력
# .find()를 반복하며 깊이 들어간다.
for question in questions:
    print(question.find("div","question").find("div", "top").h4.text)

user-agent 추가하기

  • user-agent는 HTML의 header의 내용 중 하나이다.
  • 웹 스크랩 대상 사이트마다 허용하는 user-agent가 다름
  • 기존 header의 user-agent를 탐색하고자 하는 사이트가 허용하지 않는다면 user-agent (header)를 임의로 지정해주어야 함
import requests

user_agent = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"}
res = requests.get("https://hashcode.co.kr/", user_agent)

페이지네이션(Pagination)

  • query string으로 페이지를 구분하는 사이트는 아래와 같이 탐색할 수 있다.
  • https://hashcode.co.kr/?page={i} 와 같이 page 값을 변수로 두고 페이지를 변경하면서 웹 스크래핑을 한다.
# Pagination이 되어있는 질문 리스트의 제목을 모두 가져온다.
# 과도한 요청을 방지하기 위해 1초마다 요청한다.

import time

for i in range(1, 11):
    res = requests.get(f"https://hashcode.co.kr/?page={i}", user_agent)
    soup = bs(res.text, "html.parser")
    questions = soup.find_all("li", "question-list-item")
    
    print(f"--------------page={i}---------------")
    for question in questions:
        print(question.find("div","question").find("div", "top").h4.text)
    
    time.sleep(1)

정적 웹사이트와 동적 웹사이트

정적 웹사이트

  • HTML 내용이 고정된 정적(static) 사이트
  • 웹 스크래핑이 용이함
  • HTML문서가 완전하게 응답된다

동적 웹사이트

  • HTML 내용이 변하는 동적(dynamic) 웹사이트
  • 응답 후 HTML이 렌더링이 될 때까지의 지연시간이 존재한다.

동적 웹사이트의 동작방식

웹 브라우저에선 javascript 라는 프로그래밍 언어가 동작한다.
이 javascript는 비동기 처리를 통해서 필요한 데이터를 응답 이후에 채운다.

  • 동기처리 : 요청에 따른 응답을 기다린다. 예를 들어 렌더링과 데이터 처리 작업이 있을 때, 동기 방식은 렌더링을 마친 이후 데이터 처리작업을 수행한다.
    • 이 경우, HTML로딩에 문제가 없어 우리가 원하는 데이터를 명확하게 가져올 수 있어 웹 스크래핑이 용이하다
  • 비동기 처리 : 요청에 따른 응답을 기다리지 않는다. 렌더링과 데이터 처리 작업을 같이 수행한다.
    • 상황에 따라서 데이터가 완전하지 않은 경우가 발생한다. 예를 들어 렌더링과 데이터 처리 작업이 동시에 진행되었고 렌더링이 끝난 상태에서 데이터 수집 시도를 했을 때, 데이터 처리 작업이 아직 끝나지 않은 상태일 경우

requests로 요청 시 발생하는 문제점

  • 데이터 처리가 완료되지 않은 상태에서 데이터를 요청 시 불완전한 데이터를 수집할 수 있음
  • 키보드 입력, 마우스 클릭 등을 requests로는 진행하기 어렵다.

💡 해결방법

  • 임의로 시간을 지연한 후, 데이터 처리가 끝난 후 정보를 가져온다
  • UI Action(키보드 입력, 마우스 클릭 등)을 프로그래밍을 통해 명령을 내린다.
    ➡️ 웹 브라우저를 자동화하는 파이썬 라이브러리 Selenium를 통해 UI와의 상호작용이 가능하다.

    동적 웹사이트는 응답 후 바로 정보를 추출하기 어렵다
    또한, 다양한 상호작용이 존재한다.
    이런 상황을 해결하기 위해, 웹 브라우저를 파이썬으로 조작하는 전략을 취하자!
    이는 웹 브라우저를 자동화하는 라이브러리 Selenium를 통해 실현할 수 있다


📝 주요메모사항


😵 공부하면서 어려웠던 내용

profile
거친 돌이 다듬어져 조각이 되듯

0개의 댓글