기본적인 웹 스크래핑의 실습을 하는 시간이었다.
bs4를 사용하여 스크래핑했는데, 기존에 해본 경험이 있어 낯설지 않았다.
다만 bs4가 이런거다, 기본적인 작동 방법 정도를 알려주는거라 혼자 더 연습하면서 사용법을 숙달해야겠다.
내일 강의에 selenium이 에정되어있는데, selenium 강의가 기대된다.
#bs4 설치
%pip install beautifulsoup4
# www.example.com 사이트를 요청한 후 응답 받아보기
#html 파서니 html 파일이 있어야한다
#모듈 불러오기
import requests
res = requests.get("http://www.example.com")
res.text
# BeautifulSoup4 - bs4를 불러와봅시다.
from bs4 import BeautifulSoup as bs4 #보통 파이썬에서 대문자로 시작하면 클래스
# BeautifulSoup객체를 만들어봅시다.
# 첫번째 인자로는 response의 body를 텍스트로 전달합니다.
# 두번째 인자로는 "html"로 분석한다는 것을 명시해줍니다.
soup = bs4(res.text, "html.parser") #res의 text를 먼저 전달, 어떤형식으로 분석할것인가 명시
# 객체 soup의 .prettify()를 활용하면 분석된 HTML을 보기 편하게 반환해줍니다.
print(soup.prettify())
# title 가져오기
soup.title
# head 가져오기
soup.head
# body 가져오기
soup.body
# <h1> 태그로 감싸진 요소 하나 찾기
#find 사용
h1 = soup.find("h1")
# <p> 태그로 감싸진 요소들 찾기
# find_all 사용
soup.find_all("p")
# 태그 이름 가져오기
#name 사용
h1.name
# 태그 내용 가져오기
#text사용
h1.text
# 스크래핑에 필요한 라이브러리를 불러와봅시다.
import requests
from bs4 import BeautifulSoup as bs
# 예시 사이트에 요청을 진행하고, 응답을 바탕으로 BeautifulSoup 객체를 만들어봅시다.
res = requests.get("http://books.toscrape.com/catalogue/category/books/travel_2/index.html")
soup = bs(res.text, "html.parser")
# <h3> 태그에 해당하는 요소를 하나 찾아봅시다
book = soup.find("h3")
# <h3> 태그에 해당하는 요소를 모두 찾아봅시다
h3_results = soup.find_all("h3")
len(h3_results)
h3_results[0]
# book_list에서 우리가 원하는 제목(title)만 추출해봅시다.
# 객체 - 메서드를 호출하거나 안에 있는 속성을 사용
# h3태그 안에 a태그를 속성처럼사용할수 있음
book.a.text
#title 속성에 전체 제목이 다 들어가 있음
#dic 처럼 사용
for book in h3_results:
print(book.a.text)
for book in h3_results:
print(book.a["title"])
#웹 사이트 확인
#찾고자 하는 요소가 어디에 있는가, 어떤 태그로 감싸져 있는가
#requests
#bs로 객체 만듬
#관련된 속성 사용
태그는 자신의 이름 뿐만 아니라 고유한 속성 또한 가질 수 있음
이 중에서
id와class는 Locator로서, 특정 태그를 지칭하는 데에 사용
tagname: 태그의 이름id: 하나의 고유 태그를 가리키는 라벨class: 여러 태그를 묶는 라벨<p>This element has only tagname</p> #p태그로만 묶여짐 <p id="target">This element has tagname and id</p> #id와 target라는 키와 밸류, unique 해야함 <p class="targets">This element has tagname and class</p> #class, targets
id와 class를 이용해서 HTML의 특정 태그를 지칭하고 가져오는 방법
# 스크래핑에 필요한 라이브러리를 불러와봅시다.
import requests
from bs4 import BeautifulSoup as bs
## 또 다른 연습 사이트를 이용해봅시다.
# http://example.python-scraping.com/ (현재시점 접속안됨)
#국가정보가 많은 태그에 감싸져있음
#특정 로케이터 찾기
#span12
#id = result id가 results인것은 하나
res = requests.get("http://example.python-scraping.com/")
soup = bs(res.text, "html.parser")
## id 없이 div 태그를 찾아봅시다.
soup.find("div")
#태그,id, 클래스 이름으로 함께 검색
## id가 results인 div 태그를 찾아봅시다.
soup.find("div", id ="results")
# class가 "page-header"인 div 태그를 찾아봅시다.
#파라미터 이름을 굳이 안 지정해도 됨
find_result = soup.find("div", "page-header")
# 위 결과에서 text 값을 깔끔하게 가져와봅시다.
find_result
finr_result.h1.text.strip() #특정 공백을 다 지움
아래 두 가지 원칙을 지킵니다.
- 과도한 요청을 보내지 않습니다.
- 받아온 정보 활용에 유의합니다.
질문의 리스트를 가져오는게 목적
수많은 li태그와 question, top에 질문이 들어가있음
question-list-item 클래스
li태그 중에서 클래스가 question-list-item 인 것을 find all
# 다음 User-Agent를 추가해봅시다.
user_agent = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Whale/3.22.205.26 Safari/537.36"}
# 필요한 라이브러리를 불러온 후, 요청을 진행해봅시다.
import requests
from bs4 import BeautifulSoup as bs
res = requests.get("https://hashcode.co.kr/", user_agent) #user_agent는 헤더, 키와 밸류로 되어있음
# 응답을 바탕으로 BeautifulSoup 객체를 생성해봅시다.
soup = bs(res.text, "html.parser")
# 질문의 제목을 모아서 가져옴
#class = "question-list-item"을 다 가져옴
#그다음 안에 h4를 검색 -> 51개로 유일하지 않음
#question list item에 대해서 스크래핑
#연쇄적으로 사용가능
#soup.find("li", "question-list-item").find("div", "question").find("div","top").h4.text
#for문을 사용해서 반복해서 가져오기
questions = soup.find_all("li", "question-list-item")
for question in questions:
print(question.find("div", "question").find("div","top").h4.text)
페이지네이션은 많은 정보를 인덱스로 구분하는 기법
Query String을 통해서 이를 구분
https://hashcode.co.kr/?page={i}
# Pagination이 되어있는 질문 리스트의 제목을 모두 가져와봅시다.
# 과도한 요청을 방지하기 위해 1초마다 요청을 보내봅시다.
# 페이지네이션이 n번 된 페이지를 참조하려면 n번 요청해야함
import time
for i in range(1,6):
res = requests.get("https://hashcode.co.kr/?page={}".format(i), user_agent) #중괄호의 변수를 i로 치환해줌
soup = bs(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)
- 비동기 처리 : 요청에 따른 응답을 기다리지 않음
- 동기 처리된 경우, HTML 로딩에 문제가 없음 (데이터 처리가 다 끝나기 때문)
- 비동기 처리된 경우 상황에 따라서 데이터가 완전하지 않은 경우가 발생 (데이터 처리가 진행중에 스크래핑을 하게 되는 경우 발생)
- 키보드 입력, 마우스 클릭을 프로그래밍 하려면? → 응답이 온 후의 작업 → 응답이 온 후에 ui action을 할 수 있는 환경 구현
- 웹 브라우저를 파이썬으로 조작하기
- 웹 브라우저를 자동화하는 라이브러리 Selenium
- 응답 후 시간을 지연시킬 수 있음
- UI와의 상호작용 가능