IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Parsovanie HTML v Jave s knižnicou Jsoup

V tomto tutoriále sa zoznámime s knižnicou Jsoup, ktorá sa používa pre načítanie, vyhľadávanie a manipuláciu s HTML súbory. Pre prácu je nutné si stiahnuť ( http://jsoup.org/download) .jar knižnicu a pridať ju k nášmu projektu. Pre Eclipse je postup nasledujúci: pravým tlačidlom na projekt -> Build Path -> Configure Build Path -> záložka Libraries -> Add External JARs ... -> vyberiete knižnicu, ktorú chcete pridať a potvrdíte. Z dôvodu úspory miesta nebudem u príkladov uvádzať importy. Kompletné zdrojové kódy sú k stiahnutiu v .zip priloženému k tomuto tutoriálu.

Document

public class Jsoup01 {

    public static void main(String[] args) throws IOException {
        String urlString = "http://www.seznam.cz/";
        Document doc = Jsoup.connect(urlString).get();

        System.out.println(doc.title());
        System.out.println(doc.text());
        System.out.println("=============================");

        Elements links = doc.select("a");
        for (Element link : links) {
            System.out.println("Link: " + link);
            System.out.println("Text: " + link.text());
        }
    }
}
Document doc = Jsoup.connect(urlString).get();

Ako parameter si vezme reťazec predstavujúci url adresu a vytvorí Jsoup Document (pošle HTTP GET request).

System.out.println(doc.title());
System.out.println(doc.text());

Získa a zobrazí titulok a text dokumentu.

Elements links = doc.select("a");

Objekt Elements predstavuje zoznam objektov Element. Element predstavuje html element a skladá sa z názvu tagu, atribútov a potomkov. Jednoducho povedané vyššie uvedené časť kódu vyhľadá všetky tagy <a> a uloží ich do zoznamu.

for (Element link : links) {
        System.out.println("Link: " + link);
        System.out.println("Text: " + link.text());
}

Prechádza všetky elementy v zozname links a vypisuje ich. Všimnite si, že link.text() vypíše text html elementu, kdežto link vypíše celý html element.

Connection

public class Jsoup02 {

    public static void main(String[] args) {
        String urlString = "http://forum.objectivismonline.com/?showforum=42";

        Connection con01 = Jsoup.connect(urlString);
        Document doc01 = null;
        try {
            doc01 = con01.get();
            System.out.println(doc01.text());
        } catch (IOException e) {
            System.out.println("Exception: " + e);
        }

        Connection con02 = Jsoup.connect(urlString)
                .userAgent("Mozilla")
                .timeout(10000);
        Document doc02 = null;
        try {
            doc02 = con02.get();
            System.out.println(doc02.text());
        } catch (IOException e) {
            System.out.println("Exception: " + e);
        }
    }
}
Connection con01 = Jsoup.connect(urlString);

Connection predstavuje rozhranie pre získanie obsahu z web a naparsování tohto obsahu do objektu typu Document.

doc01 = con01.get();

Metóda get () pošle request na server ako GET a naparsuje výsledok (vráti objekt typu Document). Táto metóda môže vyhodiť niekoľko výnimiek napr. MalformedURLEx­ception v prípade funkčnej url. Tiež môže dôjsť k výnimke HttpStatusException v prípade, že na náš request sme nedostali OK HTTP odpoveď. Server, na ktorý posielame náš request, zistia kto sme z užívateľskú agent header a v tomto prípade sa mu to čo zistí nepáči a neodpovie nám tak, ako by sme chceli.

Viac k http nájdete na wiki.

Connection con02 = Jsoup.connect(urlString)
                .userAgent("Mozilla")
                .timeout(10000);

Connection umožňuje reťaziť metódy, čoho sme tu využili. Najskôr nastavíme url, potom užívateľskú agent header a nakoniec timeout v milisekundách.

doc02 = con02.get();
System.out.println(doc02.text());

Ako výsledok by sa nám mal zobraziť celý text požadovanej stránky.

Načítanie zo súboru az reťazca

Najskôr si vytvoríme jednoduchý HTML dokument (my_page.html)

<html>
<head>
  <title>My Page</title>
</head>
<body>
  <h1>Nadpis h1</h1>
  <div class="prvni">
    <h2>Nadpis h2</h2>
    <p>Toto je 1. odstavec <a href="http://www.itnetwork.cz">a toto je odkaz</a>.</p>
    <p>Toto je 2. odstavec</p>
    <p>Toto je 3. odstavec</p>
  </div>
  <div class="druhy">
    <h2>Nadpis h2</h2>
    <p>Toto je 4. odstavec</p>
    <p>Toto je 5. odstavec</p>
    <p>Toto je 6. odstavec</p>
  </div>
</body>
</html>

A následne ho načítame.

public class Jsoup03 {

    public static void main(String[] args) throws IOException {
        // načtení html ze souboru
        Document doc = null;
        File input = new File("my_page.txt");
        if (input.exists()) {
            doc = Jsoup.parse(input, "UTF-8");
        }
        System.out.println("doc:\n" + doc);

        // načtení html z řetězce - úplné html
        String html01 = "<htm><head></head>"
                + "<body><h2>Nadpis</h2>"
                + "<p>Toto je první odstavec</p>"
                + "<p>Toto je druhý odstavec</p>"
                + "</body></html>";
        Document doc01 = Jsoup.parse(html01);
        System.out.println("\ndoc01:\n" + doc01);

        // načtení html z řetězce - neúplné html
        String html02 = "<head><body><head>"
                + "<h2>Nadpis</h2>"
                + "<p>Toto je první odstavec"
                + "<p>Toto je druhý odstavec</p></body>";
        Document doc02 = Jsoup.parse(html02);
        System.out.println("\ndoc02:\n" + doc02);
        System.out.println("\ndoc02.html():\n" + doc02.html());

        // výpis html bez entit a výpis textu
        System.out.println("\ndoc02.html() - StringEscapeUtils:\n" + StringEscapeUtils.unescapeHtml4(doc02.html()));
        System.out.println("\ndoc02.text():\n" + doc02.text());
    }
}
doc = Jsoup.parse(input, "UTF-8");

Načíta súbor a vytvorí z neho org.jsoup.nodes­.Document.

System.out.println("doc:\n" + doc);

Vypíše celý Document ako html.

Document doc01 = Jsoup.parse(html01);

Ako vstup môžeme metóde parse () odovzdať tiež obyčajný reťazec a Jsoup sa z neho pokúsi urobiť html dokument.

Document doc02 = Jsoup.parse(html02);

Tu sme odovzdali reťazec s neúplným html a Jsoup sa s tým celkom vysporiadal. Keď sa pozriete do výpisu, zistíte, že Jsoup správne doplnil chýbajúce html tagy. Tiež si ale pravdepodobne všimnete, že české znaky sú nahradené entitami.

StringEscapeUtils.unescapeHtml4(doc02.html())

Ak chceme stránky stiahnuť a následne v nich vyhľadávať, tak nám text plný html entít príliš nepomôže. Existuje však knižnica org.apache.com­mons.lang3.Strin­gEscapeUtils, pomocou ktorej metódy unescapeHtml4 bude výstup vyzerať tak, ako potrebujeme.

doc02.text()

Vypíše text bez html tagov.

Vyhľadávanie

public class Jsoup04 {

    public static void main(String[] args) throws IOException {
        Document doc = Jsoup.parse(new File("my_page.txt"), "UTF-8");

        // vyhledání a výpis všech odstavců (elementů p)
        Elements elem = doc.select("p");
        for (Element el : elem) {
            System.out.println(el);
        }
        System.out.println();

        // výpis prvního odstavce
        Element firstParagraphElement = doc.select("p").first();
        System.out.println(firstParagraphElement);
        System.out.println(firstParagraphElement.text());

        List<Node> nodes = firstParagraphElement.childNodes();
        for (int i = 0; i < nodes.size(); i++) {
            System.out.println("Node number " + (i + 1) + ": " + nodes.get(i));
        }
        System.out.println("Child number: " + firstParagraphElement.child(0));
        System.out.println();

        // vyhledání všech p v divu označeném třídou 'druhy'
        Element secondDivElements = doc.select("div.druhy").first();
        Elements paragraphElements = secondDivElements.select("p");
        for (Element par : paragraphElements) {
            System.out.println(par);
        }
    }
}

V tomto príklade sme opäť použili súbor my_page.txt

Elements elem = doc.select("p");
for (Element el : elem) {
        System.out.println(el);
}

Vyhľadanie a výpis všetkých odsekov.

Element firstParagraphElement = doc.select("p").first();

Získanie prvého odseku (elementu p).

List<Node> nodes = firstParagraphElement.childNodes();
for (int i = 0; i < nodes.size(); i++) {
        System.out.println("Node number " + (i + 1) + ": " + nodes.get(i));
}

Node je základná abstraktné trieda, z ktorej dedia napr. Element, Document, ..... Čo to je to vlastne childNode daného elementu zistíte najlepšie z výpisu.

firstParagraphElement.child(0)

Získame potomka elementu firstParagrap­hElement na pozíciu nula (prvého potomka).

Element secondDivElements = doc.select("div.druhy").first();
Elements paragraphElements = secondDivElements.select("p");
for (Element par : paragraphElements) {
        System.out.println(par);
}

Vyhľadávať je možné tiež do hĺbky. Tu najskôr vyhľadáme prvý element <div class = "druhy"> a následne v tomto elemente vyhľadáme všetky odseky a tie zobrazíme.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 209x (2.25 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java

 

Všetky články v sekcii
Java - Pre pokročilých
Článok pre vás napísal vita
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
vita
Aktivity