[프로그래머스 인공지능 미니 데브코스] 수업 정리 -6- [웹 스크래핑 기초 II]

3yeong·2022년 7월 26일
0
post-thumbnail

1. 웹 브라우저가 HTML을 다루는 방법

DOM(Document Object Model)

브라우저의 렌더링 엔진은 웹 문서를 로드한 후, 파싱을 진행

  • 이를 DOM(Document Object Model) 이고 한다.

브라우저에 대한 넓고 얕은 지식


각 노드를 객체로 생각하면 문서를 더욱 편리하게 관리할 수 있다.


DOM Tree를 순회해서 특정 원소를 추가할 수 있다.


DOM Tree를 순회해서 특정 원소를 찾을 수 있다

브라우저는 왜 HTML을 DOM으로 바꿀까?
1. 원하는 요소를 동적으로 변경해 줄 수 있다.
2. 원하는 요소를 쉽게 찾을 수 있다.

스크래핑 관전에선 어떤 인사이트를 얻을 수 있는가?

  • 브라우저는 HTML을 파싱해서 DOM을 생성한다.
  • 이를 바탕으로 요소를 변경하거나 찾을 수 있다
  • 파이썬으로 HTML을 분석하는 HTML Parser가 필요하다.

2. HTML을 분석해주는 BeautifulSoup

BeautifulSoup 설치 & 사용해보기

BeautifulSoup 라이브러리

res.body를 하면 내용이 아주 긴 텍스트로 와서 분석하기 힘들다.

원하는 요소만 가져올 수 없을까?
이를 해결하기 위한 HTML코드를 분석해주는, HTML Parser를 사용할 수 있다.
그 중 BeautifulSoup4를 사용하려 한다.

이를 사용하기 위해 pip를 이용하여 설치한다.

  • %를 이용하여 쉽게 다운 받을 수 있다.

    	 %pip install beautifulSoup4

BeautifulSoup 객체 만들기

www.example.com 사이트를 요청한 후 응답 받아보기

import requests

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

res.text


res를 그대로 사용하지 않고 HTML Parser에 전달하기

  • BeautifulSoup4 -bs4를 불러오기
from bs4 import BeautifulSoup # 클래스 가져오기

bs4를 사용하기 위해선, BeautifulSoup 객체를 생성해야한다.

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

객채 soup의 .prettify()를 활용하면 HTML을 보기 편하게 반환한다.

print(soup.prettify())

soup를 통해 HTML의 특정 요소를 가져올 수 있다.

#title 가져오기
soup.title

#head 가져오기
soup.head

#body 가져오기
soup.body

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

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

#태그 이름 가져오기
h1 = soup.find("h1")
h1.name

#태그 내용 가져오기
h1.text

3. 원하는 요소 가져오기 I

책 이름 모으기

Target: Mock Book Data

다음 사이트의 책 이름 정보를 스크래핑 한다.
http://books.toscrape.com/catalogue/category/books/travel_2/index.html

<h3>안의 <a> 안에있는 title
스크래핑에 필요한 라이브러리 불러오기

import requests
from bs4 import BeautifulSoup

예시 사이트에 요청을 진행하고, 응답을 바탕으로 BeautifulSoup 객체 만들기

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

soup = BeautifulSoup(res.text, "html.parser")
# <h3> 태그에 해당하는 요소를 하나 찾기
book = soup.find("h3") #객체

# <h3> 태그에 해당하는 요소 모두 찾기
h3_results = soup.find_all("h3")
h3_results[0]

찾아온 데이터들은 모두 객체이다.

# book_list에서 원하는 제목(title)만 추출

for book in h3_results:
    print(book.a["title"])

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

idclass를 활용해 특정 요소를 지정해 정보를 가져오는 방법

그래, 바로 너! idclass

  • 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>
#스크래핑에 필요한 라이브러리 불러오기

import requests
from bs4 import BeautifulSoup

#사이트에 요청을 보내고, 응답을 BeautifulSoup 객체로 만들기
res = reqests.get("http://example.python-scraping.com/")
soup = BeautifulSoup(res.text,"html.parser")

id를 이용해 요소 가져오기

: id는 요소 하나를 지칭하는 특별한 별명(겹칠 수 없다)
: id를 이용하면 해당하는 태그 단 하나를 쉽게 가져올 수 있다.

#id 없이 div 태그 찾기
soup.find("div")

#id가 results인 div 태그 찾기
soup.find("div", id = "results")

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

: class는 유사한 요소들을 구분짓는 별명이다.
: class를 이용하면 해당하는 태그 하나(혹은 여러개)를 쉽게 가져올 수 있다.

  • e.g. 차트 속의 데이터 등
#clss 가 "page-header"인 div 태그 찾아보기
find_result = soup.find("div", "page-header")

#text 깔끔하게 가져오기
find_result.h1.text.strip()

->'Example web scraping website'

5. 원하는 요소 가져오기 II

스크래핑 하고자 하는 사이트 확인하기

:https://hashcode.co.kr/

두 가지 원칙 지기키

  1. 과도한 요청 보내지 않기
  2. 받아온 정보 활용에 유의하기
# User-Agent 추가
user_agent={"User-Agent" : ""}

#스크래핑에 필요한 라이브러리 불러오기

import requests
from bs4 import BeautifulSoup

#사이트에 요청을 보내고, 응답을 BeautifulSoup 객체로 만들기
res = requests.get("https://hashcode.co.kr/", user_agent)

#응답을 바탕으로 BeautifulSoup 객체 만들기
soup = BeautifulSoup(res.text,"html.parser")

#질문의 제목을 모아서 가져와보기
soup.find("li","question-list-item").find("div", "question").find("div","top").h4.text

->"파이썬 '파일 생성' 오류 발생"

Bonus:페이지네이션(Pagination)

페이지네이션은 많은 정보를 인덱스로 구분하는 기법이다.
위 링크의 페이지는 Query String을 통해 구분하게 되는데, 화면을 보면 각각 페이지로 잘라서 보여지게 된다.

  • https://hashcode.co.kr/?page={i}
    
    #Pagination이 되어있는 질문 리스트의 제목을 모두 가져오기
    #과도한 요청을 방지하기 위해 1초마다 요청 보내기
    import time
    for i in range(1, 6): #1~5페이지 까지
       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)
       time.sleep(0.5)
           
 
 위의 코드를 통해 페이지마다 출력할 수 있게 된다.
profile
초보 컴공

0개의 댓글