티스토리 뷰
동적 웹 페이지와의 만남
▶ HTML 내용이 고정된 정적(static) 웹 사이트, HTML 문서가 완전하게 응답됩니다.
▶ HTML 내용이 변하는 동적(dynamic) 웹 사이트, HTML이 렌더링이 될 때까지 지연시간이 존재합니다. (유튜브)
웹 브라우저에선 JavaScript라는 프로그래밍 언어가 동작하며, 비동기 처리를 통해서 필요한 데이터를 채우는 경향이 있습니다.
▶동기 처리: 요청에 따른 응답을 기다리며(렌더링을 다 해야만 데이터 처리가 진행), HTML 로딩에 문제가 없습니다.
▶비동기 처리: 요청에 따른 응답을 기다리지 않고(렌더링과 데이터 처리가 동시에 진행), 상황에 따라서 데이터가 완전하지 않은 경우가 발생합니다.
스크래퍼의 문제점
▶동적 웹 사이트에 적용이 어려움
렌더링과 데이터 처리가 동시에 진행되는 상황에서 요청을 보내면 불완전한 응답을 받게 됩니다.
▶UI 상호작용이 어려움
키보드 입력, 마우스 클릭 등을 requests로는 진행하기 어렵습니다.
[해결 방법]
Q. 정보를 추출하는 시간을 임의로 지연시킨다면?
A. 임의로 시간을 지연한 후, 데이터 처리가 끝난 후 정보를 가져오면 됩니다.
Q. UI Action을 프로그래밍을 통해 명령을 내린다면?
A. 키보드 입력, 마우스 클릭 등을 프로그래밍할 수 있습니다.
웹 브라우저와 파이썬의 만남
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.example.com")
웹 브라우저를 파이썬을 조작할 수 있으며, 자동화하는 라이브러리인 Selenium으로 응답 후 시간을 지연시킬 수 있습니다.
from selenium import webdriver
elem = driver.find_element_by_tag_name("hello-input")
elem.send_keys("Hello!")
UI와의 상호작용이 가능합니다.
동적 웹사이트는 응답 후 바로 정보를 추출하기 어렵고, 다양한 키보드 입력과 마우스 클릭 등의 상호작용이 존재합니다. 이런 상황을 해결하려면 웹 브라우저를 파이썬으로 조작하는 게 좋습니다.
브라우저 자동화하기, Selenium
Selenium 라이브러리
- selenium은 Python을 이용해서 웹 브라우저를 조작할 수 있는 자동화 프레임워크입니다.
pip install을 통해서 이를 간단하게 설치할 수 있습니다.
# selenium 라이브러리를 설치해줍니다.
%pip install selenium
Requirement already satisfied: selenium in ./opt/anaconda3/lib/python3.9/site-packages (4.8.2)
Requirement already satisfied: urllib3[socks]~=1.26 in ./opt/anaconda3/lib/python3.9/site-packages (from selenium) (1.26.11)
Requirement already satisfied: trio~=0.17 in ./opt/anaconda3/lib/python3.9/site-packages (from selenium) (0.22.0)
Requirement already satisfied: certifi>=2021.10.8 in ./opt/anaconda3/lib/python3.9/site-packages (from selenium) (2022.9.24)
Requirement already satisfied: trio-websocket~=0.9 in ./opt/anaconda3/lib/python3.9/site-packages (from selenium) (0.10.2)
Requirement already satisfied: sniffio in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (1.2.0)
Requirement already satisfied: attrs>=19.2.0 in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (21.4.0)
Requirement already satisfied: sortedcontainers in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (2.4.0)
Requirement already satisfied: outcome in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (1.2.0)
Requirement already satisfied: idna in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (3.3)
Requirement already satisfied: exceptiongroup>=1.0.0rc9 in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (1.1.1)
Requirement already satisfied: async-generator>=1.9 in ./opt/anaconda3/lib/python3.9/site-packages (from trio~=0.17->selenium) (1.10)
Requirement already satisfied: wsproto>=0.14 in ./opt/anaconda3/lib/python3.9/site-packages (from trio-websocket~=0.9->selenium) (1.2.0)
Requirement already satisfied: PySocks!=1.5.7,<2.0,>=1.5.6 in ./opt/anaconda3/lib/python3.9/site-packages (from urllib3[socks]~=1.26->selenium) (1.7.1)
Requirement already satisfied: h11<1,>=0.9.0 in ./opt/anaconda3/lib/python3.9/site-packages (from wsproto>=0.14->trio-websocket~=0.9->selenium) (0.14.0)
Note: you may need to restart the kernel to use updated packages.
Web Driver
- 웹 브라우저와 연동을 위해서는 WebDriver가 필요합니다.
- WebDriver는 웹 브라우저를 제어할 수 있는 자동화 프레임워크입니다.
pip install을 통해 webdriver를 관리하는 라이브러리 webdriver-manager를 설치합니다.
# webdriver-manager를 설치해봅니다.
%pip install webdriver-manager
Requirement already satisfied: webdriver-manager in ./opt/anaconda3/lib/python3.9/site-packages (3.8.5)
Requirement already satisfied: tqdm in ./opt/anaconda3/lib/python3.9/site-packages (from webdriver-manager) (4.64.1)
Requirement already satisfied: packaging in ./opt/anaconda3/lib/python3.9/site-packages (from webdriver-manager) (21.3)
Requirement already satisfied: python-dotenv in ./opt/anaconda3/lib/python3.9/site-packages (from webdriver-manager) (1.0.0)
Requirement already satisfied: requests in ./opt/anaconda3/lib/python3.9/site-packages (from webdriver-manager) (2.28.1)
Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in ./opt/anaconda3/lib/python3.9/site-packages (from packaging->webdriver-manager) (3.0.9)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./opt/anaconda3/lib/python3.9/site-packages (from requests->webdriver-manager) (1.26.11)
Requirement already satisfied: charset-normalizer<3,>=2 in ./opt/anaconda3/lib/python3.9/site-packages (from requests->webdriver-manager) (2.0.4)
Requirement already satisfied: idna<4,>=2.5 in ./opt/anaconda3/lib/python3.9/site-packages (from requests->webdriver-manager) (3.3)
Requirement already satisfied: certifi>=2017.4.17 in ./opt/anaconda3/lib/python3.9/site-packages (from requests->webdriver-manager) (2022.9.24)
Note: you may need to restart the kernel to use updated packages.
Selenium 시작하기
Selenium을 사용하기 위해 우선 Selenium을 불러옵니다.
# selenium으로부터 webdriver 모듈을 불러옵니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
불러온 모듈 webdriver에서 Chrome() 객체를 생성합니다.
# http://www.example/com으로 요청을 보내봅니다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("http://www.example.com")
응답을 받은 후, page_source 속성을 통해 Response의 HTML 문서를 확인할 수 있습니다.
# page_source 속성을 확인해봅니다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("http://www.example.com")
print(driver.page_source)
<html><head>
<title>Example Domain</title>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body></html>
# with-as를 사용해서 위 코드를 다시 적어봅니다.
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("http://www.example.com")
print(driver.page_source)
<html><head>
<title>Example Domain</title>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 2em;
background-color: #fdfdff;
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
div {
margin: 0 auto;
width: auto;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body></html>
# By를 import해봅니다.
from selenium.webdriver.common.by import By
# p 태그를 해당하는 요소 하나를 찾아봅니다.
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("http://www.example.com")
for element in driver.find_elements(By.TAG_NAME, "p"):
print("Text:", element.text)
Text: This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.
Text: More information...
Wait and Call
- Wait을 이용해서 동적 웹 사이트를 성공적으로 스크래핑합니다.
Implicit/Explicit Wait
- Implicit Wait: 지정한 시간 동안 기다림
- Explicit Wait: 특정 요소에 대한 제약을 통한 기다림
class를 지정하면 스크래핑하기 용이해지기에 이를 방지하고자 랜덤화된 grid를 지정하는 경우가 많아졌습니다,
Target: IndieStreet 이벤트 스크래핑
사이트에 있는 행사의 이름들을 스크래핑 해봅니다: https://indistreet.com/live?sortOption=startDate%3AASC
# 스크래핑에 필요한 라이브러리를 불러옵니다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
XPath는 XML, HTML 문서 등의 요소와 위치를 경로로 표현하는 것을 의미합니다.
# 예시 사이트에 요청을 진행하고, 예시 사이트의 첫 번째 이벤트의 제목을 가져옵니다.
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]').text
# 10초동안 Implicit Wait을 진행하도록 해서 스크래핑이 잘 이루어지도록 수정해봅니다.
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.implicitly_wait(10)
print(driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]').text)
Sign up
Explicit Wait
until(): 인자의 조건이 만족될 때까지 until_not() 인자의 조건이 만족되지 않을 때까지
element = WebDriverWait(driver, 10). until(EC.presence_of_element_locater(By.ID, "target")))
from selenium.webdriver.support import expected_conditions as EC
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
# explicit wait으로 변경
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]')))
print(element.text)
Sign up
# 10개의 이름을 스크래핑하는 코드 작성
with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
driver.get("https://indistreet.com/live?sortOption=startDate%3AASC")
driver.implicitly_wait(10)
for i in range(1, 11): # 1~10
element =driver.find_element(By.XPATH, '//*[@id="__next"]/div/main/div[2]/div/div[4]/div[1]/div[2]/div/a/div[2]/p[1]'.format(i))
print(element)
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
<selenium.webdriver.remote.webelement.WebElement (session="796171469807ecd178b693fdae38d5a0", element="b530c5c7-fcdd-49e6-a414-545b0cd12eb6")>
'BOOTCAMP > 프로그래머스 인공지능 데브코스' 카테고리의 다른 글
[2주차 - Day5] 인공지능 수학 (0) | 2023.03.25 |
---|---|
[2주차 - Day4] 시각화로 결과 요약하기 - Seaborn (0) | 2023.03.24 |
[2주차 - Day2] 똑똑한 HTML 분석기 - BeautifulSoup4 (2) | 2023.03.21 |
[2주차 - Day1] HTTP 요청 주고받기 - Requests (0) | 2023.03.20 |
[1주차 - Day5] AWS를 활용한 인공지능 모델 배포 (0) | 2023.03.20 |
- Total
- Today
- Yesterday
- LV2
- 머신러닝
- Lv3
- EDA
- 파이썬
- 데이터 분석
- ML
- 데이터분석
- 딥러닝
- sql 테스트
- Kaggle
- lv4
- SQL
- 알고리즘
- 쿼리 테스트
- API
- 캐글
- 프로그래밍
- mysql
- SQLD
- 태블로
- 데이터사이언스
- 부스트코스
- LV1
- 데이터 시각화
- Python
- nlp
- 프로그래머스
- ai
- 인공지능
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |