Lekce 16 - Knihovna Jsoup v Javě - Pokročilé vyhledávání
V minulé lekci, Knihovna Jsoup v Javě - Parsování HTML, jsme si ukázali, jak načíst, vyhledat či vypsat data html dokumentů pomocí knihovny Jsoup.
V dnešním pokračování Java tutoriálu o knihovně Jsoup, si ukážeme, jak nám umožňuje pracovat například s obrázky, odkazy či atributy v html dokumentu. A v posledním příkladu zkusíme rozklíčovat komentáře z webové diskuze.
Odkazy a obrázky
Nejdříve se podíváme, jak vyhledávat odkazy a obrázky. Začneme jednodušším příkladem.
Vyhledávání a výpis
Hledání a výpis odkazů a obrázků je takřka totožné, můžeme si tedy obojí ukázat na jednom příkladu:
public class Jsoup05 { private static String urlString = "http://pctforum.tyden.cz/viewtopic.php?f=22&t=2131&sid=e4961b3cd95117044f1ec079ecaf92c2"; private static List<String> linkURLs = new ArrayList<>(); private static List<String> imageURLs = new ArrayList<>(); public static void main(String[] args) throws IOException { Document doc = Jsoup.connect(urlString).get(); // vyhledání elementů a s atributem href Elements links = doc.select("a[href]"); for (Element link : links) { System.out.println(link.attr("href")); System.out.println(link.attr("abs:href")); System.out.println(link.absUrl("href")); System.out.println("================================"); linkURLs.add(link.attr("abs:href")); } // vyhledání elementů img Elements images = doc.select("img"); for (Element image : images) { System.out.println(image.attr("src")); System.out.println(image.attr("abs:src")); System.out.println(image.absUrl("src")); System.out.println("================================"); imageURLs.add(image.attr("abs:src")); } System.out.println("Počet odkazů: " + linkURLs.size() + " | Výpis: " + Arrays.toString(linkURLs.toArray())); System.out.println("Počet obrázků: " + imageURLs.size() + " | Výpis: " + Arrays.toString(imageURLs.toArray())); } }
Vyhledání všech elementů <a>
, které mají atribut
href
má na starosti tento řádek kódu:
Elements links = doc.select("a[href]");
Následně získáme a vypíšeme relativní url:
System.out.println(link.attr("href"));
Získání a výpis absolutní url, můžeme zapsat dvěma způsoby. Uvádím oba, záleží na vás, který si vyberete:
System.out.println(link.attr("abs:href")); System.out.println(link.absUrl("href"));
Stejně postupujeme i v případě elementů img
(hledáme
obrázky), kde také nejdříve získáme a vypíšeme relativní url atributu
src
a poté absolutní url. Opět jsou uvedeny oba způsoby
získání absolutní url.
Na závěr vypíšeme počet odkazů a obrázků a jejich absolutní url:
System.out.println("Počet odkazů: " + linkURLs.size() + " | Výpis: " + Arrays.toString(linkURLs.toArray())); System.out.println("Počet obrázků: " + imageURLs.size() + " | Výpis: " + Arrays.toString(imageURLs.toArray()));
Vyhledávání a výběr s použitím podmínek
Výsledky hledání můžeme samozřejmě filtrovat pomocí podmínek. Prohlédněte si druhý příklad a zkuste sami přijít na to, co bude jeho výstupem. Malou nápovědu máte v komentáři a celé vysvětlení níže:
public class Jsoup06 { private static String urlString = "http://www.itnetwork.cz"; public static void main(String[] args) throws IOException { Document doc = Jsoup.connect(urlString).get(); Elements links = doc.select("a"); for (Element link : links) { if (link.hasAttr("target")) { if (link.hasText()) { System.out.println(link.text()); // text odkazu System.out.println(link); // celé html odkazu } } } Elements images = doc.select("img"); for (Element image : images) { if (image.hasAttr("alt")) { if (image.attr("alt").length() > 2) { System.out.println(image.attr("alt")); System.out.println(image); } } } } }
Tento kód načte stránku na zadaném url, najde všechny odkazy, které
mají atribut target
a pokud má daný odkaz nějaký text,
vypíše text a následně celý odkaz. Pak vyhledá všechny obrázky s
atributem alt
a v případě, že atribut alt
má tři
a více znaků, vypíše hodnotu tohoto atributu a posléze i celý
img
element.
Procházení diskuze
Pro pochopení dalšího příkladu je dobré znát strukturu stránky, se kterou budeme pracovat. Znovu vás nechám nejdříve prozkoumat uvedený odkaz a celý kód a vysvětlení napíšu až pod ním:
public class Jsoup07 { public static void main(String[] args) throws IOException { String urlString = "http://www.novinky.cz/diskuse?id=339381&articleId=/ekonomika/317675-zazracny-pristroj-na-usporu-elektriny-je-podvod-varuje-casopis-dtest.html§ionId=5"; Document doc = Jsoup.connect(urlString).get(); String selectorContributions = "div#contributions"; String selectorContribution = "div.contribution"; //String selectorContribution = "div.msgBoxOut"; Element contributions = doc.select(selectorContributions).first(); //Element contributions = doc.getElementById("contributions"); Elements selectedDivs = contributions.select(selectorContribution); // vypsání vybraných div for (Element div : selectedDivs) { System.out.println(div); } // vypsání textu vybraných div for (Element div : selectedDivs) { System.out.println(div.text()); } // vyhledání elementů v rozsahu jiného elementu String selectorName = "h4.name"; String selectorDate = "div.infoDate span"; String selectorContent = "div.content"; for (Element div : selectedDivs) { Element name = div.select(selectorName).first(); Element date = div.select(selectorDate).first(); Element content = div.select(selectorContent).first(); System.out.println(name.text()); System.out.println(date.text()); System.out.println(content.text()); System.out.println("====================================="); } } }
Na načítané url se nachází diskuze. Pokud se podíváte do zdrojového
kódu stránky, tak zjistíte, že oblast, ve které se nacházejí komentáře,
má id
contributions
:
<div id="contributions">
...oblast s
komentáři...</div>
, každý komentář se nachází ve
třídě contribution
:
<div class="contribution">
...komentář...</div>
.
V každém komentáři je uveden autor:
<h4 class="name">
autor</h4>
,
datum, umístěný v tagu span
, který je ve třídě
infoDate
<div class="infoDate"><span>
datum</span></div>
a samotný text příspěvku:
<div class="content">
...text...</div>
.
Pokud bychom měli být důslední, text příspěvku je v tagu
<p>
...</p>
a tento tag je ve třídě
content
. Jelikož daná třída nemá jiný text, než komentář,
není tato přesnost nutná na rozdíl od třídy infoDate
, která
obsahuje kromě data i odkazy pro hlasování (souhlasím, nesouhlasím) a
skóre hlasování.
Nejprve hledáme <div id="contributions">
, tudíž do
proměnné selectorContributions
uložíme
"div#contributions"
:
Element contributions = doc.select(selectorContributions).first();
Můžeme použít i druhý způsob:
Element contributions = doc.getElementById("contributions");
V takto vybrané oblasti hledáme div
s třídou
contribution
:
Elements selectedDivs = contributions.select(selectorContribution);
A následuje vyhledání elementů v rozsahu jiného elementu:
String selectorName = "h4.name"; String selectorDate = "div.infoDate span"; String selectorContent = "div.content";
Všimněte si syntaxe jednotlivých položek.
Tímto završíme náš výklad o knihovně Jsoup, pokud vás její využití zaujalo, můžete se ještě podívat na oficiální dokumentaci. Doufám, že vám knihovna Jsoup bude k užitku.
V příští lekci, HTTPS v Javě, si ukážeme, jak funguje ověřování serverových SSL/TLS certifikátů a kde jsou v Javě uloženy certifikáty důvěryhodných autorit.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 163x (1.97 kB)
Aplikace je včetně zdrojových kódů v jazyce Java