project_0313 selenium 오류

ooohyooo·2024년 3월 13일

myproject

목록 보기
16/44
2024-03-12 10:26:37 [http-nio-8082-exec-7] [ERROR] o.a.c.c.C.[.[.[.[dispatcherServlet] -
				Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.NoSuchMethodError: 'org.openqa.selenium.chromium.ChromiumOptions org.openqa.selenium.chrome.ChromeOptions.addArguments(java.lang.String[])'] with root cause
java.lang.NoSuchMethodError: 'org.openqa.selenium.chromium.ChromiumOptions org.openqa.selenium.chrome.ChromeOptions.addArguments(java.lang.String[])'

제공된 pom.xml 파일은 크롤링 코드와 직접적으로 관련이 없는 것으로 보입니다. 그러나 몇 가지 개선 및 주의사항이 있습니다:

의존성 버전 확인:

현재 Selenium의 버전은 4.9.0이지만, 가장 최신 버전을 사용하는 것이 좋습니다. Maven Central Repository를 통해 확인하여 필요한 버전으로 업데이트하세요.
자바 버전 지정:

현재 Java 버전이 17로 지정되어 있습니다. 사용하고 있는 Java 버전과 호환되는 다른 라이브러리 및 프레임워크 버전을 확인하세요.
Maven 빌드 프로파일 확인:

spring-boot-starter-parent의 버전은 3.1.9-SNAPSHOT으로 지정되어 있는데, 이는 현재 존재하지 않는 것으로 보입니다. 가장 최신의 안정된 버전을 사용하거나 프로젝트에 맞는 버전을 찾아서 지정하세요.
ChromiumDriver 사용 확인:

코드에서 ChromiumDriver를 사용하려면 해당 라이브러리가 의존성으로 추가되어 있어야 합니다. 필요한 경우 Selenium 버전에 따라 적절한 의존성을 추가하세요.
Lombok 관련 설정 확인:

org.projectlombok:lombok 의존성은 optional로 설정되어 있습니다. 이것이 의도된 것이라면 그대로 두세요. 그러나 Lombok을 사용 중이라면 해당 의존성을 필수로 설정하세요.
Spring Boot Maven Plugin 설정 확인:

Spring Boot Maven Plugin 설정에서 paketobuildpacks/builder-jammy-base:latest를 사용하고 있습니다. 이것이 의도된 것인지 확인하고 필요한 경우 수정하세요.

  • 일정 크롤링

    • List elements = driver.findElements(By.cssSelector(".relative"));로 데이터를 불러오려고 했는데 안되서 gpt한테 물어봤음

      만약 .relative로 태그를 지정했는데 원하는 값을 찾아오지 못한다면, 다음과 같은 몇 가지 원인이 있을 수 있습니다:
      동적 로딩: 페이지가 JavaScript나 Ajax 등을 사용하여 동적으로 데이터를 로드하는 경우가 있습니다. 이 경우 WebDriver가 페이지 로드를 기다리도록 하는 것이 좋습니다. WebDriverWait를 사용하여 해당 요소가 나타날 때까지 대기하는 방법을 시도해보세요.
      CSS 선택자 확인: .relative가 실제로 원하는 요소를 지정하는 올바른 CSS 선택자인지 확인하세요. Chrome 브라우저의 개발자 도구를 사용하여 해당 요소를 직접 확인하고 올바른 선택자를 찾아낼 수 있습니다.
      프레임/윈도우 전환: 페이지에 프레임이나 다른 윈도우가 있는 경우, 올바른 프레임이나 윈도우로 전환하는지 확인하세요. driver.switchTo().frame() 또는 driver.switchTo().window() 메서드를 사용하여 전환할 수 있습니다. 라고 말해줬고!

      // 웹 페이지 로드를 위한 대기
            WebDriverWait wait = new WebDriverWait(driver, 10);
            wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".relative")));
      
            List<WebElement> elements = driver.findElements(By.cssSelector(".relative"));
      
            for (WebElement element : elements) {
                String title = element.getText();
                System.out.println(title);
            }
    • 이런식으로 페이지 로드대기를 걸어줘보래

    • 그리고 The constructor WebDriverWait(WebDriver, int) is undefined 생성자 오류가 떠서 Duration 객체를 사용하여 타임아웃을 설정하는 방식으로 변경해보라함

 // 웹 페이지 로드를 위한 대기
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".relative")));

        List<WebElement> elements = driver.findElements(By.cssSelector(".relative"));

        for (WebElement element : elements) {
            String title = element.getText();
            System.out.println(title);
        }


잘나온다!
아니다....내가 원하는 데이터가 안나온다......

  • radio check시켜서 데이터 뽑아야하는데 자꾸 안해줘... timeout오류나고 고치면 호환 오류 같은거 나와ㅡㅡ

  • 오류: org.openqa.selenium.ElementNotInteractableException: element not interactable
    (Session info: chrome-headless-shell=122.0.6261.112)
    • "element not interactable" 오류는 Selenium이 해당 요소와 상호 작용할 수 없을 때 발생합니다. 이 오류는 대상 요소가 클릭이나 키 입력과 같은 상호 작용을 수행할 수 없는 상태에 있을 때 발생할 수 있습니다.
      일반적인 이유로는 다음과 같습니다:
      요소가 숨겨져 있거나 비활성 상태인 경우: 클릭하려는 요소가 화면에 표시되거나 활성 상태가 아닌 경우 이 오류가 발생할 수 있습니다. 페이지 로딩이나 상태 변화를 기다린 후에 클릭을 시도해 보세요.
      다른 요소가 클릭 대상을 가리는 경우: 다른 요소가 클릭하려는 요소를 가리고 있을 수 있습니다. 페이지의 레이아웃을 확인하고, 필요에 따라 스크롤이나 다른 조치를 취하여 클릭 가능한 상태로 만드세요.
      JavaScript 이벤트 또는 애니메이션이 동작 중인 경우: 페이지에 JavaScript 이벤트나 애니메이션이 실행 중인 경우 클릭이 차단될 수 있습니다. 이 경우 애니메이션이 완전히 종료될 때까지 기다리거나, JavaScript 이벤트가 완료되기를 기다려보세요.
      브라우저 크기나 위치 문제: 브라우저 창이 너무 작거나 요소가 화면에 보이지 않는 위치에 있을 경우 클릭이 불가능할 수 있습니다.
      이러한 일반적인 원인들을 확인하고, 상황에 따라 Selenium 코드를 조정하여 문제를 해결할 수 있습니다.
  • 하... 진짜 너무 짜증난다.....url에 데이터 이상하게 나와서 전체보기 눌러서 전체 일정 나오게 하려고 했는데 태그가 너무 안먹어서 포기하고 그냥 url로만 하니까 잘나와....진짜 짜쯩난다...
try {
			    	// 크롤링할 웹 페이지 URL
			        String url = "https://kovo.co.kr/redsparks/game/v-league?first=%EC%9D%BC%EC%A0%95+%EB%B0%8F+%EA%B2%B0%EA%B3%BC";
			        // 웹 페이지 열기
			        driver.get(url);

			        // 웹 페이지 로드를 위한 대기
			        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
			        
			     // 버튼을 찾아 클릭
//			        WebElement button = driver.findElement(By.cssSelector(".main-container section div:nth-child(2) button")); // 버튼의 CSS 선택자를 넣어주세요
//			        button.click();
			        
			        // 라디오 버튼이 선택된 후에 나타나는 요소를 기다림
			        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("tr"))); 
//			        
			        List<WebElement> elements = driver.findElements(By.cssSelector("tr"));
			        
			        // 결과를 파일에 저장
//			        saveToFile(elements, "output.txt");
			        for (WebElement element : elements) {
		                String text = element.getText();
		                System.out.println(text);
		            }

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

-> 버튼 클릭 써봤다가 그냥했다가 이것저것 해본 코드다...어이없네...

  • 크롤링한 정보 csv로 빼기

    
    // CSV 파일에 데이터 쓰기
    			            saveToCSV(elements, "output.csv");
                      
    private void saveToCSV(List<WebElement> elements, String filePath) throws IOException {
          try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8"))) {
              // CSV 헤더 작성 (필요에 따라 수정)
              writer.write("Column1,Column2,Column3\n");
    
              for (WebElement element : elements) {
                  // 가져온 데이터를 CSV 파일에 작성 (필요에 따라 수정)
                  String text = element.getText().replace("\n", ",");
                  writer.write(text);
            ![](https://velog.velcdn.com/images/ohyo555/post/8e2874f0-7079-4f92-bc6c-3eca0f620272/image.PNG)
        writer.newLine();
              }
              System.out.println("csv 파일 저장!!!");
          }
      }
    • 한글 인코딩 안되고 난리다...
    • writer.write("\uFEFF"); 이거 적어주니까 된다...^^...
  • 또 문제가 생겼다^^

    - 태그가 tr,td 형태로 있는데 tr은 크롤링 성공시키고, td는 찾을 수 없단다...
    - 진짜 나보고 어쩌란말이야....?
    - 그래서 쌤이 https://www.swtestacademy.com/css-selenium/ 여기 들어가서 할 수 있는거 다해보래..
    - ㅋ...xPath로 태그 순서대로 다 끌어와서 하니까 된다...ㅋㅎㅋㅎㅋㅎ
    이렇게 찾으면 나옴(xPath)
    - 근데 저 태그가 (//*[@id="root"]/article/div/article/section/article/section[2]/article/section[2]/table/tbody/tr[1]/td[1]) 이런식으로 []에 인덱스만 계속 바뀌는 식이라서
    - 너무 반복문을 오랜만에 써서 그런가...헷갈린다ㅋ..무튼 저런식으로 하니까 요소의 요소만큼을 반복해서 너무 많이 반복시킴
    - 그래서 쌤한테 또 물어봄ㅎ 그래서 get써서 해보라고 했는데 말해주자마자 바로 성공했다..하..

    - 근데 여기서 또 문제ㅎㅎㅎ

    - 데이터가 이런식으로 나와... 한 셀에 여러 값이 있을때 줄바꿈시켜서 저런식으로 나오는거야 그래서 정제를 해줘야겠다..싶었지...근데 너무 헷갈려 심지어 나는 csv로 받을꺼라 값마다 ,가 붙어야해서 별걸 다해봤다...
    - 그래서 생각한게 그냥 냅다 내멋대로 문자 치환함ㅎ 근데 진짜 어쩔수가 없어...

String t = text.getText().replace("\n", ",").replace(")","),").replace("여자", ",여자,").replace("19", ",19").replace("16", ",16").replace(":00",":00,").replace(":30",":30,").replace("육관","육관,").replace("움","움,").replace("ER","ER,").replace("nd","nd,");
        			String a = t.replace(".,", ".").replace(",,", ",").replace(" , ", " ");

- 일단 이렇게 해서
여기까진 나왔다.. ,,가 ,로 안바뀌는거랑 저 방송사를 한셀에 담기도록 다시 데이터를 정제시켜야겠구나...

replace() 메서드의 오해:
replace() 메서드는 문자열에서 지정된 문자 시퀀스의 모든 발생을 대체합니다. 만약 t가 여러 개의 쉼표를 연속해서 포함하고 있다면, 단일 replace() 호출로 모든 쉼표를 하나로 대체할 수 없습니다.

다음은 예시입니다:

java
Copy code
String t = "abc,,def,,,ghi";
String a = t.replace(",,", ","); 
System.out.println(a); // 출력: abc,def,,ghi
이 예제에서는 ",,"의 첫 번째 발생만 ","로 대체되어 abc,def,,ghi가 됩니다.

만약 모든 연속된 쉼표 시퀀스를 하나의 쉼표로 대체하고 싶다면, 반복문이나 정규 표현식을 사용해야 할 수도 있습니다.

정규 표현식을 사용하여 이를 수행하는 방법을 살펴보겠습니다:

```java
Copy code
String t = "abc,,def,,,ghi";
String a = t.replaceAll(",+", ",");
System.out.println(a); // 출력: abc,def,ghi
이 코드는 하나 이상의 쉼표 시퀀스를 모두 한 개의 쉼표로 대체하여 abc,def,ghi가 되도록 합니다.
  • replace(",,", ",")가 안돼서 GPT한테 물었는게 이렇게 말했다 근데 나는 하나뿐인데 무튼 저거 적용해도 안됨...
  • 쌤이 GPT한테 온갖 방법을 다 물어봐줘서 했는데 얜 그냥 포기 아무것도 안돼...
    1. **문자열 Caching**: 자바에서 문자열은 불변(immutable)이므로, `replace()` 메서드를 사용하더라도 원본 문자열이 변경되지는 않습니다. 대신 새로운 문자열이 생성되어 반환됩니다. 따라서 `replace()` 메서드 후에 변경된 문자열을 적절한 변수에 할당해야 합니다.
    2. **실행 순서**: 여러 `replace()` 호출이 있을 경우, 이들이 어떤 순서로 실행되는지 확인해야 합니다. 후속 `replace()` 작업이 이전에 만들어진 쉼표를 다시 변경할 수 있습니다.
    3. **특수 문자**: 원문에서 사용한 문자가 실제로 일반 쉼표인지, 아니면 시각적으로 유사하지만 다른 문자(예: 전각 쉼표 등)인지 확인하세요.
    4. **공백 포함**: 원본 문자열에 `,` 사이에 공백이 포함되어 있는 경우, `replace(",,", ",")`는 예상대로 작동하지 않을 수 있습니다. 예를 들어, `, ,`를 찾아서 `,`로 바꾸려면 다른 replace를 사용해야 합니다.
    5. 문자열 인코딩 문제: 웹 페이지에서 추출한 문자열이 특정 인코딩을 사용하고 있을 경우, 이는 인코딩 문제일 수 있습니다. 이 경우, 웹 페이지의 인코딩을 확인하고, 자바에서 문자열을 처리할 때 동일한 인코딩을 사용해야 합니다
    6. 특수문자 사용:화면상에서 보이는 `,`가 실제로는 다른 문자일 수 있습니다. 예를 드는 경우가 전각 쉼표 같은 다른 유형의 쉼표일 수 있는데, 이를 처리하기 위해 다음과 같이 할 수 있습니다

응 다안됨~ㅎ 포기 걍 txt파일 받아서 내가 직접 수정해서 csv로 받겠다...


쌤이 stringbuiler랑 stirngbuffer로도 해보라고 해서 했는데 이것도 안된다 진짜로 정신나갈거같아서 포기한다..

  • 아 또 문제임ㅋㅋㅋㅋㅋㅋㅋㅋ이제 경기컬럼에 페퍼저축은행,0 : 3,정관장 이렇게 나뉘는것도 해결하려는데
String[] data = line.split(",");
        	System.out.println(data[0]);
        	System.out.println(data[1]);

이런식으로 나누는데 data[1]을 못알아먹는다.. ,이게 뭔가 이상한가바...이유를 알 수가 없다...
무튼 그래서

StringTokenizer tokenizer = new StringTokenizer(line, ",");
        	
        	int index = 0; // 인덱스 카운터를 초기화합니다.
            StringBuilder concatenatedToken = new StringBuilder(); // 토큰을 결합할 StringBuilder를 초기화합니다.
            // 각 데이터를 다음 행의 새 셀에 쓰도록 합니다.
            while (tokenizer.hasMoreTokens()) {
            	
                String token = tokenizer.nextToken().trim();
                
                if (index >= 3 && index <= 5) { // 인덱스가 세 번째, 네 번째 또는 다섯 번째인지 확인합니다.
                    concatenatedToken.append(token); // 토큰을 StringBuilder에 추가합니다.
                    if (index != 5) { // 마지막 토큰이 아닌 경우에만 공백을 추가합니다.
                        concatenatedToken.append(" ");
                    }
                    
                } else if (index == 11) { // 인덱스가 아홉 번째인 경우
                    concatenatedToken.append(",").append(token); // 쉼표와 함께 토큰을 추가합니다.
                } else {
                    System.out.println("인덱스: " + index + ", 토큰: " + token); // 인덱스와 토큰을 출력합니다.
                    writer.write(token + ",");
                }
                index++; // 인덱스 카운터를 증가시킵니다.
            }
            // 결합된 토큰을 단일 토큰으로 쓰도록 합니다.
            System.out.println("인덱스: 2-4, 결합된 토큰: " + concatenatedToken.toString());
            writer.write(concatenatedToken.toString() + ",");
            writer.write("\n");

StringTokenizer 써서 해결했다... 이제 진짜 끝인가...

0개의 댓글