본문 바로가기
오토핫키

Rufaydium 공식문서[한글번역]

by 일등미노왕국 2024. 8. 10.

 

Rufaydium

AutoHotkey WebDriver 라이브러리로 브라우저와 상호작용합니다. Rufaydium은 WebDriver 세션을 생성하는 동안 최신 WebDriver를 자동으로 다운로드하고 브라우저 버전에 따라 WebDriver를 업데이트합니다.

지원되는 브라우저: Chrome, MS Edge, Firefox, Opera.

포럼: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=102616

Rufaydium은 https://www.w3.org/TR/webdriver2/ 의 W3C REST API를 활용하며 chrome.ahk와 같은 Chrome Devtools 프로토콜도 지원합니다.

Note:

Selenium을 설치/설정할 필요가 없습니다. Rufaydium은 AHK의 Selenium이며 Selenium보다 더 유연합니다.

How to use

#Include Rufaydium.ahk  ; Rufaydium 라이브러리를 포함시킵니다.

/*
"A_ScriptDir"에서 "chromedriver.exe"를 로드합니다.
드라이버가 아직 사용 가능하지 않은 경우, 드라이버를 시작하기 전에
"A_ScriptDir"에 "chromedriver.exe"를 다운로드합니다.
*/
Chrome := new Rufaydium("chromedriver.exe")  ; Chrome 웹드라이버 인스턴스를 생성합니다.

f1::  ; F1 키를 누르면 실행됩니다.
/*
웹 브라우저 버전이 웹드라이버 버전과 일치하는 경우 새 세션을 생성합니다.
호환되는 웹드라이버가 없으면 다운로드를 요청합니다.
*/
Page := Chrome.NewSession()  ; 새로운 Chrome 세션을 생성합니다.
; URL로 이동합니다.
Page.Navigate("https://www.autohotkey.com/")  ; AutoHotkey 공식 웹사이트로 이동합니다.
return

f12::  ; F12 키를 누르면 실행됩니다.
Chrome.QuitAllSessions()  ; 모든 Chrome 세션을 종료합니다.
Chrome.Driver.Exit()  ; 그 다음 Chrome 드라이버를 종료합니다.
return

New Rufaydium(DriverName,Parameters)

Rundriver() 클래스가 Rufaydium.ahk에 통합되어 백그라운드에서 드라이버를 실행하며 포트 9515가 기본값으로 설정됩니다.

; Chrome 웹드라이버 인스턴스 생성
Chrome := new Rufaydium()  ; "chromedriver.exe"가 기본 드라이버 이름이므로 Chrome 드라이버를 다운로드/로드합니다.

; Microsoft Edge 웹드라이버 인스턴스 생성
MSEdge := new Rufaydium("msedgedriver.exe","--port=9516")  ; MS Edge 드라이버를 다운로드/로드하고, 통신 포트를 9516으로 설정합니다.

; Firefox 웹드라이버 인스턴스 생성
Firefox := new Rufaydium("geckodriver.exe")  ; Firefox용 geckodriver를 다운로드/로드합니다.

; Opera 웹드라이버 인스턴스 생성
Opera := new Rufaydium("operadriver.exe")  ; Opera용 operadriver를 다운로드/로드합니다.

참고:

  1. 드라이버는 A_ScriptDir에 다운로드되며 이전 드라이버는 A_ScriptDir "\Backup"으로 이동됩니다.
  2. 포트가 사용 중이면 드라이버가 실행되지 않습니다. 동일한 포트로 다른 드라이버를 실행하지 않도록 주의하세요. 예: 같은 포트로 Chromedriver와 Edgedriver를 실행하려고 시도하는 경우.

Driver Default port

Rufaydium은 현재 4개의 WebDriver를 지원하며 하나의 기본 포트를 가지고 있습니다. 포트가 이미 사용 중이면 실행되지 않습니다. 드라이버 매개변수를 사용하여 별도의 포트로 드라이버를 실행하거나, 이미 실행 중인 드라이버를 종료하고 동일한 포트를 사용하려면 다른 드라이버를 실행해야 합니다.

Rufaydium은 이 충돌을 해결하기 위해 모든 드라이버에 대해 기본 포트를 가지고 있습니다:

Driver Name	Ports
chromedriver	9515
msedgedriver	9516
geckodriver	9517
operadriver	9518
unknownDriver	9519
bravedriver	9515

참고: BraveDriver 매개변수는 chromedriver를 다운로드하지만 Brave 브라우저 설정에 특화된 별도의 BraveCapabailities 클래스를 사용합니다.

Driver Parameters

매개변수는 WebDriver.exe CMD 인수입니다.

옵션은 다른 드라이버에 따라 다를 수 있으며 이러한 인수를 확인할 수 있습니다.

; 드라이버의 도움말 정보를 클립보드에 복사하고 메시지 박스로 표시합니다.
MsgBox, % Clipboard := RunDriver.help(Driverexelocation)

; 위의 MsgBox는 chromedriver를 사용할 경우 다음과 같은 정보를 반환합니다:
/*
사용법: chromedriver.exe [옵션]
옵션
  --port=PORT                     리스닝할 포트 지정
  --adb-port=PORT                 ADB 서버 포트 지정
  --log-path=FILE                 서버 로그를 stderr 대신 파일에 작성, 로그 레벨을 INFO로 증가
  --log-level=LEVEL               로그 레벨 설정: ALL, DEBUG, INFO, WARNING, SEVERE, OFF
  --verbose                       상세 로깅 (--log-level=ALL과 동일)
  --silent                        로깅 안 함 (--log-level=OFF와 동일)
  --append-log                    로그 파일을 새로 작성하지 않고 추가
  --replayable                    (실험적) 상세 로깅 및 긴 문자열 잘림 방지로 로그 재생 가능
  --version                       버전 번호 출력 후 종료
  --url-base                      명령어용 기본 URL 경로 접두사, 예: wd/url
  --readable-timestamp            로그에 읽기 쉬운 타임스탬프 추가
  --enable-chrome-logs            브라우저의 로그 표시 (다른 로깅 옵션 무시)
  --allowed-ips=LIST              ChromeDriver에 연결 허용된 원격 IP 주소 목록 (쉼표로 구분)
  --allowed-origins=LIST          ChromeDriver에 연결 허용된 요청 출처 목록 (쉼표로 구분). '*'를 사용하여 모든 호스트 출처 허용은 위험함!
*/

드라이버 CMD 창 숨기기/표시하기

; Chrome 웹드라이버의 새 인스턴스를 생성합니다.
Chrome := new Rufaydium()

; Chrome 드라이버의 명령 프롬프트 창을 표시합니다.
Chrome.Driver.visible := true  ; 드라이버 창을 보이게 합니다.

; Chrome 드라이버의 명령 프롬프트 창을 숨깁니다.
Chrome.Driver.visible := false  ; 드라이버 창을 숨깁니다.

Script reloading

스크립트를 원하는 만큼 다시 로드할 수 있지만, 드라이버는 프로세스에서 활성 상태로 유지되므로 지금까지 WebDriver를 통해 생성된 모든 세션을 계속 제어할 수 있습니다. 드라이버 프로세스를 닫을 수도 있지만, 이는 WebDriver를 통해 생성된 세션에 더 이상 접근할 수 없게 되므로 문제가 발생할 수 있습니다. Session.exit()을 사용한 다음 Chrome.Driver.Exit()을 사용하는 것이 좋습니다.

; 포트 10280을 사용하여 chromeDriver.exe를 다운로드하고 실행합니다.
Chrome := new Rufaydium("chromedriver.exe","--port=10280")
; 이 라인은 다음과 같은 작업을 수행합니다:
; 1. "chromedriver.exe"가 없으면 다운로드합니다.
; 2. 드라이버를 실행하면서 10280 포트를 사용하도록 지정합니다.
; 3. Rufaydium 객체를 생성하여 Chrome 변수에 할당합니다.

; 드라이버를 종료합니다.
Chrome.Driver.Exit()
; 이 메소드는 현재 실행 중인 ChromeDriver 프로세스를 종료합니다.
; 모든 관련 브라우저 세션도 함께 종료됩니다.

; 드라이버를 종료하고 Driver.exe 파일을 삭제합니다.
Chrome.Driver.Delete()
; 이 메소드는 다음 작업을 수행합니다:
; 1. 현재 실행 중인 ChromeDriver 프로세스를 종료합니다.
; 2. 디스크에서 "chromedriver.exe" 파일을 삭제합니다.
; 주의: 이 작업 후에는 새로운 세션을 시작하기 위해 드라이버를 다시 다운로드해야 할 수 있습니다.

Driver Status

; Chrome 웹드라이버의 새 인스턴스를 생성합니다.
Chrome := new Rufaydium()

; Chrome 드라이버의 현재 상태를 메시지 박스로 표시합니다.
msgbox, % " Chrome.Status()

; Chrome 드라이버와 운영 체제에 대한 상세 정보를 메시지 박스로 표시합니다.
msgbox, % ".Build.Version : " Chrome.Build.Version    ; Chrome 드라이버의 빌드 버전
.    "`n.OS Name : " Chrome.OS.Name                   ; 운영 체제 이름
.    "`n.OS.Arch : " Chrome.OS.Arch                   ; 운영 체제 아키텍처 (예: 32비트 또는 64비트)
.    "`n.OS.Version : " Chrome.OS.Version             ; 운영 체제 버전
.   "`n.Message : " Chrome.Message                    ; 드라이버로부터의 메시지 (있는 경우)
.   "`n.Ready : " Chrome.Ready                        ; 드라이버가 사용 준비가 되었는지 여부 (true/false)

Driver Location

특정 드라이버(예: chromedriver)가 이미 실행 중이고 특정 포트를 사용하고 있다면, Rufaydium은 주어진 위치를 무시하고 해당 드라이버(예: chromedriver)에 접근하며 올바른 프로세스 위치를 Driver.Location으로 업데이트합니다.

; D 드라이브에 있는 chromedriver.exe를 사용하여 포트 9555로 Chrome 드라이버의 첫 번째 인스턴스를 생성합니다.
Chrome1 := new Rufaydium("D:\chromedriver.exe","--port=9555")

; E 드라이브에 있는 chromedriver.exe를 지정하지만, 실제로는 이미 실행 중인 드라이버(포트 9555)에 접근합니다.
Chrome2 := new Rufaydium("E:\chromedriver.exe","--port=9555") ;이미 실행 중인 드라이버에 재접근

; 첫 번째 Chrome 드라이버 인스턴스의 실제 위치를 가져옵니다.
L1 := Chrome1.Driver.Location

; 두 번째 Chrome 드라이버 인스턴스의 실제 위치를 가져옵니다 (이는 첫 번째와 동일할 것입니다).
L2 := Chrome2.Driver.Location

; 두 드라이버의 위치가 동일하다는 것을 보여주는 메시지 박스를 표시합니다.
Msgbox, L1 "`n" L2 "두 위치 모두 하나의 드라이버 프로세스와 포트를 통해 접근됩니다"

Handling Multiple Driver

단일 드라이버 프로세스에서 여러 세션을 생성하는 것이 좋습니다. Rufaydium은 여러 드라이버 실행 파일도 처리할 수 있습니다. 다음 예제에서 Chrome2와 chrome3는 동일한 chromedriver.exe를 공유하지만 chrome1은 다른 위치와 다른 포트에서 실행됩니다.

; 데스크톱에 있는 chromedriver.exe를 사용하여 포트 9226으로 Chrome 드라이버의 첫 번째 인스턴스를 생성합니다.
Chrome1 := new Rufaydium(A_desktop "\chromedriver.exe","--port=9226")

; 기본 설정으로 Chrome 드라이버의 두 번째 인스턴스를 생성합니다.
Chrome2 := new Rufaydium()

; 세 번째 Chrome 드라이버 인스턴스를 생성하지만, 실제로는 이미 존재하는 드라이버에 접근합니다.
Chrome3 := new Rufaydium() ; 기존 드라이버에 재접근

; 세 드라이버 인스턴스의 정보를 메시지 박스로 표시합니다.
msgbox, % "Driver 1 Name :" Chrome1.Driver.Name
.       "`nDriver 1 Port :" Chrome1.Driver.Port
.       "`nDriver 1 Dest :" Chrome1.Driver.Location
.       "`nDriver 2 Name :" Chrome2.Driver.Name
.       "`nDriver 2 Port :" Chrome2.Driver.Port
.       "`nDriver 2 Dest :" Chrome2.Driver.Location
.       "`nDriver 3 Name :" Chrome2.Driver.Name
.       "`nDriver 3 Port :" Chrome2.Driver.Port
.       "`nDriver 3 Dest :" Chrome2.Driver.Location

; Chrome1의 상태를 표시하고, 확인을 누르면 Chrome1 드라이버를 종료합니다.
msgbox, % Chrome1.status() "`n`nPress Ok to close drive Drive from Chrome1"
Chrome1.Driver.Exit() ; 드라이버를 종료합니다

; Chrome2의 상태를 표시하고, 확인을 누르면 Chrome2 드라이버를 종료합니다.
msgbox, % Chrome2.status() "`n`nPress Ok to close drive Drive from Chrome2"
Chrome2.Driver.Exit() ; 드라이버를 종료합니다

; 아래 두 줄은 주석 처리되어 있습니다. Chrome3가 Chrome2와 동일한 드라이버를 사용하므로 오류가 발생할 수 있습니다.
; Chrome3.status() "`n`nthis will cause error as Chrome2 and Chrome3 were same Diver executable"
; Chrome3.Driver.Exit() ; already exited with chrome2

Capabilities Class

'New Rufaydium()' 후에 Capabilities에 접근하고 사용할 수 있습니다.

Rufaydium은 지정된 드라이버에 따라 드라이버 Capabilities를 로드합니다.

세션을 생성하기 전에 capabilities를 변경합니다.

; 기본 Capabilities로 Chrome 드라이버를 로드하는 Rufaydium 인스턴스를 생성합니다.
Chrome := new Rufaydium() ; 기본 Capabilities로 Chrome 드라이버를 로드합니다.

; Chrome의 기본 사용자 프로필을 사용하도록 설정합니다.
Chrome.capabilities.setUserProfile("Default") ; 기본 사용자 프로필을 사용할 수 있습니다.

; 사용자 프로필의 데이터 디렉토리를 변경합니다.
; 주의: "D:\Profile Dir\Profile 1" 경로가 실제로 존재해야 합니다.
Chrome.capabilities.setUserProfile("Profile 1","D:\Profile Dir\")

; 위에서 설정한 Capabilities에 따라 새 세션을 생성합니다.
Session := Chrome.NewSession()

Enable HeadlessMode

이것은 HeadlessMode를 설정하고 가져옵니다.

Browser.capabilities.HeadlessMode := true
MsgBox, % Browser.capabilities.HeadlessMode

Enable Incognito Mode

이것은 시크릿 모드를 설정하고 가져옵니다.

Browser.capabilities.IncognitoMode := true
MsgBox, % Browser.capabilities.IncognitoMode

참고: IncognitoMode := true 설정 후에는 .setUserProfile()이 작동하지 않습니다.

UserPrompt

사용자 프롬프트 핸들러는 UserPrompt를 사용하여 할당할 수 있으며, 브라우저 알림/메시지의 처리 절차를 결정합니다.

다음 매개변수가 허용됩니다

KeywordStateDescription

dismiss Dismiss state All Alert prompt should be dismissed.
accept Accept state All Alert prompt should be accepted.
dismiss and notify Dismiss and notify state All Alert prompt should be dismissed, and an error returned that the dialog was handled.
accept and notify Accept and notify state All Alert prompt should be accepted, and an error returned that the dialog was handled.
ignore Ignore state All Alert prompt should be left to the user to handle.
MsgBox, % Browser.capabilities.UserPrompt ; default useprompt is dismiss
Browser.capabilities.UserPrompt := "ignore"

Enable CrossOriginFrame

이것은 CrossOriginFrame 접근을 설정하고 가져옵니다.

Browser.capabilities.useCrossOriginFrame := true
MsgBox, % Browser.capabilities.useCrossOriginFrame

Setting / Removing Args

Chrome을 시작할 때 사용할 명령줄 인수입니다. 여기를 참조하세요.

Chrome := new Rufaydium()
Chrome.capabilities.addArg("--headless")
Chrome.capabilities.RemoveArg("--headless")

Binary

Chromium 기반 브라우저도 로드할 수 있습니다. 예를 들어, Brave 브라우저는 chromium 기반이며 ChromeDriver를 사용하여 제어할 수 있습니다. SetBinary는 NewSession(binary_location) 메서드에 병합되었습니다.

other methods

Chrome := new Rufaydium()
; capabilities 메서드로 포함된 대부분의 옵션은 여기에 정의되어 있습니다 <https://chromedriver.chromium.org/capabilities#h.p_ID_106>
Chrome.capabilities.Addextensions(extensionloaction) ; 확장 프로그램을 로드합니다
Chrome.capabilities.AddexcludeSwitches("enable-automation") ; 기본 args 없이 Chrome을 로드합니다
Chrome.capabilities.DebugPort(9255) ; debuggerAddress의 포트를 변경합니다

SetTimeouts

타임아웃은 어느 레벨/시간/장소에서든 정의할 수 있습니다.

Browser := new Rufaydium(driver,params)
ResolveTimeout := ConnectTimeout := SendTimeout := ReceiveTimeout := 3 * 1000
Broswer.SetTimeouts(ResolveTimeout, ConnectTimeout, SendTimeout, ReceiveTimeout)

Settimeouts에 대해 읽어보세요

Rufaydium Sessions

New Session

capabilities를 설정한 후 세션을 생성합니다.

capabilities를 건너뛸 수 있습니다. 세션은 사용된 드라이버를 기반으로 기본 Capabilities를 로드할 것입니다. 기본 Capabilities는 모든 드라이버에서 작동해야 합니다.

참고: WebDriver 버전이 브라우저 버전과 일치하지 않는 경우, Rufaydium은 드라이버 업데이트를 요청하고 WebDriver를 자동으로 업데이트한 다음 새 드라이버를 로드하고 세션을 생성합니다.

이 기능은 현재 Chrome 및 MS Edge 웹 브라우저에 대해 지원됩니다.

Chrome := new Rufaydium("chromedriver.exe")
Session := Chrome.NewSession()

Using WebDriver with different Browsers

Brave는 chromedriver.exe를 사용합니다. 간단히 Browser.exe(참조된 바이너리)를 NewSession() 메서드에 전달하면 됩니다.

Brave := new Rufaydium() ; Brave 브라우저는 chromedriver.exe를 지원합니다
; Brave 브라우저를 사용하여 새 세션이 생성됩니다
Session := Brave.NewSession("C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe")
Brave.Session() ; 재설정할 때까지 항상 새로운 Brave 세션을 열 것입니다
Brave.Capabilities.Resetbinary() ; 바이너리를 드라이버 기본값으로 재설정합니다
Brave.Session() ; Chrome 드라이버를 로드했으므로 Chrome 세션을 생성할 것입니다

이렇게 모든 Chromium 기반 브라우저를 로드할 수 있습니다

Getting Existing Sessions

이전에 생성된 세션에 제목이나 URL을 사용하여 접근할 수도 있습니다.

Msgbox, % json.dump(Chrome.Sessions()) ; 모든 Webdriver 세션 세부 정보를 반환합니다

Session := Chrome.getSession(1) ; 첫 번째로 생성된 것부터 최근에 생성된 순서로 번호가 매겨진 세션을 반환하고 활성 탭으로 전환합니다

Session := Chrome.getSession(1,2) ; 첫 번째 세션을 반환하고 두 번째 탭으로 전환합니다. 탭은 왼쪽에서 오른쪽으로 계산됩니다
Session := Chrome.getSessionByUrl(URL)
Session2 := Chrome.getSessionByTitle(Title)

참고: 위의 메서드들은 W3C 표준이 아닌 httpserver\\sessions 명령을 기반으로 합니다. Rufaydium은 AHK의 함수 ReadIni, WriteIni & DeleteIni를 사용하여 GeckoDriver 위치에 ActiveSessions.ini를 생성하여 세션 ID를 저장하고 파싱합니다. 따라서 getSessionByUrl() & getSessionByTitle()은 이제 Firefox 세션도 지원합니다. 이렇게 Rufaydium은 geckodriver 세션을 계속할 수 있거나, 여러 AHK 스크립트가 Firefox를 제어할 수 있습니다.

FF := new Rufaydium("geckodriver.exe")
Page := FF.NewSession() ; 세션 ID가 스크립트 다시 로드 후 접근을 위해 ini에 저장됩니다

Session Auto Delete

드라이버에 의해 생성된 세션은 사용자에 의해 닫힐 수 있습니다. 이런 상황에서 세션이 드라이버에 의해 닫히지 않았기 때문에 드라이버가 명령에 응답하는 데 시간이 걸립니다.

세션 자동 삭제는 웹 페이지에 도달할 수 없거나 사용자에 의해 닫혔을 때 드라이버에 대한 세션을 삭제합니다. 이 자동화된 단계는 웹 페이지가 수동으로/실수로 닫힌 후 Rufaydium의 모든 메서드에서 드라이버 응답 지연을 극복하기 위해 수행됩니다.

Session.NewTab() & Session.NewWindow()

새 탭이나 새 창을 생성하고 전환합니다

Session.NewTab()
Session.NewWindow()

전환하지 않고 새 탭과 새 창을 생성합니다

Session.NewTab(0)
Session.NewWindow(0)

Session.Title

페이지 제목을 반환합니다

MsgBox, % Session.Title

Session.HTML

페이지 HTML을 반환합니다

MsgBox, % Session.HTML

Session.url

페이지 URL을 반환합니다

MsgBox, % Session.url
Session.url := "<https://www>..com/boards/posting.php?mode=edit&f=6&p=456008"

Session.Refresh()

웹 페이지를 새로 고치고 새로 고침이 완료될 때까지 기다립니다.

Session.Refresh()
MsgBox, 페이지 새로 고침 완료

Session.IsLoading

페이지가 준비되었는지 여부를 부울값으로 반환하여 알려줍니다. 이는 Session.CDP()에 도움이 될 것입니다.

참고: 이 함수는 W3C 표준이 아니며 Chromedriver에서만 작동합니다

MsgBox, % Session.IsLoading()

Session.Navigate(url)

요청된 URL로 이동합니다

Session.Navigate("<https://www.autohotkey.com/>")

 

한 번에 여러 URL로 이동할 수 있습니다

TabId := Session.currentTab
Session.Navigate(url1,url2,url3,url4,url4)
Session.Switch(TabId) ; 이전 탭으로 돌아갑니다

Session.Back() & Session.Forward()

브라우저의 뒤로 가기와 앞으로 가기 버튼처럼 작동하여 이전 페이지나 최근 페이지로 이동하는 데 도움을 줍니다.

SwitchTab(), SwitchbyTitle() & SwitchbyURL(), ActiveTab()

탭 간 전환을 돕습니다.

Session.SwitchTab(2) ; 번호로 탭을 전환합니다. 왼쪽에서 오른쪽으로 계산됩니다
Session.SwitchbyTitle(Title)
Session.SwitchbyURL(url)
Session.ActiveTab() ; 활성 탭으로 전환합니다. 참고: 이는 현재 Firefox에서는 작동하지 않습니다.

Session window position and location

; 창 위치와 크기 가져오기
sessionrect := Session.Getrect()
MsgBox, % json.dump(sessionrect)
; 세션 창 위치와 크기 설정
Srect := Session.SetRect(20,30,500,400) ; x, y, w, h
; 오류 처리
if Srect.error
MsgBox, % Srect.error
; 위치 설정은 rect 배열을 반환합니다
rect := Session.SetRect(1,1) ; 이는 작업 표시줄을 고려하여 전체 화면을 덮도록 최대화합니다
MsgBox, % json.Dump(rect)
; 때로는 x나 y만 조작하고 싶을 수 있습니다
Session.x := 30
MsgBox, % session.y
; 이는 높이만이 아니라 전체 rect도 반환합니다
k := Session.height := A_ScreenHeight - (A_ScreenHeight * 5 / 100)
if !k.error
MsgBox, json.dump(k)

Session.Maximize() ; 이는 세션 창을 최대화합니다
windowrect := Session.Minimize() ; 이는 세션 창을 최소화합니다
if !windowrect.error ; 오류 처리
MsgBox, % json.dump(windowrect) ; 오류가 없으면 창 rect를 반환합니다

; 다음은 전체 화면 모드를 켭니다
MsgBox, % Json.Dump(Session.FullScreen()) ; rect를 반환합니다. x와 y가 0이고 h와 w가 전체 화면 크기임을 볼 수 있습니다
; 이는 단순히 전체 화면 모드를 끕니다
Session.Maximize()

Session.Close() and Session.Exit()

Session.Close()는 세션 창을 닫습니다 Session.Exit()는 모든 창을 닫아 세션을 종료합니다.

Chrome := new Rufaydium()
Page1 := Chrome.NewSession()
Page1.Navigate("<https://www.google.com/>")
Page1.NewTab()  ; 새 창/탭을 생성하지만 Page1 세션 포인터는 그대로 유지됩니다
Page1.Navigate("<https://www.autohotkey.com/boards/viewtopic.php?t=94276>") ; 2번째 탭으로 이동
; Page1.close() ; 활성 창/탭을 닫습니다
Page1.exit() ; 모든 창/탭을 닫아 전체 세션을 종료합니다

Switching Between Window Tabs & Frame

Session.SwitchbyTitle(Title) 또는 Session.SwitchbyURL(url="")를 사용하여 탭을 전환할 수 있습니다. 하지만 세션은 그대로 유지됩니다. 위의 예제를 확인하면 탭 전환이 어떻게 작동하는지 쉽게 이해할 수 있습니다.

탭 전환과 마찬가지로 프레임으로 전환할 수 있지만 세션 포인터는 그대로 유지됩니다.

Show Image

위 이미지에 따르면 3개의 탭이 있는 1개의 세션이 있습니다.

TAB 1에 대한 예제

Session.SwitchbyURL(tab1url) ; TAB 1로 전환
; 탭 1에는 총 3개의 프레임이 있습니다
MsgBox, % Session.FramesLength() ; 이는 메인 프레임에서 프레임 수 2를 반환합니다
Session.Frame(0) ; 프레임 A로 전환
Session.getElementByID(someid) ; 이는 프레임 A에서 요소를 가져옵니다
; 이제 프레임 B로 직접 전환할 수 없고 메인 프레임 / 메인 페이지로 돌아가야 합니다
Session.ParentFrame() ; 부모 프레임으로 돌아갑니다
Session.Frame(1) ; 프레임 B로 전환
Session.getElementByID(someid) ; 이는 프레임 B에서 요소를 가져옵니다
; 프레임 B에도 중첩된 프레임이 있어 프레임 B 안에 있으므로 프레임 BA로 전환할 수 있습니다
Session.Frame(0) ; 프레임 BA로 전환
Session.getElementByID(someid) ; 이는 프레임 BA에서 요소를 가져옵니다
Session.ParentFrame() ; 프레임 B로 돌아갑니다
Session.ParentFrame() ; 메인 페이지 / 메인 프레임으로 돌아갑니다

TAB 2에 대한 예제

Session.SwitchbyURL(tab2url) ; TAB 2로 전환
; 탭 2에도 총 3개의 프레임이 있습니다
MsgBox, % Session.FramesLength() ; 이는 프레임 수 3을 반환합니다
Session.Frame(0) ; 프레임 X로 전환
Session.ParentFrame() ; 메인 페이지 / 메인 프레임으로 돌아갑니다
Session.Frame(1) ; 프레임 Y로 전환
Session.ParentFrame() ; 메인 페이지 / 메인 프레임으로 돌아갑니다
Session.Frame(2) ; 프레임 Z로 전환
Session.ParentFrame() ; 메인 페이지 / 메인 프레임으로 돌아갑니다

 

TAB 3에 대한 예제

Session.SwitchbyURL(tab3url) ; TAB 3로 전환
MsgBox, % Session.FramesLength() ; 이는 TAB 3에 프레임이 없기 때문에 프레임 수 0을 반환합니다

참고: 프레임 전환은 Session.CDP에서 작동하지 않습니다

Error Handling

오류 처리는 요소 포인터를 반환하는 메서드를 제외한 모든 메서드에서 작동합니다. 몇 가지 공통 기능은 다음과 같습니다.

.

Accessing Element / Elements

다음 메서드들은 요소 포인터를 반환합니다.

Element := Session.getElementByID(id)
Element := Session.QuerySelector(Path)
Element := Session.QuerySelectorAll(Path)
Element := Session.getElementsbyClassName(Class)
Element := Session.getElementsbyName(Name)
Element := Session.getElementsbyTagName(TagName)
Element := Session.getElementsbyXpath(xPath)

 

DOM과 마찬가지로 요소에서 요소(들) 가져오기

element := Session.querySelector(".Someclass")
ChildElements := element.querySelectorAll("#someID")

부모 및 자식 요소 가져오기

e := Page.QuerySelector("#keywords")
parentelement := e.parentElement
for n, child in parentelement.children
msgbox, % "index: " n "`nTagName: " child.tagname

위의 메서드들은 .findelement()/.findelements()를 기반으로 합니다

Session.findelement(by.selector,"selectorparameter")
Session.findelements(by.selector,"selectorparameter")

요소의 길이를 확인할 수 있습니다

elements := Session.querySelectorAll(Path)
MsgBox, % elements.count()

표 접근하기 참조

by Class

Class by
{
static selector := "css selector"
static Linktext := "link text"
static Plinktext := "partial link text"
static TagName := "tag name"
static XPath := "xpath"
}

Accessing Tables

표에 접근하는 방법은 여러 가지가 있습니다. Session.ExecuteSync(JS) 또는 Session.CDP.Evaluate(JS)를 사용하여 JavaScript 함수로 추출할 수 있지만, AHK for 루프를 활용하는 것이 쉽고 간단한 방법입니다. 표를 반복하는 것은 약간 느린데, 이는 Rufaydium의 한 단계가 3단계로 구성되기 때문입니다:

  1. Json.Dump()
  2. WinHTTP Request
  3. Json.load()

표를 반복하는 데는 많은 단계가 필요하므로, 큰 표를 읽고 훨씬 빠르게 처리하려면 Session.ExecuteSync(JS)를 사용하는 것이 좋습니다. 단순히 표 데이터를 추출하고 표와 상호작용할 필요가 없는 경우에 특히 유용합니다.

참고: 다음 방법은 InnerText가 탭과 줄 바꿈을 포함하여 반환될 때만 작동합니다

; 수천 개의 행을 매우 빠르게 읽기
Table := Session.QuerySelectorAll("table")[1].innerText
Tablearray := []
for r, row in StrSplit(Table,"`n")
{
for c, cell in StrSplit(row,"`t")
{
;MsgBox, % "Row: " r " Col:" C "`nText:" cell
Tablearray[r,c] := cell
}
}
MsgBox, % Tablearray[1,5]

Session.ActiveElement()

포커스/활성 요소에 대한 핸들을 반환합니다. 이 함수는 Session.CDP와 Session.Basic 사이의 브리지 역할도 할 수 있습니다

DPelement.focus()
element := Session.ActiveElement() ; 이제 이전에 CDP를 사용하여 포커스를 맞춘 요소에 접근할 수 있습니다

Handling Session alerts popup messages

Session.Alert("GET") ; 팝업 메시지에서 텍스트 가져오기
Session.Alert("accept") ; 확인/수락 팝업 메시지 누르기
Session.Alert("dismiss") ; 취소/거부 팝업 메시지 누르기
Session.Alert("Send","some text")  ; 알림/팝업 메시지 보내기

Tacking Screen Shots accept only png file format

Session.Screenshot("picture location.png") ; A_ScriptDir에 PNG를 저장합니다
Session.Screenshot(a_desktop "\\picture location.png") ; a_desktop에 PNG를 저장합니다
Session.CaptureFullSizeScreenShot(a_desktop "\\fullPage.png") ; 전체 페이지 스크린샷을 저장합니다

PDF printing

WebDriver는 헤드리스 모드 인쇄만 지원합니다. 하지만 Rufaydium은 이제 "wkhtmltopdf" 덕분에 헤드풀 모드 인쇄를 지원합니다. Rufaydium은 Windows에 wkhtmltopdf가 없는 경우 wkhtmltopdf를 다운로드하고 설치하도록 요청할 것입니다.

Printing pdf with wkhtmltopdf

Print() 메서드는 동일하지만 인쇄 옵션을 정의하는 것은 필수가 아니며 PrintOptions 클래스도 wkhtmltopdf와 함께 사용할 수 있습니다.

Session.print(PDFlocation,PrintOptions.A4_Default) ; PrintOptions 클래스 참조
Session.print(PDFlocation) ; 인쇄 옵션이 필요하지 않습니다

고급 인쇄를 위한 옵션으로 Wkhtmltopdf 명령줄 매개변수

params := "--zoom 2 --margin-bottom 0 --margin-left 0 --margin-right 0 --margin-top 0 --page-height 0"
Session.print(PDFlocation,params)

참고: 중첩된 프레임에서 PDF 인쇄는 약간 까다롭지만 예제를 참조하세요.

Headless Mode Printing

헤드리스 모드 인쇄의 경우, PrintOptions를 설명해야 하며 이는 필수입니다. 다음 예제를 참조하세요.

Session.print(PDFlocation,PrintOptions.A4_Default) ; PrintOptions 클래스 참조
Session.print(PDFlocation,{"":""}) ; 기본 인쇄 옵션의 경우

Class PrintOptions

사용자 지정 PrintOptions를 만들기 위한 PrintOptions

lass PrintOptions ; <https://www.w3.org/TR/webdriver2/#print>
{
static A4_Default =
( LTrim Join
{
  "page":{
  "width": 50,
  "height": 60
},
  "margin":{
  "top": 2,
  "bottom": 2,
  "left": 2,
  "right": 2
},
  "scale": 1,
  "orientation": "portrait",
"shrinkToFit": json.true,
  "background": json.true
}
)
}

Session inputs events

Session.move(x,y) ; 마우스 포인터를 위치로 이동
Session.click() ; 이동된 위치에서 왼쪽 클릭 전송 ; [button: 0(왼쪽) | 1(중간) | 2(오른쪽)]
Session.DoubleClick() ; 이동된 위치에서 왼쪽 더블 클릭 전송 ; [button: 0(왼쪽) | 1(중간) | 2(오른쪽)]
Session.MBDown() ; 이동된 위치에서 마우스 왼쪽 버튼 누르기 전송 ; [button: 0(왼쪽) | 1(중간) | 2(오른쪽)]
Session.MBup() ; 이동된 위치에서 마우스 왼쪽 버튼 떼기 전송 ; [button: 0(왼쪽) | 1(중간) | 2(오른쪽)]
; 이제 드래그 앤 드롭을 어떻게 하는지 이해할 수 있습니다. 아래에서 요소 위치 rect와 크기에 대해 자세히 읽어보세요.

Session Cookies

Session.GetCookies() ; 쿠키의 객체 배열을 반환합니다. 이를 파싱하고 이해해야 합니다.
Session.GetCookieName(Name) ; 이름으로 쿠키를 반환합니다. 테스트하지 않았습니다.
Session.AddCookie(CookieObj) ; 쿠키를 추가합니다. 쿠키 추가를 위한 요청 매개변수는 모릅니다.

 

JSON.Dump()를 사용하여 쿠키의 속성을 확인하세요.

Msgbox, %  JSON.Dump(Session.GetCookies())
/*
[{"domain": ".autohotkey.com", "expiry": 1654584141, "httpOnly": 0, "name": "_gat_gtag_UA_5170375_17", "path": "/", "secure": 0, "value": "1"},
{"domain": ".autohotkey.com", "expiry": 1654670481, "httpOnly": 0, "name": "_gid", "path": "/", "secure": 0, "value": "GA1.2.1414453342.1654584081"},
{"domain": ".autohotkey.com", "expiry": 1717656081, "httpOnly": 0, "name": "_ga", "path": "/", "secure": 0, "value": "GA1.2.1530957962.1654584081"}]
*/

 

모든 쿠키를 검색하는 예제입니다. 쿠키에 해당 속성이 없는 경우 일부 결과가 비어있을 수 있습니다.

cookies := Session.GetCookies() ; <https://developer.chrome.com/docs/extensions/reference/cookies/#type-Cookie>
Loop % cookies.Length()
{
    MsgBox, % cookies[A_Index].Domain ; .autohotkey.com
    MsgBox, % cookies[A_Index].Expiry ; 1654584321
    MsgBox, % cookies[A_Index].HostOnly ;
    MsgBox, % cookies[A_Index].HttpOnly ; 0
    MsgBox, % cookies[A_Index].Name ; _gat_gtag_UA_1234567_89
    MsgBox, % cookies[A_Index].Path ; /
    MsgBox, % cookies[A_Index].SameSite ;
    MsgBox, % cookies[A_Index].Secure   ; 0
    MsgBox, % cookies[A_Index].Session  ;
    MsgBox, % cookies[A_Index].StoreId  ;
    MsgBox, % cookies[A_Index].Value    ; 1
}

이름으로 단일 쿠키를 검색하는 예제입니다.

var := Session.GetCookieName("CFID")
MsgBox, % var.Domain " | " var.Expiry " | " var.Value ; 등

WDElement

사용 가능한 웹 드라이버 요소 메서드들입니다.

Element.Name() ; 태그 이름을 반환합니다
Element.Rect() ; 위치와 크기를 반환합니다
Element.enabled() ; 활성화된 경우 true, 비활성화된 경우 false를 반환합니다
Element.Selected() ; 선택된 경우 true, 선택되지 않은 경우 false를 반환합니다. 이는 드롭다운 목록이나 콤보 목록에서 옵션을 선택할 때 유용합니다
Element.Displayed() ; 요소가 보이는 경우 true, 보이지 않는 경우 false를 반환합니다

; 입력 및 이벤트 트리거
Element.Submit() ; 기존 이벤트를 트리거합니다
Element.SendKey("text string " . key.class ) ; 텍스트를 변환하고 요소에 키 이벤트를 보냅니다. 특수 키는 Key.class를 참조하세요
Element.SendKey(key.ctrl "a" key.delete) ; Ctrl + A와 delete를 수행하여 편집 상자의 텍스트 내용을 지웁니다
Element.Click() ; 간단한 클릭을 보냅니다
Element.Move() ; 마우스 포인터를 해당 요소로 이동합니다. 드래그 앤 드롭에 도움이 됩니다. session.click과 session.move를 참조하세요
Element.onchange() ; onchange() 이벤트를 발생시킵니다
Element.clear() ; 선택된 항목 / 업로드된 파일 또는 내용 텍스트를 지웁니다

; 속성, 속성 & CSS
Element.GetAttribute(Name) ; 필요한 속성을 반환합니다
Element.GetProperty(Name) ; 필요한 속성을 반환합니다
Element.GetCSS(Name) ; CSS를 반환합니다

; 요소 Shadow
Element.Shadow() ; 그림자 요소 세부 정보를 반환합니다. 실제로 나중에 그림자 요소에 접근하는 기능을 추가할 예정입니다
; 먼저 그것들에 대해 배워야 합니다

Element.Sendkey(StrReplace(filelocation,"\\","/")) ; 요소가 입력 요소인 경우 SendKey()를 사용하여 파일 위치를 설정할 수 있습니다
; 파일 위치를 설정한 후 업로드 버튼을 클릭하면 파일 업로드가 시작됩니다

웹 드라이버 요소 정보 가져오기.

e := Page.querySelector(selector) ; 요소 가져오기
msgbox % e.innerText
msgbox % "TagName: " e.TagName "`nName: " e.Name "`nID: " e.id "`nTitle: " e.Title "`nClass: " e.Class "`nValue: " e.value
msgbox, % e.InnerHTML
msgbox, % e.outerHTML
msgbox, % "href: " e.href "`nSrc: " e.src

 

웹 드라이버 요소 정보 설정/변경하기.

e.Name := "abcd"
e.id := "Mywords"
e.Title := "My Title"
e.Class := "My Class"
e.value := "My Value"
newhtml = <button name="Rufaydium" id="MyButton" >Rufaydium</button>
e.outerHTML := newhtml
e.InnerHTML := newhtml
e.href := url
e.src := url

참고: 요소 조작은 Rufaydium 기본 및 1.6.3 미만 버전에서는 사용할 수 없습니다.

Shadow Elements

그림자 요소는 element.shadow()를 사용하여 쉽게 접근할 수 있습니다. 다음 예제는 Chrome 확장 프로그램 페이지로 이동하여 개발자 모드를 활성화합니다

Chrome := new Rufaydium()
Page := Chrome.getSessionByUrl("chrome://extensions")
if !isobject(page)
{
Page := Chrome.NewSession()
Page.Navigate("chrome://extensions")
}
page.QuerySelector("extensions-manager").shadow().QuerySelector("extensions-toolbar").shadow().getelementbyid("devMode").click()

Key.Class

Class Key
{
static Unidentified := "\\uE000"
static Cancel:= "\\uE001"
static Help:= "\\uE002"
static Backspace:= "\\uE003"
static Tab:= "\\uE004"
static Clear:= "\\uE005"
static Return:= "\\uE006"
static Enter:= "\\uE007"
static Shift:= "\\uE008"
static Control:= "\\uE009"
static Ctrl:= "\\uE009"
static Alt:= "\\uE00A"
static Pause:= "\\uE00B"
static Escape:= "\\uE00C"
static Space:= "\\uE00D"
static PageUp:= "\\uE00E"
static PageDown:= "\\uE00F"
static End:= "\\uE010"
static Home:= "\\uE011"
static ArrowLeft:= "\\uE012"
static ArrowUp:= "\\uE013"
static ArrowRight:= "\\uE014"
static ArrowDown:= "\\uE015"
static Insert:= "\\uE016"
static Delete:= "\\uE017"
static F1:= "\\uE031"
static F2:= "\\uE032"
static F3:= "\\uE033"
static F4:= "\\uE034"
static F5:= "\\uE035"
static F6:= "\\uE036"
static F7:= "\\uE037"
static F8:= "\\uE038"
static F9:= "\\uE039"
static F10:= "\\uE03A"
static F11:= "\\uE03B"
static F12:= "\\uE03C"
static Meta:= "\\uE03D"
static ZenkakuHankaku:= "\\uE040"
}

Session.Actions()

Actions(interactions*) 메서드를 사용하여 페이지와 상호작용할 수 있습니다. interactions는 Actions 클래스를 기반으로 한 Mouse, Scroll, Keyboard 클래스를 사용하여 생성됩니다. 빈 Actions() 메서드를 보내면 진행 중인 작업을 해제/중지합니다.

Session.Actions(Interaction1,Interaction2,interaction3) ; 상호작용에 대해서는 Action 클래스를 읽어보세요

Session.Actions() ; 진행 중인 작업 중지

Actions Class

Session.Actions() 메서드를 위한 Webdriver Actions 페이로드를 생성하는 데 도움을 주는 Action 클래스로, Mouse, Scroll, Keyboard 클래스(이하 "상호작용"이라 함)를 확장합니다. 액션 페이로드는 대소문자를 구분해야 하며 "pointerType"에 대한 특정 매개변수가 있으므로, 이 클래스들은 페이로드 생성을 도울 뿐만 아니라 이해하기 쉽게 만듭니다.

다음 메서드들은 Mouse, Scroll, Keyboard 클래스에 상속되어 있으며, 나중에 Webdriver Actions 페이로드로 변환되는 상호작용 객체를 생성합니다(이하 "이벤트/이벤트 생성"이라 함).

Pause(duration) - 상호작용 사이에 지연을 일으키는 "pause" 이벤트를 생성합니다. 기본 'duration'은 100입니다.

cancel() - 'pointerCancel' 이벤트를 생성합니다.

Clear() - 모든 이벤트를 삭제하여 상호작용을 재설정합니다.

참고: 하나의 상호작용 클래스 객체에는 여러 이벤트가 있을 수 있습니다.

Mouse Class

Mouse 클래스는 Session.Actions()에 매개변수로 제출될 때 나중에 Webdriver Actions 페이로드로 변환되는 'Type' "pointer" 이벤트/상호작용 객체를 생성합니다.

interaction := New mouse(pointerType) - 'pointerType' 매개변수를 받아들이며, "mouse", "pen", 또는 "touch"일 수 있습니다. 기본 pointerType은 mouse입니다. 상호작용 클래스 객체를 반환합니다.

mouse.Clear() - 모든 이벤트를 삭제하여 상호작용을 재설정합니다.

mouse.cancel() - 'pointerCancel' 이벤트를 생성합니다. 이는 마우스가 문서 위에 없는 것처럼 작동합니다.

mouse.press(Button) - "pointerDown"에 대한 페이로드 객체를 생성합니다. "Button" 매개변수로 0(왼쪽), 1(중간), 또는 2(오른쪽) 마우스 버튼을 받아들입니다. 빈 매개변수는 AutoHotkey에서 0으로 간주되어 왼쪽 마우스 버튼이 기본값으로 설정됩니다.

mouse.Release(Button) - "pointerUp"에 대한 페이로드 객체를 생성합니다. "Button" 매개변수로 0(왼쪽), 1(중간), 또는 2(오른쪽) 마우스 버튼을 받아들입니다. 빈 매개변수는 AutoHotkey에서 0으로 간주되어 왼쪽 마우스 버튼이 기본값으로 설정됩니다.

mouse.Move(x,y,duration,width,height,pressure,tangentialPressure,tiltX,tiltY,twist,altitudeAngle,azimuthAngle,origin) - 마우스 포인터를 'x' 'y' 방향으로 이동시킵니다. 이동에 걸리는 시간은 'duration'입니다. 포인터 크기는 'width'와 'height'로 정의할 수 있으며, 이는 선택사항입니다.

이동은 'pressure', 'tangentialPressure', 'tiltX', 'tiltY', 'twist', 'altitudeAngle', 'azimuthAngle' 매개변수를 사용하여 버튼/터치에 대해 조정할 수 있으며, 이 또한 선택사항입니다.

"origin"은 "viewport" 또는 "pointer"일 수 있습니다.

Move의 기본 매개변수:

매개변수값x0y0duration10width0height0pressure0tangentialPressure0tiltX0tiltY0twist0altitudeAngle0azimuthAngle0origin"viewport"

mouse.click(button,x,y,duration) - 클릭은 위에서 이미 정의된 메서드를 따르는 직렬화된 객체를 생성하며, JSON 페이로드로 변환되어 처음부터 마지막까지 하나씩 실행됩니다.

        mouse.move(x,y,0)
        mouse.press(button,duration)
        mouse.Pause(500)
        mouse.release(button,duration)

마우스 상호작용 및 이벤트 예제

MouseEvent := new mouse() ; pointerType을 "mouse"로 설정
MouseEvent.press() ; 0(왼쪽) | 1(중간) | 2(오른쪽)
MouseEvent.move(288,258,10)
MouseEvent.release()
Session.Actions(MouseEvent)
return

Scroll Class

Scroll 클래스는 'Type' "wheel" 이벤트/상호작용 객체를 생성하며, 이는 나중에 Session.Actions()에 매개변수로 제출될 때 Webdriver Actions 페이로드로 변환됩니다.

interaction := New Scroll(pointerType) - 'pointerType' 매개변수를 받아들이며, "mouse", "pen", 또는 "touch"일 수 있습니다. 기본 pointerType은 mouse입니다. 상호작용 클래스 객체를 반환합니다.

interaction.Clear() - 모든 이벤트를 삭제하여 상호작용을 재설정합니다.

interaction.Scroll(deltaX,deltaY,x,y,duration,origin) - 웹페이지의 문서 뷰에서 수직 수평 스크롤을 수행합니다. 주어진 duration, x, y, 목표 delta x, 목표 delta y, 현재 delta x 및 현재 delta y에 대해 스크롤을 수행합니다:

Scroll 메서드의 기본 매개변수:

매개변수값deltaX0deltaY0x0y0duration10origin"viewport"

다음 메서드들은 .Scroll(s)를 활용하여 위, 아래, 왼쪽, 오른쪽으로 스크롤을 수행합니다. 여기서 's'는 기존 위치에서 계산된 스크롤 값이며, 기본값은 50입니다.

interaction.ScrollUP(s)

interaction.ScrollDown(s)

interaction.ScrollLeft(s)

interaction.ScrollRight(s)

Keyboard Class

Keyboard 클래스는 'Type' "key" 이벤트/상호작용 객체를 생성하며, 이는 나중에 Session.Actions()에 매개변수로 제출될 때 Webdriver Actions 페이로드로 변환됩니다.

KeyInterAction := New Keyboard() 상호작용 클래스 객체를 반환합니다. 매개변수가 필요하지 않습니다.

Keyboard.Clear() 모든 이벤트를 삭제하여 상호작용을 재설정합니다.

Keyboard.keyUp(key) "keyUp"에 대한 페이로드 객체를 생성합니다. "key" 매개변수를 키 "Value"로 필요로 합니다.

Keyboard.keyDown(key) "keyDown"에 대한 페이로드 객체를 생성합니다. "key" 매개변수를 키 "Value"로 필요로 합니다.

Keyboard.SendKey(keys) 키 입력을 모방하기 위해 'keyUp()'과 'keyDown()' 메서드를 동시에 사용합니다. Keys 문자열 매개변수가 필요합니다. 요소에서 키 입력을 모방하려면 Element.Sendkey()를 사용하고, 요소 값을 설정하고 가져오려면 WDElement.value를 사용하는 것이 좋습니다.

<details> <summary>상호작용 예제</summary>

#Include, %A_ScriptDir%\\..\\Rufaydium-Webdriver
#include Rufaydium.ahk
goto, TestKeyboard; 여기서 라벨을 변경하세요
return

clickTest:
URL := "<https://quickdraw.withgoogle.com>"
page := GetRufaydium(URL); 크롬 브라우저 실행/접근

MI := new mouse(); MI = mouse interaction;MI.click(0, 400, 400);MI.click(0, 200, 300)

MI.press()
MI.move(288,258,10)
MI.release()
MI.press()
MI.move(391,181,10)
MI.release()
MI.press()
MI.move(493,258,10)
MI.release()
MI.press()
MI.move(454,358,10)
MI.release()
MI.press()
MI.move(328,358,10)
MI.release()
MI.press()
MI.move(288,258,10)
MI.release()
MI.press()
MI.release()
msgbox, 그리기 창을 이동하고 확인을 클릭하여 그리기
x := page.actions(MI)
return

ScrollTest:
URL :=  "<https://www.autohotkey.com/boards/>"
page := GetRufaydium(URL); 크롬 브라우저 실행/접근
msgbox, % 스크롤하려면 위쪽 및 아래쪽 화살표 키를 사용하세요
return

down::
page.scrollDown(); Scroll 클래스를 활용합니다
return

up::
page.scrollup(); Scroll 클래스를 활용합니다
return

TestKeyboard:
URL :=  "<https://www.autohotkey.com/boards/>"
page := GetRufaydium(URL); 크롬 브라우저 실행/접근
e := Page.querySelector("#keywords"); 요소 가져오기
e.focus(); 키 입력 상호작용을 볼 수 있도록 요소에 포커스
page.sendkey("aBcd"); session.sendkey()는 Keyboard 클래스를 사용합니다
page.sendkey("xyZ")
return

; GetRufaydium(URL)은 기존 세션을 가져옵니다; 이는 매번 여러 세션을 생성하는 것을 방지합니다; 수동으로 드라이버를 닫지 않도록 주의하세요 / chrome.driver.exit(); by Xeo786
GetRufaydium(URL)
{
; 크롬 드라이버를 가져옵니다 / 실행 중이 아니면 크롬 드라이버를 실행하고, A_ScriptDir에 없으면 드라이버를 다운로드합니다; 기본 매개변수로 크롬 드라이버를 실행하고 기본 capabilities를 로드합니다
Chrome := new Rufaydium()
Page := Chrome.getSessionByUrl(URL); 페이지(드라이버에 의해 생성된)가 이미 존재하는지 확인합니다
if !isobject(page); URL이 있는 세션이 존재하는지 확인합니다
{
Page := Chrome.getSession(1,1); 첫 번째 세션의 첫 번째 탭을 가져오려고 시도합니다
if isobject(page); 존재한다면
Page.NewTab(); 새 탭을 생성합니다
else; 존재하지 않는다면
Page := Chrome.NewSession(); 새 세션을 생성합니다 ; 사용자가 수동으로 세션을 닫은 경우 Page.Exit()를 사용하면 지연이 발생할 수 있습니다
Page.Navigate(URL); 탐색합니다
}
return page
}

</details>

Await

Rufaydium Basic은 모든 작업/변경이 완료될 때까지 기다린 다음 다음 줄을 실행하지만, CDP Session.CDP를 통해 실행되는 모든 작업은 기다리지 않으므로 Session.CDP.WaitForLoad()를 사용해야 합니다.

웹페이지 대기는 문서 준비 상태 https://www.w3schools.com/jsref/prop_doc_readystate.asp 를 기반으로 합니다. 그러나 준비 상태가 complete로 유지되는 동안 요소와 내용을 계속 로드하고 언로드하는 웹페이지가 있습니다. 이러한 상황에서 Rufaydium Basic과 Rufaydium CDP는 단순히 오류를 통해 기다리거나 문제의 요소를 사용할 수 없거나 요소 가시성 또는 표시/활성화 상태 요소, displayed(), element.enabled()를 통해 기다립니다. 이러한 트릭을 사용하여 AutoHotkey가 기다리도록 할 수 있습니다. 예를 들어, 버튼을 클릭하면 button 태그 이름을 가진 요소가 로드됩니다.

while !IsObject(button) ;
{
   sleep, 200
   ; 요소 가져오기는 현재 오류 처리를 지원하지 않지만 요소를 찾으면 요소 객체를 반환하고 찾지 못하면 빈 값을 반환합니다
   button := Session.QuerySelector("button")
}
h := button.innerText
while h.error
{
    h := button.innerText ; 하지만 element.methods는 오류 처리를 지원합니다
    sleep, 200
}
MsgBox, % "innerText" h ; 그렇지 않으면 h에 innertext가 있습니다
Button.click()

Session.CDP

Session.CDP는 Chrome Devtools 프로토콜에 접근할 수 있습니다.

<details> <summary>예제</summary>

ChromeDriver := A_ScriptDir "\\chromedriver.exe"
; 드라이버가 이미 실행 중인 경우 이미 실행 중인 드라이버에 접근합니다
Driver := new RunDriver(ChromeDriver)
Chrome := new Rufaydium(Driver)
Page := Chrome.getSessionByUrl(Webpage) ; 세션 가져오기

if !isobject(Page)
{
MsgBox, 세션을 찾을 수 없습니다
return
}

; Page.CDP.Document() ; 더 이상 필요하지 않습니다
input := Page.CDP.QuerySelector(".mb-2")
MsgBox, % input.innerText
for k , tag in  Page.cdp.QuerySelectorAll("input") ; 모든 입력 상자를 해당 id로 채웁니다
{
tag.sendKey(tag.id)
}

</details>

참고: Firefox / Geckodriver 세션은 Session.CDP (Chrome Devtools 프로토콜)를 지원하지 않습니다. Firefox에는 자체 Remote 프로토콜이 있으며, 이는 곧 Session.FRP, Firefox Remote 프로토콜로 추가될 예정입니다.

CDP.Document()

CDP.Document()는 더 이상 사용되지 않으며 필요하지 않습니다. Rufaydium CDP는 프레임에 대한 안정적인 접근을 개발했습니다.

CDP 기능

Session.CDP.navigate(url) ; url로 이동
Session.CDP.WaitForLoad() ; Session.methods()와 달리 CDP는 대기를 지원하지 않습니다

; 요소 가져오기
element := Session.CDP.querySelector(selector)
element := Session.CDP.getElementByID(ID)
; 요소 배열 가져오기
elements := Session.CDP.querySelectorAll(selector)
elements := Session.CDP.getElementsbyClassName(Class)
elements := Session.CDP.getElementsbyName(Tagename)

/* JS 함수로 요소 가져오기
1) GetelementbyJS()는 Document에서만 사용할 수 있습니다. Document.GetelementbyJS(JS)와 같이 사용합니다. 요소에서도 작동하지만
   document를 기본 노드/포인터로 간주합니다.
2) JS는 요소 또는 요소 배열을 반환해야 합니다. 예: GetelementbyJS("document.querySelectorAll('input')")
   함수를 전달하고 그 결과를 사용하려면 요소 하나 또는 요소 배열을 반환하는 함수를 전달할 수 있습니다.
3) GetelementbyJS(js).value := var 및 GetelementbyJS(js)[].value := var와 같이 사용할 수 있습니다. 이는 전적으로
   전달하는 JavaScript에 달려 있습니다.
4) GetelementbyJS("document.querySelector('input').value = '1234'")와 같은 작업은 할 수 없습니다.
   이를 위해서는 CDP.Evaluate()가 있습니다.
5) GetelementbyJS()는 느릴 수 있다고 생각합니다. 빠른 결과를 위해 DOM.querySelector를 사용해야 하지만 JavaScript 사용자들은
   GetelementbyJS()를 만든 이유를 이해할 것입니다. 일부 시나리오에서는 JS가 더 빠른 결과를 얻을 수 있습니다.
   위에서 언급한 Evaluate를 사용한 JS 사용자 정의 함수 전달과 같은 경우입니다.
*/
element := Session.CDP.GetelementbyJS("JSfunc()") ; JS 함수

; 위치로 요소 가져오기
; 이 메서드는 Session.CDP.Document()가 필요하지 않습니다
element := Session.CDP.getelementbyLocation(x,y)

CDP.Element

다음 메서드들은 CDP에서 반환된 요소(들)에만 적용됩니다

CDP_element.getBoxModel() ; 요소 좌표 여백 및 패딩 세부 정보가 포함된 Json 배열 반환
CDP_element.getNodeQuads() ; quads는 각 점에 대해 x 바로 뒤에 y가 오며, 시계 방향으로 점이 배치됩니다

val := CDP_element.value ; 값 가져오기
CDP_element.value := "abcd" ; 값 설정

eleClass := CDP_element.class ; 클래스 가져오기
CDP_element.class := "abcd" ; 클래스 설정

eleID := CDP_element.id ; id 가져오기
CDP_element.id := "abcd" ; id 설정

text := CDP_element.innerText ; innerText 가져오기
CDP_element.innerText := "abcd" ; innerText 설정

text := CDP_element.textContent ; textContent 가져오기

html := CDP_element.OuterHTML ; html 가져오기
CDP_element.OuterHTML := htmlstring ; html 설정

allattribus := CDP_element.getAttributes() ; 모든 속성을 객체로 가져옵니다. json dump를 사용하여 내용을 확인할 수 있습니다
value := CDP_element.getAttribute(Name) ; 위 메서드를 기반으로 특정 속성 값 가져오기
CDP_element.setAttribute(Name,Value) : 속성 값 변경

; istrusted 매개변수가 true인 dispatch 이벤트 사용
CDP_element.focus()
CDP_element.click() ; click() 보내기
CDP_element.ClickCoord(x,y, delay:= 10) ; 좌표로 클릭 보내기
CDP_element.SendKey("1234`n") ; 1 2 3 4 엔터 보내기

CDP Evaluate(JS)

Session.CDP.Evaluate()는 Chrome의 콘솔을 사용하는 것처럼 Javascript를 실행합니다.

js =
(
function findByTextContent(searchText)
{
var aTags = document.querySelectorAll("[Class='mb-4 block-menu-item col-xl-auto col-lg-4 col-sm-6 col-12']");
var found;
for (var i = 0; i < aTags.length; i++) {
  if (aTags[i].textContent == searchText) {
    found = aTags[i];
    break;
  }
}
return found
}
)
Session.CDP.evaluate(js)
Session.CDP.evaluate("findByTextContent('" btnName "').childNodes[0].click()")

CDP.Frames

Basic과 마찬가지로 CDP 메서드를 사용하여 프레임으로 전환할 수 있습니다.

MsgBox, % Page.CDP.FramesLength() ; 자식 프레임 길이를 반환합니다
Page.CDP.Frame(0) ; 프레임 1로 전환
Page.CDP.ParentFrame() ; 메인 페이지 / 프레임으로 돌아갑니다

CDP Call

Call은 Chrome Devtools 프로토콜을 위한 sendCommand call입니다, https://chromedevtools.github.io/devtools-protocol/ 위의 모든 메서드는 CDP.Call()을 기반으로 합니다 Session.CDP.call(method,Json_param)

ExtList := ["*.ttf","*.gif" , "*.png" , "*.jpg" , "*.jpeg" , "*.webp"]
Session.CDP.call("Network.enable")
Session.CDP.call("Network.setBlockedURLs",{"urls": ExtList })

 

댓글