Jsoup 크롤링 안되는 경우 - Jsoup keulolling andoeneun gyeong-u

웹 크롤링¶

웹 페이지에 있는 필요한 정보들을 사용할 수 있습니다.

jsoup¶

jsoup은 java에서 사용할 수 있는 html parser 패키지입니다.

설치 및 라이브러리 추가¶

jsoup 사이트에 접속해서 최신 jar 파일을 다운받습니다. 다운받은 jar 파일을 라이브러리에 추가하는 방법은 프로젝트 페이지의 외부 라이브러리 이용을 참조합니다.

간단한 예제¶

jsoup이 잘 작동하는지 알아보기위해 다음 코드를 실행해봅니다.

import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; /** * A simple example, used on the jsoup website. */ public class Wikipedia { public static void main(String[] args) throws IOException { Document doc = Jsoup.connect("//en.wikipedia.org/").get(); log(doc.title()); Elements newsHeadlines = doc.select("#mp-itn b a"); for (Element headline : newsHeadlines) { log("%s\n\t%s", headline.attr("title"), headline.absUrl("href")); } } private static void log(String msg, String... vals) { System.out.println(String.format(msg, vals)); } }

  • org.jsoup.Jsoup 객체는 jsoup을 편리하게 시작할 수 있는 여러 가지 정적 메소드들을 제공합니다.
  • Jsoup.connect(‘url’) 메소드를 이용해서 지정된 url에 접속을 위한 Connection 객체를 반환받습니다.
  • Connection.get() 메소드를 이용하여 웹페이지를 가져와 파싱을 한 후 Document 객체를 반환합니다.
  • Document 객체의 select 메소드의 인자로 CSS 선택자를 이용해 지정한 성분들 newsHeadlines을 찾습니다.
  • 성분들을 순회하며 각 성분의 titlehref 속성값을 출력합니다.

jsoup 소개¶

jsoup은 html 파일을 파싱하여 html 성분들을 jsoup 성분(Element) 객체로 만듭니다. 즉, HTML 페이지를 웹브라우저가 사용하는 DOM(Document Object Model) 형식으로 변경합니다.

jsoup은 다음과 같은 기능들을 갖추고 있습니다.

  • html을 파일, url, 문자열로부터 파싱합니다.
  • CSS 선택자 또는 DOM 순회를 이용하여 원하는 자료를 찾거나 추출합니다.
  • HTML 성분, 속성 및 텍스트를 조작합니다.
  • HTML을 보기 편하게 출력합니다.

문서 가져오기¶

파싱할 문서는 url 또는 파일, 문자열을 이용해서 가져올 수 있습니다. 자세한 것은 Jsoup 클래스 메소드를 참조하시기 바랍니다.

url 이용¶

url 주소를 지정하여 웹사이트에 접속해서 원하는 문서를 가져올 수 있습니다. Jsoup.connect('url').get() 메소드를 이용해서 웹페이지를 파싱하여 Document 객체를 반환합니다.

Document doc = Jsoup.connect("//example.com/").get(); String title = doc.title();

진행중에 오류가 발생하면 예외 IOException을 발생시키기 때문에 예외처리를 해주어야 합니다.

파일 이용¶

파일로 저장되어 있는 HTML 파일을 읽어서 파싱을 합니다. Jsoup.parse(File in, String encoding, String baseUri)를 이용하면 encoding 인코딩 파일 객체 in으로부터 파싱을 할 수 있습니다. baseUri는 HTML 문서 중 상대적인 URL을 처리할 때 baseUri를 앞에 붙여서 처리를 하기 위한 것입니다.

File input = new File("/tmp/input.html"); Document doc = Jsoup.parse(input, "UTF-8", "//example.com/");

예외 IOException이 발생할 경우를 위해 예외처리를 해야합니다.

parse(File in, String encoding)를 이용하면 baseUri는 자동으로 파일의 위치가 됩니다.

문자열 이용¶

문자열을 파싱할 수 있습니다.

String html = "<html><head><title>First parse</title></head>" + "<body><p>Parsed HTML into a doc.</p></body></html>"; Document doc = Jsoup.parse(html);

Note

숙제

  • 네이버 홈페이지에서 실시간 검색어를 출력하시오.

클래스 만들기¶

Timetable 클래스 만들기 ArrayList<TimetableItem>을 상속받도록 합니다. ArrayList를 참고합니다.

TimetableItemstation, schoolno 필드를 넣습니다.

셀레늄(selenium)¶

셀레늄은 프로그래밍으로 웹브라우저를 대신할 수 있는 라이브러리입니다. 셀레늄은 기능에 따라 웹드라이버(WebDriver), Selenium RC(Remote Control), Selenium IDE 등으로 나눌 수 있습니다. 웹드라이버는 웹브라우저를 제어할 수 있는 드라이버를 이용해서 브라우저의 기능을 사용하는 것입니다. Selenium RC는 이전 버전의 셀레늄이고 Selenium IDE는 파이어폭스와 크롬 플러그인으로 사용할 수 있는 통합개발환경을 제공합니다.

여기서는 웹드라이버를 사용하도록 합니다.

설치 및 라이브러리 추가¶

자바 프로젝트¶

셀레늄 사이트에서 jar 파일을 다운받아 jar 파일을 라이브러리에 추가합니다. 추가 방법은 프로젝트 페이지의 외부 라이브러리 이용을 참조합니다.

그레이들 프로젝트¶

build.gradle 파일에 다음을 추가하고 그레이들 프로젝트를 새로고침 합니다. 프로젝트 이름을 선택하여 오른쪽 클릭을 하고 Gradle > Refresh Gradle Project를 선택하면 됩니다. 아래 셀레늄 버전은 메이븐 사이트에서 최신 버전을 사용하시면 됩니다.

implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'

웹브라우저 설정¶

셀레늄 웹드라이버를 사용하기 위해서는 웹브라우저가 설치되어 있어야 합니다. 크롬 또는 파이어폭스를 설치하시면 됩니다. 또한 각 브라우저가 제공하는 드라이버를 다운받아 경로에 설정을해야 합니다. 크롬을 예로 들어보겠습니다.

크롬 드라이버를 웹페이지에서 다운받습니다. 파이어폭스 드라이버는 여기에서 다운받으시면 됩니다. 다운받은 파일을 프로젝트 디렉토리 안에 drivers라는 폴더를 만들고 저장합니다. 셀레늄을 사용하기 위해서는 크롬 드라이버를 먼저 경로에 지정하시고 사용하시면 됩니다. 다음과 같이 사용하시면 됩니다.

System.setProperty("webdriver.chrome.driver", "drivers\\chromedriver.exe"); WebDriver driver = new ChromeDriver();

웹드라이버 API 사용법¶

웹페이지 접속¶

driver.get("//www.google.com");

대기 시간¶

웹 요소를 찾는 동안 드라이버가 다음으로 진행하지 않고 대기하는 시간을 설정할 수 있습니다.

암시적 대기¶

WebDriver.Timeouts에 정의되어 있는 implicitlyWait() 메소드를 이용하여 대기 시간을 설정합니다. 대기 시간이 지나면 NoSuchElementException이 발생합니다.

WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("//somedomain/url_that_delays_loading"); WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));

명시적 대기¶

어떤 조건을 만족할 때까지 다음으로 넘어가지 않고 대기하는 것을 명시적 대기(explicit wait)이라고 합니다. WebDriverWait의 until 메소드를 이용해서 대기 시간을 설정합니다. until 인자로 넘겨진 조건이 만족이 될 때까지 주어진 시간을 기다립니다.

WebDriver driver = new FirefoxDriver(); driver.get("//somedomain/url_that_delays_loading"); WebElement myDynamicElement = (new WebDriverWait(driver, 10)) .until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));

사용자 에이전트¶

User-Agent 변경을 할 수 있습니다.

ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--user-agent=Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Mobile Safari/537.36"); WebDriver driver = new ChromeDriver(chromeOptions);

자바스크립트¶

자바스크립트를 실행할 수 있습니다.

JavascriptExecutor js = (JavascriptExecutor) driver; String js_string = "Object.defineProperty(navigator, 'webdriver', {" + " get: () => false," + " });"; js.executeScript(js_string);

HTML 성분 검색(WebElements)¶

아이디(ID) 검색¶

WebElement element = driver.findElement(By.id("coolestWidgetEvah"));

클래스 이름 검색¶

List<WebElement> cheeses = driver.findElements(By.className("cheese"));

태그(Tag) 이름 검색¶

WebElement frame = driver.findElement(By.tagName("iframe"));

이름(Name) 검색¶

WebElement cheese = driver.findElement(By.name("cheese"));

링크 텍스트(Link Text) 검색¶

WebElement cheese = driver.findElement(By.linkText("cheese"));

부분 링크 텍스트 검색¶

WebElement cheese = driver.findElement(By.partialLinkText("cheese"));

CSS 검색¶

WebElement cheese = driver.findElement(By.cssSelector("#food span.dairy.aged"));

XPath 검색¶

List<WebElement> inputs = driver.findElements(By.xpath("//input"));

자바스크립트 이용¶

WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]");

텍스트 값 얻기¶

WebElement element = driver.findElement(By.id("elementID")); element.getText();

사용자 입력 - 폼 채우기¶

WebElement select = driver.findElement(By.tagName("select")); List<WebElement> allOptions = select.findElements(By.tagName("option")); for (WebElement option : allOptions) { System.out.println(String.format("Value is: %s", option.getAttribute("value"))); option.click(); }

select 이용

Select select = new Select(driver.findElement(By.tagName("select"))); select.deselectAll(); select.selectByVisibleText("Edam");

클릭 이용

driver.findElement(By.id("submit")).click();

제출(submit) 이용

창과 프레임 이동¶

driver.switchTo().window("windowName");

for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); }

driver.switchTo().frame("frameName");

팝업 창¶

Alert alert = driver.switchTo().alert();

이동¶

driver.navigate().to("//www.example.com");

driver.navigate().forward(); driver.navigate().back();

쿠기¶

// Go to the correct domain driver.get("//www.example.com"); // Now set the cookie. This one's valid for the entire domain Cookie cookie = new Cookie("key", "value"); driver.manage().addCookie(cookie); // And now output all the available cookies for the current URL Set<Cookie> allCookies = driver.manage().getCookies(); for (Cookie loadedCookie : allCookies) { System.out.println(String.format("%s -> %s", loadedCookie.getName(), loadedCookie.getValue())); } // You can delete cookies in 3 ways // By name driver.manage().deleteCookieNamed("CookieName"); // By Cookie driver.manage().deleteCookie(loadedCookie); // Or all of them driver.manage().deleteAllCookies();

사용자 에이전트 변경¶

FirefoxProfile profile = new FirefoxProfile(); profile.addAdditionalPreference("general.useragent.override", "some UA string"); WebDriver driver = new FirefoxDriver(profile);

드래그 앤 드랍(Drag and Drop)¶

WebElement element = driver.findElement(By.name("source")); WebElement target = driver.findElement(By.name("target")); (new Actions(driver)).dragAndDrop(element, target).perform();

Toplist

최신 우편물

태그