"자바 크롤링"의 두 판 사이의 차이
DB CAFE
(→셀레니엄 모바일 모드) |
(→셀레니엄) |
||
15번째 줄: | 15번째 줄: | ||
https://heodolf.tistory.com/103?category=887835 | https://heodolf.tistory.com/103?category=887835 | ||
+ | ==== css Selector ==== | ||
+ | ==== Xpath ==== | ||
+ | https://testmanager.tistory.com/121 | ||
<source lang=java> | <source lang=java> | ||
// App.java | // App.java |
2021년 4월 26일 (월) 23:08 판
thumb_up 추천메뉴 바로가기
- DBA { Oracle DBA 명령어 > DBA 초급 과정 > DBA 고급 과정 }
- 튜닝 { 오라클 튜닝 목록 }
- 모델링 { 데이터 모델링 가이드 }
목차
1 자바 크롤링[편집]
1.1 자바 설치[편집]
1.2 자바 크롤링 라이브러리[편집]
https://mobilemonitoringsolutions.com/8-most-popular-java-web-crawling-scraping-libraries/
1.3 크롤링 샘플[편집]
1.3.1 jsoup[편집]
1.3.2 셀레니엄[편집]
https://heodolf.tistory.com/103?category=887835
1.3.2.1 css Selector[편집]
1.3.2.2 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.3 셀레니엄 모바일 모드[편집]
Map<String,String> mobileEmulation = new HashMap<>();
mobileEmulation.put("deviceName", "Nexus 5");
//Driver SetUp
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("mobileEmulation", mobileEmulation);
1.3.2.4 셀레니엄 페이징 반복 처리[편집]
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.5 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.6 트위터 크롤링[편집]
1.3.2.6.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.6.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();
}
// 중략
}