1. BeautifulSoup
2. 원하는 요소 찾기
3. 동적 웹 사이트
HTML에서 원하는 요소만 가져오려면?
라이브러리 설치
pip install bs4BeautifulSoup
import requests
# bs4안의 BeautifulSoup Class 사용
from bs4 import BeautifulSoup
res = requests.get("http://www.example.com")
# BeautifulSoup객체를 만들기
# 첫번째 인자로는 response의 body를 텍스트로 전달합니다.
# 두번째 인자로는 어떤 형식으로 분석을 할 것인지 명시 : "html"
soup = BeautifulSoup(res.text, "html.parser")
# .prettify()를 활용하면 분석된 HTML을 보기 편하게 반환
print(soup.prettify())
# => soup로 분석을 진행하고, prettify()로 분석한 것을 가시화
# title, head, body 부분을 별도로 추출 가능
soup.title
soup.head
soup.body
# <h1> 태그로 감싸진 요소 하나 찾기
soup.find("h1")
# <h1> 태그로 감싸진 요소 모두 찾기
soup.find_all("h1")
# 태그 이름 가져오기
h1.name
# 태그 내용 가져오기
h1.text
1) 책 이름 모으기
https://books.toscrape.com/catalogue/category/books/travel_2/index.html
HTML의 h3태그 안에 책 이름이 있는 것을 이용 ( 관찰에 의한 결론 )
import requests
from bs4 import BeautifulSoup
res = requests.get("https://books.toscrape.com/catalogue/category/books/travel_2/index.html")
soup = BeautifulSoup(res.text,"html.parser")
# h3태그가 감싼 모든 요소를 호출
book_list = soup.find_all("h3")
# book_list에서 a태그 속 contents를 text로 변환
for book in book_list :
print(book.a.text)
# 확인해보니 contents에는 정보의 소실이 있다는 것을 발견
# title 내부에 정확한 책 이름이 있다는 것을 확인
# a 태그의 title에 접근
for book in book_list :
print(book.a["title"])
2) Tag의 id와 class 활용
태그는 자신의 이름 뿐만 아니라 고유한 속성을 가질 수 있음
이 중, id와 class는 Locator로서, 특정 태그를 지칭하는데 사용
<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
res = requests.get("http://example.python-scraping.com/")
soup = BeautifulSoup(res.text,"html.parser")
## id가 results인 div 태그
soup.find("div",id="results")
# class가 "page-header"인 div 태그
find_result = soup.find("div","page-header")
# find_result의 h1의 contents를 호출
# python의 strip() 함수는 개행, 역슬래시, 공백 등을 모두 잘라준다.
find_result.h1.text.strip()
python의 strip() 함수는 개행, 역슬래시, 공백 등을 모두 제거
3) Hashcode 질문 가져오기
주의사항
- 과도한 요청을 보내지 않는다.
- 받아온 정보 활용에 유의할 것.
질문의 제목이 li 태그 속 class가 question-list-item인 경우에 들어있다는 것을 확인
import requests
from bs4 import BeautifulSoup
# 이 user_agent를 설정하면, Mac의 Chrome환경의 접속자로 여겨짐
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"}
# 본래 user_agent의 자리에 header가 들어감, key-value의 형태이기에 같은 형식의 user_agent로 교체
res = requests.get(" https://hashcode.co.kr/", user_agent)
soup = BeautifulSoup(res.text,"html.parser")
questions = soup.find("li","question-list-item")
# 타고 타고 들어가서 제목 찾기
questions.find("div","question").find("div","top").h4.text
# 전부 찾기
for question in questions :
print(question.find("div","question").find("div","top").h4.text)
페이지네이션은 많은 정보를 인덱스로 구분하는 기법입니다.
https://hashcode.co.kr/의 경우 Query String을 통해서 이를 구분
https://hashcode.co.kr/?page={i}
# Pagination이 되어있는 질문 리스트의 제목을 모두 가져와봅시다.
# 과도한 요청을 방지하기 위해 1초마다 요청을 보내봅시다.
import time
# 1~6 페이지까지 호출
for i in range(1,6):
requests.get("https://hashcode.co.kr/?page={}".format(i),user_agent)
soup = BeautifulSoup(res.text,"html.parser")
questions = soup.find("li","question-list-item")
# 전부 찾기
for question in questions :
print(question.find("div","question").find("div","top").h4.text)
# 0.5초마다 뽑기
time.sleep(0.5)
웹페이지의 종류
정적 웹 사이트
동적 웹 사이트
동적 웹사이트

Requests로 요청 시 발생하는 문제점
해결 방법
임의로 시간을 지연한 후, 데이터 처리가 끝난 후 정보를 가져오면 됨
UI Action(키/마)을 프로그래밍을 통해 명령을 내림
=> 웹 브라우저를 Python으로 조작
e.g.) 파이썬을 통해 이 버튼을 클릭해, 이 명령을 입력해, ...
웹 브라우저를 자동화하는 라이브러리 (Python)
from selenium import webdriver
# Chrome 브라우저
driver = webdriver.Chrome()
# 10초간 지연 시킴
driver.implicitly_wait(10)
driver.get("http://www.example.com")
from selenium import webdriver
# UI와 상호작용
elem = driver.find_element_by_tag_name("hello-input")
elem.send_keys("Hello!")
- 동적 웹사이트는 응답 후 바로 정보를 추출하기 어렵다
- 다양한 키보드 입력과 마우스 클릭 등의 상호작용이 존재
- 이런 상황을 해결하기 위해, 웹 브라우저를 파이썬으로 조작하는 전략을 취하자
(selenium 라이브러리)