행위

자바 크롤링

DB CAFE

1 자바 크롤링

1.1 자바 설치

https://niceman.tistory.com/198

1.2 자바 크롤링 라이브러리

https://mobilemonitoringsolutions.com/8-most-popular-java-web-crawling-scraping-libraries/

1.3 크롤링 샘플

1.3.1 jsoup

  1. 샘플1 https://heodolf.tistory.com/101
  2. 샘플2 https://aboullaite.me/jsoup-html-parser-tutorial-examples/

1.3.2 셀레니엄

https://heodolf.tistory.com/103?category=887835 https://youtu.be/yQ20jZwDjTE

1.3.2.1 셀레니엄 설치

https://devqa.io/selenium-tutorial/

1.3.2.2 브라우져별 Web-Driver 설정

  • Chrome
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

WebDriver driver = new ChromeDriver();
  • Firefox
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Firefox.FirefoxDriver;

WebDriver driver = new FirefoxDriver();
  • Edge
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.edge.EdgeDriver;

WebDriver driver = new EdgeDriver();
  • Internet Explorer
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

WebDriver driver = new InternetExplorerDriver();

1.3.2.3 브라우져 네비게이션

  • URL 호출
//The short form
driver.get("https://devqa.io");

//The long form
driver.navigate().to("https://devqa.io");
  • 뒤로/앞으로 이동
driver.navigate().back();
driver.navigate().forward();
  • 새로 고침
driver.navigate().refresh();
  • 현재 URL 읽기
driver.getCurrentUrl();
  • 페이지 소스 읽기
driver.getPageSource();
  • 브라우져 종료
// 브라우져는 종료 하지 않음. 
driver.close();
// 브라우져 종료함.
driver.quit();

1.3.2.4 css Selector

1.3.2.4.1 css 셀렉터 레퍼런스

1.3.2.5 Xpath

1.3.2.5.1 Xpath 레퍼런스 설명

https://testmanager.tistory.com/121

// App.java
package selenium;
 
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
 
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
 
public class App {
    
    public static void main(String[] args) {
        
        // 현재 package의 workspace 경로, Windows는 [ chromedriver.exe ]
        Path path = Paths.get(System.getProperty("user.dir"), "src/main/resources/chromedriver");  // 현재 package의
        
        // WebDriver 경로 설정
        System.setProperty("webdriver.chrome.driver", path.toString());
        
        // WebDriver 옵션 설정
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");            // 전체화면으로 실행
        options.addArguments("--disable-popup-blocking");    // 팝업 무시
        options.addArguments("--disable-default-apps");     // 기본앱 사용안함
        
        // WebDriver 객체 생성
        ChromeDriver driver = new ChromeDriver( options );
        
        // 빈 탭 생성
        driver.executeScript("window.open('about:blank','_blank');");
        
        // 탭 목록 가져오기
        List<String> tabs = new ArrayList<String>(driver.getWindowHandles());
        
        
        
        // 첫번째 탭으로 전환
        driver.switchTo().window(tabs.get(0));
        
        // 웹페이지 요청
        driver.get("https://heodolf.tistory.com/101");
        
        // 웹페이지에서 글제목 가져오기
        WebElement page1_title = driver.findElementByXPath("//*[@id=\"content\"]/div[1]/div[1]/div/h1");
        if( page1_title != null  ) {
            System.out.println( page1_title.getText() );            
        }
        // 웹페이지 소스 출력
        //System.out.println( driver.getPageSource() );
        
        // 탭 종료
        driver.close();
        
        
        
        // 두번째 탭으로 전환
        driver.switchTo().window(tabs.get(1));
        
        // 웹페이지 요청
        driver.get("https://heodolf.tistory.com/102");
        
        // 웹페이지에서 글제목 가져오기
        WebElement page2_title = driver.findElementByXPath("//*[@id=\"content\"]/div[1]/div[1]/div/h1");
        if( page1_title != null  ) {
            System.out.println( page2_title.getText() );            
        }
        
        // 웹페이지 소스 출력
        //System.out.println( driver.getPageSource() );
        
        // 탭 종료
        driver.close();
        
        
        
        // 5초 후에 WebDriver 종료
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // WebDriver 종료
            driver.quit();
        }
    }
}
1.3.2.5.2 슬래쉬(/),점(.) 의미

https://dev.to/masihurmaruf/locator-strategy-xpath-54p7

1.3.2.5.3 Xpath 부모/형제/자식 찾기

https://www.guru99.com/xpath-selenium.html

1.3.2.5.3.1 정리 잘된곳

https://www.swtestacademy.com/xpath-selenium/#xpath-child

1.3.2.6 화면로딩완료까지 대기

WebDriverWait wait2 = new WebDriverWait(driver,30);
/* 클래스가 로딩시까지 대기 */
wait2.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@class='trip_result']"))); // //ul[@class='trip_result_list']
1.3.2.6.1 자바 sleep

time.sleep 지정한 시간만큼 지연 (프로세스 자체를 지정한 시간동안 기다림)

from time import sleep

sleep(3) //3초간 기다림
1.3.2.6.2 Implicitly Wait (암묵적 대기)

Selenium에서만 사용되는 특수한 메서드 지정한 시간만큼 대기 (브라우저에서 사용되는 엔진 자체에서 파싱되는 시간을 기다림) 모든 요소에 적용 sleep보다 낭비되는 시간이 적음

from selenium import webdriver

driver = webdriver.Chrome('chromedriver.exe')
driver.implicitly_wait(10)
1.3.2.6.3 Explicitly Wait (명시적 대기)

Selenium에서만 사용되는 특수한 메서드 조건이 True가 될 때 까지 지정한 시간만큼 대기 특정 요소에 적용

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser=webdriver.Chrome('chromedriver')
browser.get("https://www.naver.com/")
WebDriverWait(driver, 100).until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.header")))

클래스 로딩후 데이터 가져오기

List<WebElement> listOfElements = driver.findElements(By.xpath("//ul[@class='trip_result_list']/child::li")); // //li[starts-with(@class,'trip_result_item')]  //li[starts-with(@class,'trip_result_item')]
System.out.println(listOfElements.size());

for ( WebElement webElement : listOfElements )
{
    //System.out.println( webElement.getAttribute("value") );
    System.out.println( webElement.getText() );
    System.out.println( webElement.getAttribute(TEST_URL));
    System.out.println( "=============================" );
    /*if (webElement.getText().trim().equals("selenium ide")) {
        webElement.click();
        break;
    }*/
}

1.3.2.7 엘리먼트 체크 하기

import org.openqa.selenium.By;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
public class TestTestTest {

public static void main (String [] args) throws InterruptedException {
//Instantiation of driver object. To launch Firefox browser 
System.setProperty("webdriver.chrome.driver", "D:\\Selenium Environment\\Drivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
//To open gmail
driver.get("http://www.gmail.com");
//isDisplayed() method returns boolean value either True or False
Boolean Display = driver.findElement(By.xpath("//*[@id='next']")).isDisplayed();
//To print the value
System.out.println("Element displayed is :"+Display);
//isEnabled() method returns boolean value either True or False 
Boolean Enable = driver.findElement(By.xpath("//*[@id='next']")).isEnabled();
System.out.println("Element enabled is :"+Enable);
//Passing value as "softwaretestingmaterial" in the email field
driver.findElement(By.xpath("//*[@id='Email']")).sendKeys("<put_an_email_id>");
//to click on next button
driver.findElement(By.xpath("//*[@id='next']")).click();
//isSelected() method returns boolean value either True or False
Boolean Select = driver.findElement(By.xpath("//*[@id='PersistentCookie']")).isSelected();
System.out.println("Element selected is :"+Select);
} 
}

1.3.2.8 셀레니엄 모바일 모드

Map<String,String> mobileEmulation = new HashMap<>();        
mobileEmulation.put("deviceName", "Nexus 5");
//Driver SetUp
ChromeOptions options = new ChromeOptions();         
options.setExperimentalOption("mobileEmulation", mobileEmulation);

1.3.2.9 셀레니엄 페이징 반복 처리

import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class Exam1 {
	public static void main(String... args) {
		WebDriver driver = null;
		try {
			// drvier 설정 - 저는 d드라이브 work 폴더에 있습니다.
//			System.setProperty("webdriver.chrome.driver", "d:/eclipse/selenuim/chromedriver.exe");
			
		    final String WEB_DRIVER_ID = "webdriver.chrome.driver";
		    final String WEB_DRIVER_PATH = "D:/eclipse/selenium/chromedriver.exe";
		    System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);
		    
			// Chrome 드라이버 인스턴스 설정
			driver = new ChromeDriver();
			
			
			// 스크립트를 사용하기 위한 캐스팅
			JavascriptExecutor js = (JavascriptExecutor) driver;
			// 블로그 URL로 접속
			driver.get("https://nowonbun.tistory.com");
			// 대기 설정
			driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
			// xpath로 element를 찾는다. 이 xpath는 명월 일지 블로그의 왼쪽 메뉴의 Dev note의 Javascript, Jquery, Css 카테고리다.
			WebElement element = driver.findElement(By.xpath("//*[@id='leftside']/div[2]/ul/li/ul/li[1]/ul/li[6]/a"));
			// 클릭한다. 사실 element.click()로도 클릭이 가능한데 가끔 호환성 에러가 발생하는 경우가 있다.
			js.executeScript("arguments[0].click();", element);
			while (true) {
				try {
					// css selector로 element를 찾는다.
					element = driver.findElement(By.cssSelector("[href^='/626']"));
					// 클릭
					js.executeScript("arguments[0].click();", element);
					// 루프 정지
					break;
				} catch (Throwable e) {
					// 해당 element가 없으면 아래의 다음 페이지 element를 찾는다.
					element = driver.findElement(By.cssSelector(".paging li.active+li > a"));
					// 클릭
					js.executeScript("arguments[0].click();", element);
				}
			}
			// id가 promptEx인 데이터를 찾는다.
			element = driver.findElement(By.xpath("//*[@id='promptEx']"));
			// 버튼은 클릭이 되는데 link 계열은 script로 클릭해야 한다.
			element.click();
			// xpath로 팝업의 dom를 찾는다.
			element = driver.findElement(By.xpath("/html/body/div[6]/div/div/div[2]/div/form/input"));
			// input text에 test의 값을 넣는다.
			element.sendKeys("test");
			// 5초 기다린다.
			Thread.sleep(5000);
			// xpath로 팝업의 dom를 찾는다.
			element = driver.findElement(By.xpath("/html/body/div[6]/div/div/div[2]/div/form/input"));
			// 속성 value를 출력한다.
			System.out.println(element.getAttribute("value"));
			// .article의 글에 p 태그의 속성을 전부 가져온다.
			List<WebElement> elements = driver.findElements(By.cssSelector(".article p"));
			for (WebElement ele : elements) {
				// 속성의 NodeText를 전부 출력한다.
				System.out.println(ele.getText());
			}
		} catch (Throwable e) {
			e.printStackTrace();
		} finally {
			driver.close();
		}
	}
}

1.3.2.10 html로 저장

// App.java 
package selenium; 
import java.io.File;
import java.io.FileOutputStream; 
public class App { 
    // 중략 
    public static void saveHtml(String filename, byte[] html) {
        File savedir = new File("C:/work/java/crawler/html");
        if( !savedir.exists() ) {
            savedir.mkdirs();
        }
 
        File file = new File(savedir, filename);
        try {
            FileOutputStream out = new FileOutputStream(file);
            out.write( html );
            out.close();            
        } catch (Exception e) {
            e.printStackTrace();
        }        
    }    
 
    // 중략
    
}

1.3.2.11 자바스크립트 이용

import java.util.List;	
import java.util.concurrent.TimeUnit;	
import org.openqa.selenium.By;	
import org.openqa.selenium.JavascriptExecutor;	
import org.openqa.selenium.WebDriver;	
import org.openqa.selenium.WebElement;	
import org.openqa.selenium.chrome.ChromeDriver;	
 	
public class Example {	
  public static void main(String... args) {	
    WebDriver driver = null;	
    try {	
      // drvier 설정 - 저는 d드라이브 work 폴더에 있습니다.	
      System.setProperty("webdriver.chrome.driver", "d:\\work\\chromedriver.exe");	
      // Chrome 드라이버 인스턴스 설정	
      driver = new ChromeDriver();	
      // 스크립트를 사용하기 위한 캐스팅	
      JavascriptExecutor js = (JavascriptExecutor) driver;	
      // 블로그 URL로 접속	
      driver.get("https://nowonbun.tistory.com");	
      // 대기 설정	
      driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);	
      // xpath로 element를 찾는다. 이 xpath는 명월 일지 블로그의 왼쪽 메뉴의 Dev note의 Javascript, Jquery, Css 카테고리다.	
      WebElement element = driver.findElement(By.xpath("//*[@id='leftside']/div[2]/ul/li/ul/li[1]/ul/li[6]/a"));	
      // 클릭한다. 사실 element.click()로도 클릭이 가능한데 가끔 호환성 에러가 발생하는 경우가 있다.	
      js.executeScript("arguments[0].click();", element);	
      while (true) {	
        try {	
          // css selector로 element를 찾는다.	
          element = driver.findElement(By.cssSelector("[href^='/626']"));	
          // 클릭	
          js.executeScript("arguments[0].click();", element);	
          // 루프 정지	
          break;	
        } catch (Throwable e) {	
          // 해당 element가 없으면 아래의 다음 페이지 element를 찾는다.	
          element = driver.findElement(By.cssSelector(".paging li.active+li > a"));	
          // 클릭	
          js.executeScript("arguments[0].click();", element);	
        }	
      }	
      // id가 promptEx인 데이터를 찾는다.	
      element = driver.findElement(By.xpath("//*[@id='promptEx']"));	
      // 버튼은 클릭이 되는데 link 계열은 script로 클릭해야 한다.	
      element.click();	
      // xpath로 팝업의 dom를 찾는다.	
      element = driver.findElement(By.xpath("/html/body/div[6]/div/div/div[2]/div/form/input"));	
      // input text에 test의 값을 넣는다.	
      element.sendKeys("test");	
      // 5초 기다린다.	
      Thread.sleep(5000);	
      // xpath로 팝업의 dom를 찾는다.	
      element = driver.findElement(By.xpath("/html/body/div[6]/div/div/div[2]/div/form/input"));	
      // 속성 value를 출력한다.	
      System.out.println(element.getAttribute("value"));	
      // .article의 글에 p 태그의 속성을 전부 가져온다.	
      List<WebElement> elements = driver.findElements(By.cssSelector(".article p"));	
      for (WebElement ele : elements) {	
        // 속성의 NodeText를 전부 출력한다.	
        System.out.println(ele.getText());	
      }	
    } catch (Throwable e) {	
      e.printStackTrace();	
    } finally {	
      driver.close();	
    }	
  }	
}

1.3.2.12 트위터 크롤링

1.3.2.12.1 JSOAP 이용
// App.java
 
package selenium;
 
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
 
public class App {
    
    // 중략
 
    public static void runJsoup(String URL) throws Exception { 
        // 1. Connection 객체 생성
        Connection conn = Jsoup.connect(URL);
        conn.header("Content-Type", "application/html;charset=UTF-8");
        conn.timeout(30*1000);
 
        // 2. HTML 파싱
        Document html = conn.get();
        
        // 3. HTML 저장.
        saveHtml("twitter-jsoup.html", html.toString() );
 
        try {
            // 4. 트윗 목록 조회
            Element parent = html.selectFirst("section[aria-labelledby*=\"accessible-list\"]");
            if(parent == null ) { throw null; }
        
            // 5. 트윗 콘텐츠 조회
            Elements contents = parent.select("div.css-1dbjc4n.r-my5ep6.r-qklmqi.r-1adg3ll");
            System.out.println( "조회된 콘텐츠 수 : "+contents.size() );
            
            // 6. 트윗 내용 파싱.
            if( contents.size() > 0 ) {
                // 7. 트윗 상세 내용 탐색
                for(Element content : contents ) {
                    try {
                        String username = content.selectFirst("span > span.css-901oao.css-16my406.r-1qd0xha.r-ad9z0x.r-bcqeeo.r-qvutc0").text();
                        String id = content.selectFirst("span.css-901oao.css-16my406.r-1qd0xha.r-ad9z0x.r-bcqeeo.r-qvutc0").text();
                        String text = content.selectFirst("div.css-901oao.r-hkyrab.r-1qd0xha.r-a023e6.r-16dba41.r-ad9z0x.r-bcqeeo.r-bnwqim.r-qvutc0").text();
 
                        System.out.println( "========================" );
                        System.out.println( username+" "+id );
                        System.out.println( text );
                        System.out.println( "========================" );
                    } catch ( Exception e ) {
                        // pass
                    }
                }
            }
        } catch ( Exception e ) {
            System.out.println("목록을 찾을 수 없습니다.");
        } finally {
            // 3. HTML 저장.
            saveHtml("twitter-jsoup-loaded.html", html.toString() );
        }
    }
    
    // 중략
    
}
1.3.2.12.2 세레니엄 이용
// App.java
 
package selenium;
 
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Properties;
 
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
 
public class App {
    
    // 중략
 
    public static void runSelenium(String URL) throws Exception {
        // 1. WebDriver 경로 설정
        Path path = Paths.get(System.getProperty("user.dir"), "src/main/resources/chromedriver.exe");
        System.setProperty("webdriver.chrome.driver", path.toString());
        
        // 2. WebDriver 옵션 설정
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");          // 최대크기로
        options.addArguments("--headless");                 // Browser를 띄우지 않음
        options.addArguments("--disable-gpu");              // GPU를 사용하지 않음, Linux에서 headless를 사용하는 경우 필요함.
        options.addArguments("--no-sandbox");               // Sandbox 프로세스를 사용하지 않음, Linux에서 headless를 사용하는 경우 필요함.
        
        // 3. WebDriver 객체 생성
        ChromeDriver driver = new ChromeDriver( options );
        
        // 4. 웹페이지 요청
        driver.get(URL);
        
        // 5. HTML 저장.
        saveHtml("twitter-selenium.html", driver.getPageSource() );
        
        try {
            // 6. 트윗 목록 Block 조회, 로드될 때까지 최대 30초간 대기
            WebDriverWait wait = new WebDriverWait(driver, 30);
            WebElement parent = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("section[aria-labelledby*=\"accessible-list\"]")));
            
            // 7. 트윗 콘텐츠 조회
            List<WebElement> contents = parent.findElements(By.cssSelector("div.css-1dbjc4n.r-my5ep6.r-qklmqi.r-1adg3ll"));
            System.out.println( "조회된 콘텐츠 수 : "+contents.size() );
            
            if( contents.size() > 0 ) {
                // 8. 트윗 상세 내용 탐색
                for(WebElement content : contents ) {
                    try {
                        String username = content.findElement(By.cssSelector("span > span.css-901oao.css-16my406.r-1qd0xha.r-ad9z0x.r-bcqeeo.r-qvutc0")).getText();
                        String id = content.findElement(By.cssSelector("span.css-901oao.css-16my406.r-1qd0xha.r-ad9z0x.r-bcqeeo.r-qvutc0")).getText();
                        String text = content.findElement(By.cssSelector("div.css-901oao.r-hkyrab.r-1qd0xha.r-a023e6.r-16dba41.r-ad9z0x.r-bcqeeo.r-bnwqim.r-qvutc0")).getText();
                        
                        System.out.println( "========================" );
                        System.out.println( username+" "+id );
                        System.out.println( text );
                        System.out.println( "========================" );
                    } catch ( NoSuchElementException e ) {
                        // pass
                    }
                }
            }
            
        } catch ( TimeoutException e ) {
            System.out.println("목록을 찾을 수 없습니다.");
        } finally {            
            // 9. HTML 저장.
            saveHtml("twitter-selenium-loaded.html", driver.getPageSource() );
        }
                       
        // WebDriver 종료
        driver.quit();
    }
    
    // 중략
}

1.3.2.13 호텔스컴바인

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
 
public class SeleniumTest {
 
    public static void main(String[] args) {
 
        SeleniumTest selTest = new SeleniumTest();
        selTest.crawl();
        
    }
 
    
    //WebDriver
    private WebDriver driver;
    
    private WebElement webElement;
    
    //Properties
    public static final String WEB_DRIVER_ID = "webdriver.chrome.driver";
    public static final String WEB_DRIVER_PATH = "D:/eclipse/selenium/chromedriver.exe";
    
    //크롤링 할 URL
    private String base_url;
    
    public SeleniumTest() {
        super();
 
        //System Property SetUp
        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);
        Map<String,String> mobileEmulation = new HashMap<>();        
        mobileEmulation.put("deviceName", "Nexus 5");
        //Driver SetUp
         ChromeOptions options = new ChromeOptions();         
         options.setExperimentalOption("mobileEmulation", mobileEmulation);         
         
         options.setCapability("ignoreProtectedModeSettings", true);
         driver = new ChromeDriver(options);
        
        base_url = "https://www.hotelscombined.co.kr/hotels/%EB%8B%A4%EB%82%AD,%EB%B2%A0%ED%8A%B8%EB%82%A8-c42700/2021-04-27/2021-05-04/2adults?placeId=P65216&placeName=place:Da_Nang&sort=rank_a";
        
        
        
    }
 
    public void crawl() {
 
        try {
            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
            driver.get(base_url);

            driver.manage().timeouts().pageLoadTimeout(3,TimeUnit.SECONDS);
            System.out.println("===================");
        	WebElement list = (WebElement) driver.findElement(By.xpath("/html/body/app/ng-component/div/div/main/ng-component/hotels-result-page/div/div[2]/hotels-toolbar/div[1]/button[1]/div[1]/div/div"));
        	System.out.println("===================");
        	System.out.println(list.getTagName());
        	System.out.println(list.getText());            
            try {
            	WebDriverWait wait = new WebDriverWait(driver, 5);
                WebElement parent = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/app/ng-component/div/div/main/ng-component/hotels-result-page/div/div[3]/div/div/div[1]/div/div[3]/hotels-result-card/div/div/hotels-result-card-property-info/h4")));
                System.out.println(parent.getTagName());
                System.out.println(parent.getText());
                
                
                
//            	WebElement button = (WebElement) driver.findElements(By.xpath("//button[@class='moreButton']"));
//            	driver.find_element_by_xpath("//button[@class='moreButton']").click()
//            	button.click();
//            	System.out.println( driver.getPageSource() );
            } catch (NoSuchElementException e){
//            	fail();
            	e.printStackTrace();
            	
            }
            //iframe으로 구성된 곳은 해당 프레임으로 전환시킨다.
//            driver.switchTo().frame(driver.findElement(By.id("loginForm")));
            
            //iframe 내부에서 id 필드 탐색
//            webElement = driver.findElement(By.id("id"));
//            String daum_id ="your id";
//            webElement.sendKeys(daum_id);
//            
//            //iframe 내부에서 pw 필드 탐색
//            webElement = driver.findElement(By.id("inputPwd"));
//            String daum_pw ="your pw";
//            webElement.sendKeys(daum_pw);
//            
// 
//            //로그인 버튼 클릭
//            webElement = driver.findElement(By.id("loginSubmit"));
//            webElement.submit();
//            
//            
//            Thread.sleep(20000);
    
        } catch (Exception e) {
            
            e.printStackTrace();
        
        } finally {
 
//            driver.close();
        }
 
    }
 
}

1.4 크롤링 툴

https://gdbs.tistory.com/94

1.5 셀리니엄 서버 구축

1.5.1 리모트 셀리니엄

selenium-server-standalone-3.141.59.jar 다운로드 후

java -jar selenium-server-standalone-3.141.59.jar
driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), DesiredCapabilities.chrome());

1.5.2 JAR파일 커맨트 라인으로 실행하기

https://dev.to/mwickrmanayaka/dealing-with-jar-files-from-command-line-in-a-selenium-project-2iea

1.5.3 셀리니엄 그리드

  • 콘솔로 실행 가능

https://www.guru99.com/introduction-to-selenium-grid.html


1.5.4 도커

https://github.com/SeleniumHQ/docker-selenium/blob/trunk/README.md