JAVA Selenium NoSuchElementException, elementclickinterceptedexception 해결

2021. 1. 18. 10:28Computer Science/Backend

JAVA Selenium

 

데이터 크롤링을 하게됐다. 자바를 메인언어로 바꾸겠다고 마음 먹은지 6개월정도 지났나 이제 좀 익숙해져 가고 있다. 두려움을 떨쳤다는 것 만으로도 스스로 기특하다고 생각하고 있다. 파이썬에서 자바로 언어를 바꿀 때 가장 답답한 부분은 함수형 사고방식에서 OOP형 사고방식으로 바꾸는 거였다. 뭐든 모르면 쫄기 마련인데, 하다보면 사실 몰랐을 뿐 어려운 건 아니었다는 생각을 하게 된다. 셀레니움 쓰다보면 자주 맞닥뜨리는 에러랑 간단한 해결법이다. 이런 글이라도 도움 되는 사람이 있겠지. 

 

1. NoSuchElementException

셀레니움을 쓰다보면 제일 많이 보이는 에러다. 그런 엘리먼트는 없어~ 이런 느낌이다. 기본적으로 셀레니움은 다음 코드를 가장 많이 사용한다.

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

// WebDriver
private WebDriver webDriver;


// Crawl by xpath
WebElement test = webDriver.findElement(By.xpath("//*[@id=\"main_contents\"]/div[4]/div[1]/a[2]"));

// Crawl by Selector
WebElement test2 = webDriver.findElement(By.cssSelector("#container > div:nth-child(4) > form > div.box_detail_point"));

중간에 뭘 많이 생략했지만 어쨌든 대충 이런 느낌이다. NoSuchElementException이 나타나는 경우는 xpath나 CssSelector를 잘못 입력해줬다는 의미다. 나같은 경우는 상품 리스트의 상세페이지에 일일이 접근해서 데이터를 가져와야 되는 상황이었다. 상세페이지마다 일정한 xpath에 일정한 값이 할당 돼 있어야 했는데, 값이 미묘하게 다른 경우 엄한 부분이 크롤링 되거나 해당 에러가 발생했다. 내가 해결한 방법은 그냥 try . . . catch문으로 해결해줬다. div값 하나가 다르다거나 그런 문제였기 때문이다.

 

try {

WebElement isub = webDriver.findElement(By.xpath("/html/body/div[2]/div[1]"));
temp.put("isub", isub.getText());

} catch (NoSuchElementExceiption se){

System.out.println("아래 상품에서 예외처리 발생 ");
WebElement isub = webDriver.findElement(By.xpath("/html/body/div[3]/div[1]"));
temp.put("isub", isub.getText());

}

temp는 무시해도 된다. 그냥 HashMap에 add하는 부분.. xpath값을 보면 div[2]랑 div[3]부분이 다른게 보일텐데 이런 방법으로 해결했다. 

 

2. ElementClickInterceptedException

이건 테스트중 클릭을 수행할 때 발생하는 에러다. 처음에 시도했던 방법은

WebElement clickUnderTen = webDriver.findElement(By.xpath("//*[@id=\"main_contents\"]/div[4]/div[1]"));
clickUnderTen.click();

이거였는데 

WebElement clickUnderTen = webDriver.findElement(By.xpath("//*[@id=\"main_contents\"]/div[4]/div[1]"));
clickUnderTen.sendKeys(Keys.ENTER);

click() -> sendKeys(Keys.ENTER)로 바꿔주니까 해결됐다. click()과 sendKeys()의 차이점은 다음과 같다.

 

- sendKeys() : 특정 값을 입력할 수 있는 input Box를 활용할 때 쓴다. text box를 엔터할 때 사용한다.

- click() : 링크를 클릭하고 페이지 로드가 완료될 때까지 기다린 후 다음 명령을 진행한다.