Jsoup을 사용하여 Java에서 HTML 구문 분석

1. 개요

Jsoup은 주로 HTML에서 데이터를 추출하는 데 사용되는 오픈 소스 Java 라이브러리입니다. 또한 HTML을 조작하고 출력 할 수 있습니다. 꾸준한 개발 라인, 훌륭한 문서, 유창하고 유연한 API가 있습니다. Jsoup을 사용하여 XML을 구문 분석하고 빌드 할 수도 있습니다.

이 튜토리얼에서는 Spring 블로그를 사용하여 jsoup의 여러 기능을 보여주는 스크래핑 연습을 설명합니다.

  • 로드 : HTML을 문서 로 가져오고 구문 분석
  • 필터링 : 원하는 데이터를 요소 로 선택 하고 순회
  • 추출 : 노드의 속성, 텍스트 및 HTML 얻기
  • 수정 : 노드 추가 / 편집 / 제거 및 속성 편집

2. Maven 종속성

프로젝트에서 jsoup 라이브러리를 사용하려면 종속성을 pom.xml에 추가하십시오 .

 org.jsoup jsoup 1.10.2 

Maven Central 저장소에서 최신 버전의 jsoup을 찾을 수 있습니다.

3. Jsoup 살펴보기

Jsoup은 페이지 HTML을로드하고 해당 DOM 트리를 빌드합니다. 이 트리는 브라우저의 DOM과 동일한 방식으로 작동하며 jQuery 및 vanilla JavaScript와 유사한 메소드를 제공하여 텍스트 / HTML / 속성을 선택하고, 탐색하고, 요소를 추가 / 제거합니다.

클라이언트 측 선택기 및 DOM 탐색 / 조작에 익숙하다면 jsoup이 매우 익숙 할 것입니다. 페이지의 단락을 인쇄하는 것이 얼마나 쉬운 지 확인하십시오.

Document doc = Jsoup.connect("//example.com").get(); doc.select("p").forEach(System.out::println);

jsoup은 HTML 만 해석하고 JavaScript는 해석하지 않습니다. 따라서 JavaScript 사용 가능 브라우저에서 페이지가로드 된 후 일반적으로 발생하는 DOM 변경 사항은 jsoup에서 볼 수 없습니다.

4. 로딩

로딩 단계는 HTML을 문서 로 가져오고 파싱하는 단계로 구성 됩니다. Jsoup은 최신 브라우저와 마찬가지로 가장 유효하지 않은 것부터 완전히 검증 된 것까지 모든 HTML의 구문 분석을 보장합니다. String , InputStream , File 또는 URL 을로드하여 얻을 수 있습니다 .

Spring Blog URL에서 문서 를 로드 해 보겠습니다 .

String blogUrl = "//spring.io/blog"; Document doc = Jsoup.connect(blogUrl).get();

통지 가져 오기 방법, 그것은 HTTP GET 호출을 나타냅니다. post 메소드를 사용하여 HTTP POST를 수행 할 수도 있습니다 (또는 HTTP 메소드 유형을 매개 변수로 수신 하는 메소드 를 사용할 수 있습니다 ).

비정상적인 상태 코드 (예 : 404)를 감지해야하는 경우 HttpStatusException 예외를 포착해야합니다 .

try { Document doc404 = Jsoup.connect("//spring.io/will-not-be-found").get(); } catch (HttpStatusException ex) { //... }

때로는 연결을 좀 더 사용자 정의해야합니다. Jsoup.connect (…) 는 사용자 에이전트, 리퍼러, 연결 시간 제한, 쿠키, 게시 데이터 및 헤더를 설정할 수 있는 Connection 을 반환합니다 .

Connection connection = Jsoup.connect(blogUrl); connection.userAgent("Mozilla"); connection.timeout(5000); connection.cookie("cookiename", "val234"); connection.cookie("cookiename", "val234"); connection.referrer("//google.com"); connection.header("headersecurity", "xyz123"); Document docCustomConn = connection.get();

연결이 유창한 인터페이스를 따르므로 원하는 HTTP 메서드를 호출하기 전에 이러한 메서드를 연결할 수 있습니다.

Document docCustomConn = Jsoup.connect(blogUrl) .userAgent("Mozilla") .timeout(5000) .cookie("cookiename", "val234") .cookie("anothercookie", "ilovejsoup") .referrer("//google.com") .header("headersecurity", "xyz123") .get();

해당 Javadoc을 찾아 연결 설정에 대해 자세히 알아볼 수 있습니다 .

5. 필터링

이제 HTML을 Document 로 변환 했으므로 탐색하여 원하는 내용을 찾을 차례입니다. 선택기와 순회 방법이 비슷하기 때문에 jQuery / JavaScript와의 유사성이 더 분명해집니다.

5.1. 선택

문헌이 선택 방법은 수신 문자열 CSS 또는 자바 스크립트와 같은 선택기 구문을 사용하여 셀렉터를 나타내는, 그리고 일치하는 검색 목록 요소 . 이 목록은 비어있을 수 있지만 null 이 될 수 없습니다 .

select 메서드를 사용하여 몇 가지 선택 사항을 살펴 보겠습니다 .

Elements links = doc.select("a"); Elements sections = doc.select("section"); Elements logo = doc.select(".spring-logo--container"); Elements pagination = doc.select("#pagination_control"); Elements divsDescendant = doc.select("header div"); Elements divsDirect = doc.select("header > div");

일반적인 select 대신 브라우저 DOM에서 영감을 얻은보다 명시적인 메서드를 사용할 수도 있습니다 .

Element pag = doc.getElementById("pagination_control"); Elements desktopOnly = doc.getElementsByClass("desktopOnly");

Since Element is a superclass of Document, you can learn more about working with the selection methods in the Document and Element Javadocs.

5.2. Traversing

Traversing means navigating across the DOM tree. Jsoup provides methods that operate on the Document, on a set of Elements, or on a specific Element, allowing you to navigate to a node's parents, siblings, or children.

Also, you can jump to the first, the last, and the nth (using a 0-based index) Element in a set of Elements:

Element firstSection = sections.first(); Element lastSection = sections.last(); Element secondSection = sections.get(2); Elements allParents = firstSection.parents(); Element parent = firstSection.parent(); Elements children = firstSection.children(); Elements siblings = firstSection.siblingElements();

You can also iterate through selections. In fact, anything of type Elements can be iterated:

sections.forEach(el -> System.out.println("section: " + el));

You can make a selection restricted to a previous selection (sub-selection):

Elements sectionParagraphs = firstSection.select(".paragraph");

6. Extracting

We now know how to reach specific elements, so it's time to get their content — namely their attributes, HTML, or child text.

Take a look at this example that selects the first article from the blog and gets its date, its first section text, and finally, its inner and outer HTML:

Element firstArticle = doc.select("article").first(); Element timeElement = firstArticle.select("time").first(); String dateTimeOfFirstArticle = timeElement.attr("datetime"); Element sectionDiv = firstArticle.select("section div").first(); String sectionDivText = sectionDiv.text(); String articleHtml = firstArticle.html(); String outerHtml = firstArticle.outerHtml();

Here are some tips to bear in mind when choosing and using selectors:

  • Rely on “View Source” feature of your browser and not only on the page DOM as it might have changed (selecting at the browser console might yield different results than jsoup)
  • Know your selectors as there are a lot of them and it's always good to have at least seen them before; mastering selectors takes time
  • Use a playground for selectors to experiment with them (paste a sample HTML there)
  • Be less dependent on page changes: aim for the smallest and least compromising selectors (e.g. prefer id. based)

7. Modifying

Modifying encompasses setting attributes, text, and HTML of elements, as well as appending and removing elements. It is done to the DOM tree previously generated by jsoup – the Document.

7.1. Setting Attributes and Inner Text/HTML

As in jQuery, the methods to set attributes, text, and HTML bear the same names but also receive the value to be set:

  • attr() – sets an attribute's values (it creates the attribute if it does not exist)
  • text() – sets element inner text, replacing content
  • html() – sets element inner HTML, replacing content

Let's look at a quick example of these methods:

timeElement.attr("datetime", "2016-12-16 15:19:54.3"); sectionDiv.text("foo bar"); firstArticle.select("h2").html(" "); 

7.2. Creating and Appending Elements

To add a new element, you need to build it first by instantiating Element. Once the Element has been built, you can append it to another Element using the appendChild method. The newly created and appended Element will be inserted at the end of the element where appendChild is called:

Element link = new Element(Tag.valueOf("a"), "") .text("Checkout this amazing website!") .attr("href", "//baeldung.com") .attr("target", "_blank"); firstArticle.appendChild(link);

7.3. Removing Elements

To remove elements, you need to select them first and run the remove method.

For example, let's remove all

  • tags that contain the “navbar-link” class from Document, and all images from the first article:

    doc.select("li.navbar-link").remove(); firstArticle.select("img").remove();

    7.4. Converting the Modified Document to HTML

    Finally, since we were changing the Document, we might want to check our work.

    To do this, we can explore the Document DOM tree by selecting, traversing, and extracting using the presented methods, or we can simply extract its HTML as a String using the html() method:

    String docHtml = doc.html();

    The String output is a tidy HTML.

    8. Conclusion

    Jsoup is a great library to scrape any page. If you're using Java and don't require browser-based scraping, it's a library to take into account. It's familiar and easy to use since it makes use of the knowledge you may have on front-end development and follows good practices and design patterns.

    You can learn more about scraping web pages with jsoup by studying the jsoup API and reading the jsoup cookbook.

    The source code used in this tutorial can be found in the GitHub project.