▶ Selenium
- URL만으로 접근할 수 없는 홈페이지에 접근
- 크롤링이 목적이 아니라 만들어진 홈페이지를 테스트하고 웹 브라우저를 제어할 목적으로 사용
▶ 관련 패키지 설치
- pip install selenium
- pip install webdriver_manager
## webdriver 실행하기 ##
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
# 웹 드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
# 기 설치된 웹 드라이버 구동 방식
s = Service('c:\\DEV\\chromedriver\\chromedriver.exe') # 설치된 웹 드라이버의 경로를 지정
driver = webdriver.Chrome(service=s)
## find_element() 함수 ##
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
# 웹 드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(by=By.LINK_TEXT, value='카페')
print(ele)
print(type(ele))
print(ele.text)
▶ 이벤트 제어하기
# click()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
# 웹 드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(by=By.LINK_TEXT, value='카페') # 다음 홈페이지에 카페로 들어감
ele.click()
# send_keys()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
# 웹 드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(By.ID, 'q')
ele.send_keys('python') # 검색창에 'python' 검색
ele.send_keys(Keys.ENTER)
▶ selenium과 BeautifulSoup 연결하기
- 페이지의 내용을 자바스크립트를 이용해 동적으로 불러오는 경우에는 곧바로 BeautifulSoup을 이용할 경우 HTML 내용이 개발자 모드를 통해 보는 HTML 소소와 다를 수 있다.
- 이런 경우 selenium을 이용해서 페이지를 요청하고 sleep() 함수를 통해서 페이지가 로딩될 때까지 기다린 후 BeautifulSoup으로 스크래핑 한다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
# 웹 드라이버 동적 다운로드 방식
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.daum.net')
ele = driver.find_element(By.ID, 'q')
ele.send_keys('데이터 분석')
ele.send_keys(Keys.ENTER)
bs = BeautifulSoup(driver.page_source, 'lxml') # 웹 드라이버를 통해서 얻은 소스 코드를 가져옴
[실습] 네이버 로그인하기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.naver.com')
ele = driver.find_element(By.CLASS_NAME, 'MyView-module__link_login___HpHMW')
ele.click() # 간혹 click() 이벤트가 적용되지 않는 경우에는 send_keys(Keys.ENTER)를 이용
id = 'myid'
pw = 'mypw'
# ele = driver.find_element(By.ID, 'id')
# ele.send_keys(id)
# ele = driver.find_element(By.ID, 'pw')
# ele.send_keys(pw)
# 로봇에 의해 클릭되지 못하도록 막았기 때문에 스크립트로 처리하여 로그인해야 된다
driver.execute_script(f'document.getElementById("id").value="{id}"')
driver.execute_script(f'document.getElementById("pw").value="{pw}"')
ele = driver.find_element(By.CLASS_NAME, 'btn_login')
ele.click()
[실습] 구글에서 이미지 검색 후 스크래핑 하기
[step-1] 구글에서 이미지 검색 후 검색 결과 6번 스크롤 하기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 페이지가 로드될 때까지 기다리는 시간
SCROLL_PAUSE_TIME = 1
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.google.com')
ele = driver.find_element(By.CLASS_NAME, 'gLFyf')
ele.send_keys('python') # 검색창에 python 검색
ele.submit()
# 이미지 검색 결과로 이동
driver.find_element(By.LINK_TEXT, '이미지').click()
# 페이지가 로드될 때까지 기다림
time.sleep(SCROLL_PAUSE_TIME)
last_height = driver.execute_script('return document.body.scrollHeight') # 스크롤바의 높이
print('last height: ', last_height) # 3751
for i in range(6):
# 윈도우 창의 스크롤바를 0에서부터 가장 밑(scrollHeight값)까지 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
time.sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script('return document.body.scrollHeight')
print('new height: ', new_height)
print('-'*30)
# 더 이상 스크롤 될 페이지가 없을 경우 scrollHeight 값의 변화가 없다
last height: 3751
new height: 7874
------------------------------
new height: 15872
------------------------------
new height: 23386
------------------------------
new height: 30658
------------------------------
new height: 30739
------------------------------
new height: 30739
------------------------------
[step-2] 구글에서 이미지 검색 후 검색 결과 스크롤 한 후 '결과 더보기' 클릭하기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 페이지가 로드될 때까지 기다리는 시간
SCROLL_PAUSE_TIME = 1
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.google.com')
ele = driver.find_element(By.CLASS_NAME, 'gLFyf')
ele.send_keys('python') # 검색창에 python 검색
ele.submit()
# 이미지 검색 결과로 이동
driver.find_element(By.LINK_TEXT, '이미지').click()
# 페이지가 로드될 때까지 기다림
time.sleep(SCROLL_PAUSE_TIME)
last_height = driver.execute_script('return document.body.scrollHeight') # 스크롤바의 높이
# 스크롤 횟수
scroll_cnt = 0
while True:
# 윈도우 창의 스크롤바를 0에서부터 가장 밑(scrollHeight값)까지 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
scroll_cnt += 1
time.sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script('return document.body.scrollHeight')
print(f'last height:{last_height}, new height:{new_height}, scroll count:{scroll_cnt}')
if last_height != new_height: # 계속헤서 new_height 값이 변경 된다면...
last_height = new_height
else: # 더 이상 스크롤 될 페이지가 없으면...
ele = driver.find_element(By.CSS_SELECTOR, '#islmp > div > div > div > div > div.C5Hr4 > div.K414Oe > div.FAGjZe > input')
# 해당 element와 상호작용이 불가능한 상태면 ElementNotInteractableException 예외가 발생
try:
ele.click()
print('결과 더보기 클릭')
except:
break
[step-3] 구글에서 이미지 검색 후 검색 결과 스크롤 한 후 검색 결과 이미지의 src값(실제 이미지가 저장되어 있는 주소값) 수집하기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
from bs4 import BeautifulSoup
# 페이지가 로드될 때까지 기다리는 시간
SCROLL_PAUSE_TIME = 1
# 이미지 추출 개수
IMAGE_EXTRACT_NUM = 20
# 찾고싶은 키워드
SEARCH_KEYWORD = 'python'
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.google.com')
ele = driver.find_element(By.CLASS_NAME, 'gLFyf')
ele.send_keys('python') # 검색창에 python 검색
ele.submit()
# 이미지 검색 결과로 이동
driver.find_element(By.LINK_TEXT, '이미지').click()
# 페이지가 로드될 때까지 기다림
time.sleep(SCROLL_PAUSE_TIME)
# 스크롤바의 높이
last_height = driver.execute_script('return document.body.scrollHeight')
# 스크롤 횟수
scroll_cnt = 0
while True:
# 윈도우 창의 스크롤바를 0에서부터 가장 밑(scrollHeight값)까지 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
scroll_cnt += 1
time.sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script('return document.body.scrollHeight')
print(f'last height:{last_height}, new height:{new_height}, scroll count:{scroll_cnt}')
if last_height != new_height: # 계속헤서 new_height 값이 변경 된다면...
last_height = new_height
else: # 더 이상 스크롤 될 페이지가 없으면...
ele = driver.find_element(By.CSS_SELECTOR, '#islmp > div > div > div > div > div.C5Hr4 > div.K414Oe > div.FAGjZe > input')
# 해당 element와 상호작용이 불가능한 상태면 ElementNotInteractableException 예외가 발생
try:
ele.click()
print('결과 더보기 클릭')
except:
break
####### 이미지를 선택하고 해당 이미지의 src를 저장 #######
# 검색된 첫 번째 이미지 선택 : CSS_SELECTOR 값을 복사
imgs = driver.find_elements(By.CSS_SELECTOR, '#islrg > div.islrc > div a.FRuiCf.islib.nfEiy')
# div = 일종의 영역을 나타내는 태그
# a = 링크 태그 (원본이미지에 대한 접근이 가능)
print('이미지 개수: ', len(imgs))
img_cnt = 0
# 수집된 이미지의 src값을 리스트에 저장
img_src_list = []
for img in imgs:
img.send_keys(Keys.ENTER) # 또는 img.click()
# 검색 이미지 클릭 후 오른쪽에 크게 보여지는 원본 이미지의 CSS_SELECTOR 값을 수집
try: # try~except를 사용해서 CSS_SELECTOR 값이 다르면 넘어감
img_src = driver.find_element(By.CSS_SELECTOR, '#Sva75c > div.A8mJGd.NDuZHe.CMiV2d.OGftbe-N7Eqid-H9tDt > div.dFMRD > div.AQyBn > div.tvh9oe.BIB1wf.hVa2Fd > c-wiz > div > div > div > div.v6bUne > div.p7sI2.PUxBg > a > img').get_attribute('src') # src 속성값을 가져옴
except:
continue
if not img_src.startswith('http'): # 가지고 온 주소가 http로 시작하지 않으면 건너띔
continue
img_cnt += 1
print(f'[{img_cnt}].{img_src}')
img_src_list.append(img_src)
if img_cnt == IMAGE_EXTRACT_NUM: break # 20개가 되면 멈춤
[step-4] 구글에서 이미지 검색 후 검색 결과 스크롤 한 후 검색 결과 이미지의 src값(실제 이미지가 저장되어 있는 주소값) 수집후 이미지 파일로 저장하기
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
from bs4 import BeautifulSoup
# 페이지가 로드될 때까지 기다리는 시간
SCROLL_PAUSE_TIME = 1
# 이미지 추출 개수
IMAGE_EXTRACT_NUM = 20
# 찾고싶은 키워드
SEARCH_KEYWORD = 'python'
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=webdriver.ChromeOptions())
driver.get('https://www.google.com')
ele = driver.find_element(By.CLASS_NAME, 'gLFyf')
ele.send_keys('python') # 검색창에 python 검색
ele.submit()
# 이미지 검색 결과로 이동
driver.find_element(By.LINK_TEXT, '이미지').click()
# 페이지가 로드될 때까지 기다림
time.sleep(SCROLL_PAUSE_TIME)
# 스크롤바의 높이
last_height = driver.execute_script('return document.body.scrollHeight')
# 스크롤 횟수
scroll_cnt = 0
while True:
# 윈도우 창의 스크롤바를 0에서부터 가장 밑(scrollHeight값)까지 이동
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
scroll_cnt += 1
time.sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script('return document.body.scrollHeight')
print(f'last height:{last_height}, new height:{new_height}, scroll count:{scroll_cnt}')
if last_height != new_height: # 계속헤서 new_height 값이 변경 된다면...
last_height = new_height
else: # 더 이상 스크롤 될 페이지가 없으면...
ele = driver.find_element(By.CSS_SELECTOR, '#islmp > div > div > div > div > div.C5Hr4 > div.K414Oe > div.FAGjZe > input')
# 해당 element와 상호작용이 불가능한 상태면 ElementNotInteractableException 예외가 발생
try:
ele.click()
print('결과 더보기 클릭')
except:
break
####### 이미지를 선택하고 해당 이미지의 src를 저장 #######
# 검색된 첫 번째 이미지 선택 : CSS_SELECTOR 값을 복사
imgs = driver.find_elements(By.CSS_SELECTOR, '#islrg > div.islrc > div a.FRuiCf.islib.nfEiy')
# div = 일종의 영역을 나타내는 태그
# a = 링크 태그 (원본이미지에 대한 접근이 가능)
print('이미지 개수: ', len(imgs))
img_cnt = 0
# 수집된 이미지의 src값을 리스트에 저장
img_src_list = []
for img in imgs:
img.send_keys(Keys.ENTER) # 또는 img.click()
# 검색 이미지 클릭 후 오른쪽에 크게 보여지는 원본 이미지의 CSS_SELECTOR 값을 수집
try:
img_src = driver.find_element(By.CSS_SELECTOR, '#Sva75c > div.A8mJGd.NDuZHe.CMiV2d.OGftbe-N7Eqid-H9tDt > div.dFMRD > div.AQyBn > div.tvh9oe.BIB1wf.hVa2Fd > c-wiz > div > div > div > div.v6bUne > div.p7sI2.PUxBg > a > img').get_attribute('src') # src 속성값을 가져옴
except:
continue
if not img_src.startswith('http'): # 가지고 온 주소가 http로 시작하지 않으면 건너띔
continue
img_cnt += 1
print(f'[{img_cnt}].{img_src}')
img_src_list.append(img_src)
if img_cnt == IMAGE_EXTRACT_NUM: break # 20개가 되면 멈춤
####### 검색 이미지 파일로 저장 #######
import os
import requests
now = time.localtime() # 현재 시스템의 시간
path = 'c:/Temp/' # c드라이브 밑에 Temp 폴더를 만들어서 저장
folder_name = f'{now.tm_year}.{now.tm_mon}.{now.tm_mday}.{now.tm_hour}.{now.tm_min}.{now.tm_sec}'
directory = SEARCH_KEYWORD+'/'+folder_name+'/' # 검색 키워드마다 폴더가 만들어짐
os.chdir(path) # 경로 이동
if not os.path.exists(directory): # 폴더가 존재하지 않으면 새로 만들어줌
os.makedirs(directory)
file_no = 1 # 파일 번호
os.chdir(path+directory)
# 원본 이미지의 확장자를 먼저 확인, 없으면 임의로 붙여줌
for url in img_src_list: # 리스트에 있는 원본 url을 하나씩 가져옴
extension = url.split('.')[-1] # .으로 구분하고 가장 마지막에 있는 걸 가져옴 (확장자)
ext = ''
if extension in ['jpg', 'JPG', 'jpeg', 'JPEG', 'png', 'PNG', 'gif', 'GIF']:
ext = '.'+extension
else:
ext = '.jpg'
file_name = str(file_no)+'-'+SEARCH_KEYWORD+ext # 파일 번호는 정수형이기 때문에 문자열로 바꿔줌
file_no += 1
res = requests.get(url) # 원본 이미지의 url 요청
with open(file_name, 'wb') as f:
f.write(res.content)
driver.close() # 열려있는 웹브라우저를 닫아줌
'데이터 분석 > 웹 스크래핑' 카테고리의 다른 글
[Web Scrapping 실습] Crawling Test (0) | 2023.11.03 |
---|---|
[Web Scrapping] XPath (XML Path Language) (0) | 2023.11.01 |
[Web Scrapping 실습] BeautifulSoup (0) | 2023.11.01 |
[Web Scrapping] Selenium 모듈 (0) | 2023.11.01 |
[Web Scrapping] BeautifulSoup 모듈 (0) | 2023.10.31 |