[TIL] 파이썬으로 웹 데이터를 크롤하고 분석하기 (3)

이원진·2023년 4월 19일
0

데브코스

목록 보기
8/54
post-thumbnail

학습 주제


  1. HTML을 분석해주는 BeautifulSoup

  2. 원하는 요소 가져오기 1

  3. HTML의 Locator로 원하는 요소 찾기

  4. 원하는 요소 가져오기 2

  5. 동적 웹페이지와의 만남

1. HTML을 분석해주는 BeautifulSoup


  • BeautifulSoup 라이브러리

    • HTML 코드를 분석해주는 HTML Parser

    • BeautifulSoup(response_body, "html.parser")

      • 첫 번째 인자는 response의 body를 텍스트로 전달

      • 두 번째 인자는 "html"로 분석한다는 것을 명시

    • .pretify()

      • 분석된 HTML을 보기 편하게 변환

import requests
from bs4 import BeautifulSoup

res = requests.get("http://www.example.com")

soup = BeautifulSoup(res.text, "html.parser")
print(soup.prettify())

# title 가져오기
print(soup.title)

# head 가져오기
print(soup.head)

# body 가져오기
print(soup.body)

# <h1> 으로 감싸진 요소 하나 찾기
print(soup.find("h1"))

# <p> 로 감싸진 요소들 찾기
print(soup.find_all("p"))

# 태그 이름, 내용 가져오기
h1 = soup.find("h1")
print(h1.name)
print(h1.text)

2. 원하는 요소 가져오기 1


  • 사용할 사이트: http://books.toscrape.com/catalogue/category/books/travel_2/index.html

  • 특정 태그로 스크래핑하는 것은 직관적이지만 좋음 방법은 아님

    • 웹사이트의 구조가 자주 변경되기 때문

  • 크롬에서 검사를 원하는 요소를 우클릭한 뒤 "검사"를 누르면 개발자 도구가 켜지면서 해당 요소 가리킴

  • 찾아온 데이터들은 모두 객체이므로, 아래와 같이 접근할 수 있음

    book = soup.find("h3")
    
    # <h3> 안에 있는 <a>의 콘텐츠 추출
    book.a.text

import requests
from bs4 import BeautifulSoup

res = requests.get("http://books.toscrape.com/catalogue/category/books/travel_2/index.html")

soup = BeautifulSoup(res.text, "html.parser")

# <h3> 에 해당하는 요소 모두 검색해 제목(Title)만 추출
h3_results = soup.find_all("h3")

for book in h3_results:
    # 속성(Attribute)은 딕셔너리처럼 접근
    print(book.a["title"])

3. HTML의 Locator로 원하는 요소 찾기


  • id와 class는 Locator로서, 특정 태그를 지칭하는 데 사용

    • id: 하나의 고유 태그를 가리키는 라벨

    • class: 여러 태그를 묶는 라벨

  • 사용할 사이트: http://example.python-scraping.com/

import requests
from bs4 import BeautifulSoup

res = requests.get("http://example.python-scraping.com/")

soup = BeautifulSoup(res.text, "html.parser")

# id가 "results"인 div 검색
print(soup.find("div", id = "results"))

# class가 "page-header"인 div 검색
find_result = print(soup.find("div", "page-header"))

# 텍스트 깔끔하게 출력
print(find_result.h1.text.strip())

4. 원하는 요소 가져오기 2


  • 사용할 사이트: https://hashcode.co.kr/

  • 아래의 두 가지 원칙을 지키며 스크래핑하기

    1. 과도한 요청 보내지 않기
    2. 받아온 정보를 유의하며 활용하기

  • 페이지네이션(Pagination)

import requests
from bs4 import BeautifulSoup
import time

# 스크래핑을 위해 user agent 추가
user_agent = {"User-Agent": "Mozilla/5.0 ..."}

# Pagination 되어있는 질문 리스트의 제목 모두 추출
# 1page ~ 5page
for i in range(1, 6):
    res = requests.get("https://hashcode.co.kr/?page={}".format(i), user_agent)

    soup = BeautifulSoup(res.text, "html.parser")

    questions = soup.find_all("li", "question-list-item")

    for question in questions:
        # 계층 구조를 연쇄적으로 접근해 질문글의 제목만 추출
        print(question.find("div", "question").find("div", "top").h4.text)

    # 과도한 요청을 방지하기 위해 1초씩 지연
    time.sleep(1)

5. 동적 웹페이지와의 만남


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

    • 생성 방식에 따른 구분

    • HTML이 고정된 정적(Static) 웹사이트, 내용이 변하는 동적(Dynamic) 웹사이트

    • 정적 웹사이트는 HTML 문서가 완전하게 응답

    • 동적 웹사이트는 응답 후 HTML이 렌더링될 때까지 지연시간이 존재

      • 스크래핑/크롤링 시 유의

  • 동적 웹사이트의 동작 방식

    • Javascript라는 프로그래밍 언어가 동작하며 비동기 처리를 통해 데이터를 채움

      • 동기 처리: 요청에 대한 응답을 기다림

      • 비동기 처리: 요청에 대한 응답을 기다리지 않음

    • 불완전한 응답을 받는 것을 방지하기 위해 임의로 시간을 지연한 뒤 정보를 가져옴

    • 키보드, 마우스 입력 등의 이벤트(상호작용)을 처리하기 위해 웹 브라우저를 파이썬으로 조작

      • 웹 브라우저 자동화 라이브러리 Selenium

메모


  • import 'requests' could not be resolved from source Pylance reportMissingModuleSource

    • 라이브러리가 설치되지 않았거나 찾지 못해서 발생하는 오류
      -> 설치했음에도 오류가 발생한다면, IDE의 인터프리터를 설정해 해결

  • requests.get(URL) 할 때 URL은 "https://"부터 전부 적어줘야 함

0개의 댓글