728x90
728x90

BS4로도 충분히 원하는 정보를 추출할 수 있지만, 이에는한게가 있다.

자바스크립트로 동적으로 생성된 정보는 가져올 수 없다!

자바스크립트가 발전하며 , AJAX (비동기 통신) 형태로 서버와 통신을 주고받는 사이트가 많아졌고, 새로고침 없이 데이터를 가져오게 되었다. 자바스크립트가 동적으로 만든 데이터를 크롤링할때, 그리고 사이트의 다양한 HTML요소에 클릭, 키보드 입력 등 추가 이벤트를 주기 위해 Selenium을 사용한다.

셀레니움 기본 세팅을 해준다

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

셀레니움의 웹드라이버, 크롬 서비스, 옵션들을 가지고 와준다

from selenium.webdriver.chrome.service import Service

크롬 웹 브라우저를 실행하기 위한 WebDriver 서비스를 설정한다.

이는 실제 브라우저 인스턴스를 관리하고 제어한다

selenium.webdriver.chrome.options import Options

크롬 브라우저를 실행할 때 설정 옵션을 관리하기 위한 클래스 Options를 가져온다. 브라우저 동작을 커스터마이즈 할 수 있는 다양한 설정을 포함한다. 브라우저 창 크기, 브라우저 창 숨기기 등의 설정을 제어할 수 있다.

selenium을 사용하여 자동화하는 과정에서 필요한 초기 설정을 모두 마쳤으면, 뒤로 가보자

브라우저 종료 현상 방지

셀레니움 동작이 스레드를 통해 브라우저를 켜는 방식이라 프로세스가 종료되면 스레드가 종료되는데, 이걸 막기 위해서 브라우저 종료를 방지해주는 코드를 작성한다

chrome_options = Options()
chrome_options = add_expremental_option("detach", True)

만약에 이게 잘 안된다면 while을 사용해 프로세스가 종료되지 않게 하는 방법도 있다.

😋 웹 페이지 로딩을 기다리는 방법 3가지

  • time.sleep(초) : 물리적인 시간(초)를 기다리는 방법
  • implicity wait(초) : 웹 페이지가 로딩될때까지 기다리고 동작 실행 (기다리는 시간 넘어가면 그냥 실행)
  • ecplicitly wait(초): 명시적으로 어떤 조건이 성립할 때까지 기다린다(wait.until(조건)이 실행될떄까지 기다렸다가 다음 명령어를 실행하겠다!)

로딩 기다리기

driver.implicitly_wait(5)
driver.maximize_window()

로그인 페이지로 접속해 5초동안 로딩을 기다리고, 창을 켜주는 역할을 한다. 두번쨰 줄은 창을 전체화면으로 바꿔준다.

링크 연결하기

driver.get("<https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/>")

나는 네이버 로그인 실습을 할 것이기 때문에 네이버 로그인 사이트를 연결해주었다 !

아이디 입력하기

원래는 그냥 해보려고 하였지만 CAPCHA를 피하기 위해 pyperclip을 사용해보기로 하였다.

복사 붙여넣기를 하면 자동입력 방지에 안 걸릴 것 같다는 생각이 들었다. 사실 이전에 대기시간을 충분히 주면 되겠지? 하는 생각이 있었는데 대기시간을 아무리 줘도 다 걸리더라 ;;;;

id= driver.find_element(By.CSS_SELECTOR, "#id")
id.click()
pyperclip.copy('insidepixce')
id.send_keys(Keys.CONTROL,'v')
time.sleep(2)

driver.find_element(By.CSS_SELECTOR, "#id") 를 통해 ID 입력창을 찾고, 입력창을 클릭해준다.

근데 … 여기서 파이퍼클립이 안 먹었다 ! 아니 세상에…

그래서 방향을 틀었다.

스택오버플로우 선생님들 ! 제게 힘을 주세요 !!!!!!

🙋🏻‍♀️ CAPCHA 우회하는 거 불법인가요? 불법 아니면 어케 뚧나요?

💁🏻 우회하는 거 불법 맞음 ㅇㅇ 2capcha 사용하면 우회 가능. 결제하면 우회 가능함 ㅇㅇ

하. 캡챠 우회가 불법이였다니. 그러면 일단 자동으로 비밀번호와 아이디가 입력된다는 기능에 초점을 두자!! 는 방향으로 코드를 써보기 시작했다.

좀 더 깔끔하게 ! 좀 더 가독성이 높게 ! 좀 더 확실하게 !

⌨️ 뒤집어 엎자! 코드!

불러올 것들

from selenium.webdriver import Chrome, ChromeOptions, Keys
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time

셀레니움 기본 설정들과 쓸 것들을 불러와준다.

크롬 옵션 설정하기

chrome_options = ChromeOptions()
chrome_options.add_argument("--start-maximized")
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])

--start-maximized : 크롬 브라우저 실행할 때 창을 최대화하여 연다. 전체화면이라고 생각하면 편하다. 원래 이거 설정 안 해주면 창 모드로 뜬다 ;;

add_experimental_option("excludeSwitches", ["enable-automation"] : 원래는 크롬 브라우저 자동화 감지해서 컷한다. 셀레니움을 사용할때 일부 웹사이트에서 자동화를 감지해서 접금제한 때릴 떄가 있는데… 이 옵션 켜서 막을 수 있다.

웹드라이버 조건 설정

driver = Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)

저번처럼 경로 설정해주고 뭐고 하기 싫어서 그냥 웹드라이버 설치해버렸당.

아까 정한 옵션도 넣어주었다 .

웹드라이버 초기화

이거 되게 까다로웠다 ;;;;

Implicitly_wait(5)랑 WebDriverWait 중 무엇을 쓸지 고민하다 그냥 한 곳에 다 때려박아 보았다.

wait = WebDriverWait(driver, 10)
driver.implicitly_wait(5)
driver.maximize_window()

wait = WebDriverWait(driver, 10)로 최대 10초를 가디려준다. 웹이 로딩될때까지 기다려준다. 우리가 가져올 요소들이 바로 안 나타날때 쓴다.

그럼 driver.implicitly_wait(5) 이건 뭐냐?

implicitly_wait을 사용하여 일반적인 요소 찾기에 대한 대기 시간을 갖고, **WebDriverWait**를 사용하여 특정 조건을 충족할 때까지 대기한다. 복잡하다. 전자는 대기하는 객체를 ‘생성' 하는거고. 후자는 대기하는 암묵적 대기 시간을 ‘설정’한다의 차이가 있다. 후자로 동적으로 로딩되는 경우를 처리하고 완전히 로딩 안 되어도 바로바로 쓸 수 있게 된다.

→하나만 써도 되는데, implicitly_wait만 쓸 경우 모든 요소에 똑같은 대기 시간이 적용되었다 ! 어떤게 로딩 안 된 경우에는 너무 오래 걸렸다.

브라우저 종료 현상 방지

chrome_options = ChromeOptions()
chrome_options.add_experimental_option('detach', True)

갈아엎기 전에도 넣어주었던 코드이다 !

셀레니움 동작이 스레드를 통해 브라우저를 켜는 방식이라 프로세스가 종료되면 스레드가 종료되는데, 이걸 막기 위해서 브라우저 종료를 방지해주는 코드를 작성한다 (설명 재탕😂)

크롬 드라이버로 열기

driver.get("<https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/>")

드라이버로 사이트를 열어주자

아이디 입력 필드 찾고 로드될때까지 기다린 다음 아이디 입력

username = wait.until(EC.presence_of_element_located((By.ID, 'id')))
username.send_keys('insidepixce')  
time.sleep(10)

웹 페이지가 로드될 때까지 기다렸다가 아이디 입력창을 찾아 아이디를 입력한다. 이후 10초 동안 기다린다.

비밀번호 입력 필드 찾고 로드될때까지 기다린 다음 비밀번호 입력

password = wait.until(EC.presence_of_element_located((By.ID, 'pw')))
password.send_keys('mypassword')
time.sleep(10)

웹 페이지가 로드될 때까지 기다렸다가 비밀번호 입력창을 찾아 비밀번호를 입력한다. 이후 10초 동안 기다린다.

뭔 대기가 이렇게 많아… 하는데 다 로드되었는지 확인하고 확인하고 확인하고 또 확인하는 과정이다.

엔터키 누르고 로그인 폼 submit 하기

password.send_keys(Keys.ENTER)
input()

원래는 로그인 버튼을 클릭하려고 했는데 엔터가 더 효율이 좋은 것 같았다 ;

저놈의 input()을 꼭 써줘야 페이지가 바로 안 닫힌다. 성빈이(바보멍청이흰둥이)가 먼저 공부했던 내용이여서 바로 닫힌다고 찡찡대며 물어봤는데, 인풋() 이거 한 번 적으니까 바로 해결되었다 ; 아 킹받아. 도대체 왜 이러는 걸까?

→ 서치하고 서치하고 서치해보니 ‘프로그램이 종료되지 않고 계속 실행되도록 한다’ 이게 맞았다… 디버깅 목적으로 사용된다고 한다. 프로그램이 실행되고 웹 브라우저를 제어하여 특정 작업을 수행하고 바로 종료 안되게 막아준다 ! 이말인거다… 입력 기다리는 동안 프로그램이 계속 실행되니 개발자가 결과를 확인할 떄 자주 쓴다고 한다.

예를 들어 웹 브라우저가 로그인을 시도하고 나서 사용자에게 다음으로 뭘 할건지 물어본다는 것이다. 실제 환경ㅇ에서는 사용 안 하거나, 임시로 사용된다고 한다.

정상적으로 작동할때는 이거 수정해서 굳이 실행할 필요가 없는 입력 대기 없애는 게 맞다 !


이렇게 모든 과정을 완료하고 실행해 보았더니…

이렇게 로그인이 되고 ,,,

이딴 자동입력 방지창이 나오긴 했지만 그래도 나름 성공한 것 같았다! 어질어질하다… 솔직히 셀레니움으로 해보고 싶은게 너무 많아서 고민이다.

 

‘스크래핑’과 ‘자동화’ 부분이 나한테 너무 잘 맞는다. 딥러닝 쪽으로 가야할까…하다가도 내가 너무 그쪽 분야를 쉽게 생각하는 것 같아 실례가 될까봐 무섭다 ;; 해보고 싶은게 많다. 사실 내가 만들겠다고 설치고 다녔던 ‘야구 시뮬레이터’ 도 결국 bs4를 사용해서 진행했으니까. 저번처럼 키워드 분석하는 스크래핑도 재밌었는데 자동화는 진짜진짜 진짜 더 재밌다 ;;;

CAPCHA 우회 방법이 있다고 스택오버플로우에서 듣기는 했는데… 유료고 무엇보다는 아직 그것을 써먹을만한 프로젝트를 찾지 못했다는 것이다. 좀 더 전문적인 프로젝트를 진행하게 된다면 그거 구매해서 사용해봐도 짱 좋을 것 같다!

이미 정보보안을 위주로 공부하겠다고 마음 먹었고, 구름 정보보안 과정도 신청해놓은 상태기에, 정보보안 위주로 공부하다 OSINT 기법을 공부하기 위해 셀레니움(셀리늄?)을 공부하고 있기는 하지만 나중에 시간이 된다면 좀 더 깊게 공부해보고 싶다 !

내일 공부도 Selenium으로 해야 할지, 아니면 슬슬 Bs4로 넘어가서 공부해도 될지는 모르겠다 ;

728x90
300x250
728x90
728x90

Selenium을 맛봤으니 이제는 실습을 해야 할 차례이다.

Selenium은 다양한 웹 브라우저를 조작할 수 있는 라이브러리이다. 이 때, Selenium이 웹 브라우저를 조작하기 위해서는 각 브라우저마다 해당 브라우저를 제어할 수 있는 드라이버가 필요한데, Chrome 웹 브라우저를 조작하기 위해서는 ChromeDriver가 필요하다. 따라서, Selenium을 사용하기 위해서는 ChromeDriver를 다운로드하여 설치해야 한다.

셀레니움은 다양한 언어로 사용할 수 있는데, 자바, 파이썬 등에서 가장 많이 사용된다.

험난했던 chrome web browser 버전 맞추기

이전에 (한참 전…) 에 selenium을 찍먹했을 때는 https://chromedriver.chromium.org/downloads 이곳에서 크롬 웹브라우저를 설치할 수 있었다. 내가 다시 접한 자료들에서도 이곳에서 다운받으라고 하기에 내 크롬 버전이 뭔지도 모르고 가장 최신이라는 94.0.4606.41 을 설치했는데…

계속되는 오류에 지쳐가던 중 내가 사용하는 크롬 버전이 115버전이라는 걸 알게되었다.

https://googlechromelabs.github.io/chrome-for-testing/

크롬드라이버 115.0.5790.170은 여기서 다운받을 수 있다. STATUS가 X로 되어있는 경우도 있는데 이러면 안된다는거다 ;; 기다려야지 뭐

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

chromedriver_path = "/Users/inseoulmate/Downloads/chromedriver-mac-arm64/chromedriver"
service = Service(chromedriver_path)
driver = webdriver.Chrome(service=service)

driver.get("<https://www.genie.co.kr/chart/top200>")

wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "list-wrap")))

chart_items = driver.find_elements(By.CSS_SELECTOR, ".list-wrap > tbody > tr.list")

for item in chart_items:
    rank = item.find_element(By.CLASS_NAME, "number").text
    title = item.find_element(By.CSS_SELECTOR, ".info .title").text
    artist = item.find_element(By.CSS_SELECTOR, ".info .artist").text

    print(f"{rank}. {title} - {artist}")

# 셀레니움 웹 드라이버 종료
driver.quit()

먼저 코드 전문이다

1. 필요한 것 불러와주기

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Selenium 라이브러리 자체를 임포트해준다.

webdriver : 웹 드라이버를 제어학디 위한 모듈이다. 웹 드라이버는 브라우저를 제어하고 웹 페이지에 엑세스하는데 사용된다.

Service : 웹 드라이버를 실행시키는 데 필요한 서비스를 관리하는 클래스이다. 특정 드라이버를 실행하기 위해 사용된다.

By: 웹 요소를 찾는 방법을 지정하기 위한 클래스이다. By.CLASS_NAME, By.CSS_SELECTOR, 등과 같은 방법을 사용하여 웹 요소를 식별한다.

WebdriverWait : 웹 드라이버를 통해 웹 페이지가 특정 조건을 만족할 때까지 기다리기 위한 클래스이다. 웹 요소의 출현이나 속성 등을 기다리는 데 사용된다 .

expected_conditions : 웹 요소가 특정 조건을 만족하는지 확인하기 위한 클래스이다

EC.presence_of_element_located , EC.visibility_of_element_located 등과 같은 조건을 사용했다.

2. 크롬 드라이버 설정해주기

chromedriver_path = "/Users/inseoulmate/Downloads/chromedriver-mac-arm64/chromedriver"
service = Service(chromedriver_path)
driver = webdriver.Chrome(service=service)

크롬드라이버가 어디 있는지도 찾아야 한다. 이거 찾느라 꽤나 오래 걸렸다. 보통 다운로드에 있다.

절대경로를 복사해서 붙여넣어주면 된다 .

3. 링크 연결하기

driver.get("<https://www.genie.co.kr/chart/top200>")

다음 나는 지니뮤직의 1위부터 100위까지를 스크래핑할거기에 차트 링크를 넣어주었다.

4. 정보 스크래핑하고 변수에 저장하고 출력하기

wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.CLASS_NAME, "list-wrap")))
chart_items = driver.find_elements(By.CSS_SELECTOR, ".list-wrap > tbody > tr.list")

for item in chart_items:
    rank = item.find_element(By.CLASS_NAME, "number").text
    title = item.find_element(By.CSS_SELECTOR, ".info .title").text
    artist = item.find_element(By.CSS_SELECTOR, ".info .artist").text

드라이버 객체를 최대 10초까지 기다리며, 해당 시간 내에 “list-wrap” 클래스가 웹페이지에 나타날 떄까지 기다린다. 이 요소는 음악 차트 목록을 감싸는 부모 요소이다 .

BY.CSS_SELECTOR를 사용해 CSS선택자를 이용하여 해당 요소들을 찾고 반복문을 실행해주었다. 이후 item.find_element를 사용하여 요소 내에서 순위, 제목 및 아티스트 정보를 해당 요소들에서 찾아낸다. 이 정보들은 ‘rank’ , ‘title’, ‘artist’ 변수에 저장된다.

나머지는 print 함수를 이용해 출력하는것과 , 드라이버를 종료하는 것으로 마무리된다.

 

이렇게 잘 출력되었다. 개인적으로 뉴진스-ETA 노래 너무 좋다. 안 들어본 사람 있으면 꼭 들어봤으면 좋겠다.

728x90
300x250

+ Recent posts