자동화

반응형

윈도우 탐색기의 파일 목록을 가져오는 방법

 

먼저 해당 경로의 첫번째 파일 xpath를 UIRecorder를 통해 확보한다.

xpath를 보면 파일명 이전에

 

/ListItem[@ClassName=\"UIItem\"]

 

이 요소를 볼 수 있다. UIItem 이 목록을 담고 있는 요소라고 직감적으로 판단할 수 있다.

 

그렇다면 해당 목록을 Name을 모두 가져올 수 있을 것이다.

 

java 코드

 

public class Modules extends Setup{
    public static WindowsDriver<?> winapp = null;
    
    public Modules(WindowsDriver<?> driver) throws Exception {
    	winapp = driver;
    }
    
    
    public void 개인폴더(String folder_name) {
    	
    	ArrayList<String> list = new ArrayList<String>();
		//해당 경로의 목록 xpath 
    	String folder_listview = "/Pane[@ClassName=\"#32769\"][@Name=\"데스크톱 1\"]"
    			+ "/Window[@ClassName=\"CabinetWClass\"][@Name=\"MYBOX\"]"
    			+ "/Pane[@ClassName=\"ShellTabWindowClass\"][@Name=\"MYBOX\"]"
    			+ "/Pane[@ClassName=\"DUIViewWndClassName\"]"
    			+ "/Pane[@Name=\"셸 폴더 보기\"][@AutomationId=\"listview\"]"
    			+ "/List[@ClassName=\"UIItemsView\"][@Name=\"항목 보기\"]"
    			+ "/ListItem[@ClassName=\"UIItem\"]";

		
    	//목록 파일 명 불러오기
		List<WebElement> list_elements = (List<WebElement>) winapp.findElementsByXPath(folder_listview);

		System.out.println("size"+size);
		for (WebElement e : list_elements) {
			list.add(e.getText());
			System.out.println(e.getText());
		}
		System.out.println("------------------\n");
		System.out.println("list 21번째 파일명" +list.get(21));

    	 
    }

▼상속받은 setup.java 코드 보기

더보기
import java.net.URL;
import java.util.concurrent.TimeUnit;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;


import io.appium.java_client.windows.WindowsDriver;
import io.appium.java_client.windows.WindowsElement;

/**
 * Hello world!
 *
 */
public class Setup 
{
    public static WindowsDriver ExplorerSession = null;
    public static WindowsDriver<WindowsElement> WindowSession = null;
    public static WebElement Result = null;
    public static ChromeDriver Chrome = null;
    public static Modules modules;
    public static Actions actions ;
    public static Session session;
    
	@BeforeClass
	public static void setup() {
		try {
			DesiredCapabilities appCapabilities = new DesiredCapabilities();
			appCapabilities.setCapability("platformName", "Windows");
			appCapabilities.setCapability("deviceName", "WindowsPC");
			
			
			//switch to desktop/root Session
			appCapabilities.setCapability("app", "Root");
			WindowSession = new WindowsDriver<WindowsElement>(new URL("http://127.0.0.1:4723"), appCapabilities);
			WindowSession.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
			
			
			//기존코드
			Assert.assertNull(session);
			actions = new Actions(WindowSession);
			modules = new Modules(WindowSession);
			session = new Session(WindowSession);	
			String currentWindowHandle = WindowSession.getWindowHandle();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		}
	}
	   

	    @AfterClass
	    public static void TearDown()
	    {
	    	Result = null;
	        if (WindowSession != null) {
	        	WindowSession.quit();
	        }
	        WindowSession = null;
	    }
}

 

실행 결과

 

목록의 모든 파일명을 가져와 보여주고 있는 모습이다.

반응형
반응형

 

 

winappdriver 자동화 도중 키보드 입력을 위해 .sendkeys("문자열"); 을 사용했는데 아무리해도 키보드입력이 되질 않았다. 그런데 웃긴 건 같은 xpath로 click()은 또 먹힌다는 것이었다. 도대체 뭐가 문제일까 해서 찾아보니 winappdriver가 미국 키보드만 입력한다는 것이었다 ;;;

 

이 뭔...

 

https://github.com/microsoft/WinAppDriver/issues/507

 

SendKeys not always send correct keys (if keyboard differs (Swedish, English)) · Issue #507 · microsoft/WinAppDriver

Define the datetime as string: string date = DateTime.Now.ToShortDateString(); sendKeys for some text control: someWindowsElementTextControl.SendKeys(date); Actual result: Depending on windows cult...

github.com

 

 

위 이슈 번역기를 돌려보니

미국 키보드만 지원한다고 한다. 아니 이건 무슨 차별일까? 언어를 따질게 아니라 키보드 입력이면 언어가 안맞더라도 입력은 되어야 하는거 아닌가. 언제 개선될련지.. 그래서 윈도우 설정에서 키보드를 바꿔놓았더니 바로 입력이 되었다..

(참고로 한국어 스트링도 입력됨)

 

 

쓸데없는 걸로 또 시간을 낭비했다. 하..

 

Windows 11에서도 같은 문제에 직면했다. 한창 삽질을 하다가 이 글이 생각나서 입력방법을 재설정 해보았더니 역시나 되었다.  시간 및 언어 > 언어 및 지역 > 옵션에서 영어(미국)이 없다면 언어 추가를 통해 추가하고 키보드도 같이 추가하면 된다.

US 키보드 추가

 

반응형
반응형

 

 

winappdriver 에서 우클릭 메뉴를 클릭하고 싶었는데 도무지 클릭이 되지 않았다. 단순 요소로 클릭이 되지 않아서 xpath를 찾아서 해보았지만 그래도 실패.. 한참을 삽질하다가 중간에 스레드 슬립을 주어 시간을 좀 지연 시켰더니 겨우 됐다. 

 

우클릭 > 열기를 클릭해보려고 한다

먼저 우클릭 하는 방법을 알아야 하므로 이 링크를 참고하였다

 

https://yonoo88.tistory.com/1322

 

Winappdriver 주요 기능 사용법 in java

더블 클릭 public void DoubleClick(String name) { WebElement elementLocator = driver.findElementByName(name); actions.doubleClick(elementLocator).perform(); } 우클릭 public void RightClick(String nam..

yonoo88.tistory.com

 

 Root 세션을 받아와야 한다. Setup에서 WindowSession에 받아옴

WindowSession

Name으로 클릭하는 방법

그냥 name 으로 클릭하는 방법이 가장 간단하다 

예를 들면 이런식 - WindowSession.findElemnet(By.name("열기(O)")).click();

    public void RightClick(String name) {
    	//우클릭 구현
		WebElement elementLocator = winapp.findElementByName(name);
		actions.contextClick(elementLocator).perform();
        try {
			Thread.sleep(1000); //name를 찾기위한 지연시간 추가
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        //이름으로 클릭
		WindowSession.findElemnet(By.name("열기(O)")).click();
       
    }

이름을 못 찾으면 중간에 지연시간을 추가해주면 동작한다. 이런 식으로 하면 바로 클릭이 가능한데 가끔 저게 안먹히는 녀석들이 있다. 그럴 땐 xpath로 하는 방법이 있다

 

Xpath로 클릭하는 방법

파일 탐색기의 xpath를 찾아야 한다. WinAppDriverUiRecorder 를 실행 시킨 후 Record를 클릭한다음 탐색기를 실행한다. 그리고 우클릭을 해보면 xpath가 나오는데

 

우클릭 열기의 xpath

 

저 xpath를 사용하여 클릭을 해주어야 한다. 일단 해당 폴더까지 마우스를 클릭까지 구현해준 다음 우클릭 코드를 작성

    public void RightClick(String name) {
    	//우클릭 구현
		WebElement elementLocator = winapp.findElementByName(name);
		actions.contextClick(elementLocator).perform();
        try {
			Thread.sleep(1000); //name를 찾기위한 지연시간 추가
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        //이름으로 클릭
		WindowSession.findElementByXPath("//Menu[@ClassName=\"#32768\"][@Name=\"컨텍스트\"]/MenuItem[@Name=\"열기(O)\"]").click();
       
    }

xpath를 보면 //Menu.. 부터 사용했으며 그 전 xpath는 Windowsession을 받아왔기 때문에 생략이 가능한 듯 하다.

 

 

코드를 실행해보면 우클릭 > 열기 버튼이 클릭되는데 열기 버튼을 누르기까지 약 20여초가 걸렸다. 왜 이렇게 오래 걸리는지 모르겠다. . 그렇다고 코드 중간에 Thread.sleep(1000)을 빼면 찾지를 못한다. xpath 를 탐색하는데 시간이 좀 걸리나 보다. 이것도 해결하는데 시간이 꽤 걸렸는데 안되는 이유는 2가지였었다.

 

1. xpath가 잘못된 경우 - xpath에 오타가 없는지 다른 xpath를 복사한건 아닌지 확인

2. 지연시간을 주지않아 동작하지 않은 경우

 

우클릭이 되지 않는다면 위 2가지를 다시 한번 살펴보아야 한다.

 

 

반응형
반응형

 

 

더블 클릭

 public void DoubleClick(String name) {
    	WebElement elementLocator = driver.findElementByName(name);
   	 	actions.doubleClick(elementLocator).perform();
    }

우클릭

    public void RightClick(String name) {
    	
		WebElement elementLocator = driver.findElementByName(name);
		actions.contextClick(elementLocator).perform();
    }

xpath 사용

driver.findElementByXPath("//ListItem[@ClassName=\"UIItem\"][@Name=\"폴더명\"]").click();

이클립스에서 xpath

UIRecorder에서 본 xpath, 빨간줄만 뽑아내어 사용

 

새로운 기능 사용할 때마다 추가 예정

 

 

 

반응형
반응형




자동화를 하면 항상 새 크롬창을 띄웠는데 현재 실행 중인 크롬 창에서 실행할 수는 없을까해서 검색해본 결과


무조건 한번은 새로 크롬을 새로 띄워야 한다는 결론에 도달.


그리고 그 크롬에서 적용 할 수 있었다.


첫번째 해야할 것은 (크롬드라이버 다운은 필수)


cmd에서 디버그용? 크롬을 실행시켜야 한다


chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile" 


이걸 cmd에서 실행해보면 크롬이 실행된다.


안된다면 C:\Program Files (x86)\Google\Chrome\Application\ 이 경로로 이동해서 실행해보거나


환경변수에 위 경로를 추가해준다.



이 크롬으로 계속 재활용할 수 있다.


이제 이걸 자바 코드 내에 cmd 실행을 시킨다음 실행해주면 된다.


참고로 코드 내에서 실행할 때는 완전한 경로로 해주어야 실행이 된다.


 Runtime.getRuntime().exec("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe --remote-debugging-port=9222 --user-data-dir=\"C:/selenum/AutomationProfile\"");


위 코드를 먼저 실행해 준 다음


ChromeOptions options = new ChromeOptions();

options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");

driver = new ChromeDriver(options); 


크롬 옵션을 추가해주어 실행된 크롬창을 사용하도록 지정해준다.(9222포트는 위 실행명령어 포트와 동일)



전체적인 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Automation {
 
    private static WebDriver driver;
 
    @BeforeClass 
    public static void setUp() throws Exception { 
        System.setProperty("webdriver.chrome.driver""C:\\chromedriver.exe");
            
        Runtime.getRuntime().exec("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe --remote-debugging-port=9222 --user-data-dir=\"C:/selenum/AutomationProfile\"");
 
        ChromeOptions options = new ChromeOptions();
        options.setExperimentalOption("debuggerAddress""127.0.0.1:9222");
        driver = new ChromeDriver(options);
        
        System.out.println(driver.getTitle());
        driver.manage().window().maximize();
        driver.get("https://www.naver.com");
        
    }
}
cs



 자동화 실행 후 현재 실행중인 크롬에서 확인해보려면  Runtime.getRuntime().exec 코드를 주석처리하고 실행하면 확인해볼 수 있다


주석처리를 안하면 실행할 때마다 새로운 크롬이 생성된다.



반응형
반응형




셀레니움으로 자동화를 하다보면 작업관리자에 chromedriver.exe가 수두룩하게 누적되어 있는 걸 볼 수 있다


이게 쌓이다보면 메모리를 상당히 잡아먹고 있는데 그래서 자동화가 한번 끝나면 프로세스를 종료하도록 하였다.

셀레니움에서 프로레스를 죽이는 기능이 있다고 하는데 이제 사용하지 않는 기능이라고 문서에 나와있었다




그렇다면 다른 방법으로 메소드를 다시 만들었을 것 같은데 아직 찾지 못했고 일단 급한대로 프로세스 죽이는 코드를 적용했다.



python 파이썬

- cmd에서 pip install psutil 로 설치 필수
1
2
3
4
5
6
7
import psutil 
 
for proc in psutil.process_iter():
    # check whether the process name matches
    if proc.name() == PROCNAME:
        proc.kill()
 
cs



java 자바에서 사용


1
Runtime.getRuntime().exec("taskkill /F /IM chromedriver.exe /T");
cs



자동화 코드 이후에 추가해주면 chromedriver.exe가 없어지는 걸 볼 수 있었다.

반응형
반응형


GUI 구성하기

Qt designer로 생성한 .ui 파일 파이썬 .py로 변환

http://yonoo88.tistory.com/1209


GUI 구성상태


기능 : ID와 PW 입력 후 시작버튼을 누름 > 동작 완료 후 listWidget에 로그인 성공 표시


아래 코드를 보면 UI 객체 명 별로 코드가 구성되어 있다

핵심은 시작 버튼에 이벤트 처리를 해주는 것. 시작 버튼 객체명은  startButton  이다

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 
from PyQt5 import QtCore, QtGui, QtWidgets
from selenium import webdriver
import time
 
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(180234)
 
        self.listWidget = QtWidgets.QListWidget(Dialog)
        self.listWidget.setGeometry(QtCore.QRect(2016014161))
        self.listWidget.setObjectName("textBrowser")
 
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(80101616))
        self.label.setObjectName("label")
 
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setGeometry(QtCore.QRect(80702116))
        self.label_2.setObjectName("label_2")
 
        self.startButton = QtWidgets.QPushButton(Dialog)
        self.startButton.setGeometry(QtCore.QRect(501307523))
        self.startButton.setObjectName("startButton")
 
        self.lineEdit_ID = QtWidgets.QLineEdit(Dialog)
        self.lineEdit_ID.setGeometry(QtCore.QRect(303011320))
        self.lineEdit_ID.setObjectName("lineEdit_ID")
 
        self.lineEdit_PW = QtWidgets.QLineEdit(Dialog)
        self.lineEdit_PW.setGeometry(QtCore.QRect(309011320))
        self.lineEdit_PW.setObjectName("lineEdit_PW")
 
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
 
#startButton 클릭시 autoExcute 함수 수행
        self.startButton.clicked.connect(self.autoExcute)
 
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog""Naver Login"))
        self.label.setText(_translate("Dialog""ID"))
        self.label_2.setText(_translate("Dialog""PW"))
        self.startButton.setText(_translate("Dialog""시작"))
 
 #셀레니움 동작 코드 함수 autoExcute 생성
    def autoExcute(self):
        driver  = webdriver.Chrome('C://chromedriver.exe')
        driver.implicitly_wait(3)
        driver.get('http://www.naver.com')
        driver.maximize_window()
        id = self.lineEdit_ID.text()
        pw = self.lineEdit_PW.text()
        driver.find_element_by_class_name('lg_local_btn').click()
        driver.find_element_by_id('id').send_keys(id)
        driver.find_element_by_id('pw').send_keys(pw)
        driver.find_element_by_class_name('btn_global').click()
        time.sleep(3)
        driver.close()
#listWidget에 로그인 성공 표시
        self.listWidget.addItem('로그인 성공')
        # self.addItem()
 
 
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Dialog = QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())
 

cs


코드를 실행시킨 후 아이디와 암호 입력 > 시작을 누르면 로그인 자동화가 진행되고 끝나면 로그인 성공 텍스트가 나타난다




반응형
반응형




사전 작업은 링크 참고


파이썬에서 selenium을 이용하여 크롬 브라우저 띄우기

http://yonoo88.tistory.com/1200 





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from selenium import webdriver
import time
 
driver = webdriver.Chrome('C://chromedriver.exe')
driver.implicitly_wait(3)
driver.get('http://www.naver.com')
 
driver.maximize_window()
 
 
driver.find_element_by_class_name('lg_local_btn').click()
driver.find_element_by_id('id').send_keys('아이디')
driver.find_element_by_id('pw').send_keys('비번')
driver.find_element_by_class_name('btn_global').click()
 
time.sleep(3)
driver.close()
cs



반응형

+ Recent posts