Menghuraikan HTML di Java dengan Jsoup

1. Gambaran keseluruhan

Jsoup adalah perpustakaan Java sumber terbuka yang digunakan terutamanya untuk mengekstrak data dari HTML. Ia juga membolehkan anda memanipulasi dan mengeluarkan HTML. Ia memiliki garis pengembangan yang stabil, dokumentasi hebat, dan API yang lancar dan fleksibel. Jsoup juga dapat digunakan untuk mengurai dan membina XML.

Dalam tutorial ini, kami akan menggunakan Spring Blog untuk menggambarkan latihan mengikis yang menunjukkan beberapa ciri jsoup:

  • Memuat: mengambil dan menguraikan HTML ke dalam Dokumen
  • Menyaring: memilih data yang diinginkan ke dalam Elemen dan melintasinya
  • Pengekstrakan: memperoleh atribut, teks, dan HTML nod
  • Mengubah: menambah / menyunting / membuang nod dan menyunting atributnya

2. Ketergantungan Maven

Untuk memanfaatkan perpustakaan jsoup dalam projek anda, tambahkan kebergantungan ke pom.xml anda :

 org.jsoup jsoup 1.10.2 

Anda boleh mendapatkan versi terbaru jsoup di repositori Maven Central.

3. Sepintas lalu Jsoup

Jsoup memuat HTML halaman dan membina struktur DOM yang sesuai. Pokok ini berfungsi dengan cara yang sama seperti DOM dalam penyemak imbas, menawarkan kaedah yang serupa dengan JavaScript jQuery dan vanilla untuk memilih, melintasi, memanipulasi teks / HTML / atribut dan menambah / membuang elemen.

Sekiranya anda selesa dengan pemilih di sisi pelanggan dan manipulasi / manipulasi DOM, anda akan mendapati jsoup sangat biasa. Periksa betapa mudahnya mencetak perenggan halaman:

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

Perlu diingat bahawa jsoup hanya menafsirkan HTML - ia tidak menafsirkan JavaScript. Oleh itu, perubahan pada DOM yang biasanya berlaku setelah pemuatan halaman dalam penyemak imbas berkemampuan JavaScript tidak akan dilihat di jsoup.

4. Memuatkan

Fasa memuat merangkumi pengambilan dan penghuraian HTML ke dalam Dokumen . Jsoup menjamin penghuraian HTML apa pun, dari yang paling tidak sah hingga yang disahkan sepenuhnya, seperti yang dilakukan oleh penyemak imbas moden. Ini dapat dicapai dengan memuat String , InputStream , File atau URL.

Mari memuatkan Dokumen dari URL Blog Spring:

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

Perhatikan kaedah get , ini mewakili panggilan HTTP GET. Anda juga dapat melakukan HTTP POST dengan kaedah posting (atau anda boleh menggunakan metode yang menerima jenis kaedah HTTP sebagai parameter).

Sekiranya anda perlu mengesan kod status yang tidak normal (contohnya 404), anda harus mendapatkan pengecualian HttpStatusException :

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

Kadang kala, penyambungan perlu lebih disesuaikan. Jsoup.connect (…) mengembalikan Sambungan yang membolehkan anda menetapkan, antara lain, ejen pengguna, perujuk, tamat masa sambungan, kuki, data siaran, dan tajuk:

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();

Oleh kerana sambungannya mengikuti antara muka yang lancar, anda boleh merantai kaedah ini sebelum memanggil kaedah HTTP yang diinginkan:

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

Anda boleh mengetahui lebih lanjut mengenai tetapan Sambungan dengan melayari Javadoc yang sesuai.

5. Penapisan

Sekarang kita telah mengubah HTML menjadi Dokumen , sudah waktunya untuk menavigasinya dan mencari apa yang kita cari. Di sinilah kemiripan dengan jQuery / JavaScript lebih jelas, kerana kaedah pemilih dan traversingnya serupa.

5.1. Memilih

The Document pilih kaedah menerima String mewakili pemilih, menggunakan sintaks pemilih yang sama seperti dalam CSS atau JavaScript, dan mendapatkan semula senarai yang hampir sama Elements . Senarai ini boleh kosong tetapi tidak kosong .

Mari kita lihat beberapa pilihan menggunakan kaedah pilih :

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");

Anda juga boleh menggunakan kaedah yang lebih eksplisit yang diilhamkan oleh penyemak imbas DOM dan bukannya pilih generik :

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

Oleh kerana Element adalah superclass of Document , anda boleh mengetahui lebih lanjut mengenai cara menggunakan kaedah pemilihan dalam Document dan Element Javadocs.

5.2. Melintas

Melintasi bermaksud menavigasi melintasi pokok DOM. Jsoup menyediakan kaedah yang beroperasi pada Dokumen , pada sekumpulan Elemen, atau pada Elemen tertentu , yang membolehkan anda menavigasi ke ibu bapa, adik-beradik, atau anak-anak nod.

Anda juga boleh melompat ke Elemen pertama, terakhir, dan ke-9 (menggunakan indeks berasaskan 0) dalam satu set Elemen :

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();

Anda juga boleh melakukan lelaran melalui pilihan. Sebenarnya, apa-apa jenis Elemen boleh berulang:

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

Anda boleh membuat pilihan yang terbatas pada pilihan sebelumnya (sub-pilihan):

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

6. Mengekstrak

Kami sekarang tahu bagaimana menjangkau elemen tertentu, jadi sudah waktunya untuk mendapatkan kandungannya - iaitu atribut, HTML, atau teks anak mereka.

Lihat contoh ini yang memilih artikel pertama dari blog dan mendapatkan tarikhnya, teks bahagian pertama, dan akhirnya, HTML dalaman dan luarannya:

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();

Berikut adalah beberapa petua yang perlu diingat semasa memilih dan menggunakan pemilih:

  • Mengandalkan fitur "Lihat Sumber" pada penyemak imbas anda dan tidak hanya pada halaman DOM kerana mungkin telah berubah (memilih di konsol penyemak imbas mungkin menghasilkan hasil yang berbeza daripada jsoup)
  • Ketahui pemilih anda kerana ada banyak pilihan dan selalu baik untuk melihatnya sekurang-kurangnya sebelum ini; menguasai pemilih memerlukan masa
  • Gunakan taman permainan untuk pemilih bereksperimen dengan mereka (tampal contoh HTML di sana)
  • Kurang bergantung pada perubahan halaman: bertujuan untuk pemilih terkecil dan paling tidak berkompromi (mis. Lebih suka berdasarkan id)

7. Mengubahsuai

Mengubah merangkumi atribut pengaturan, teks, dan HTML elemen, serta menambahkan dan menghapus elemen. Ia dilakukan ke pokok DOM yang sebelumnya dihasilkan oleh jsoup - the Document .

7.1. Menetapkan Atribut dan Teks Dalam / HTML

Seperti dalam jQuery, kaedah untuk menetapkan atribut, teks, dan HTML mempunyai nama yang sama tetapi juga menerima nilai yang akan ditetapkan:

  • attr () - menetapkan nilai atribut (ia mencipta atribut jika tidak ada)
  • text () - menetapkan elemen teks dalaman, menggantikan kandungan
  • html () - menetapkan elemen HTML dalaman, menggantikan kandungan

Mari lihat contoh ringkas kaedah ini:

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

7.2. Membuat dan Menambah Elemen

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.