Di episode terakhir, kita membahas tentang perlunya menggunakan Java untuk membuat crawler Zhihu, jadi kali ini kita akan mempelajari cara menggunakan kode untuk mendapatkan konten halaman web.
Pertama-tama, jika Anda tidak memiliki pengalaman dengan HTML, CSS, JS dan AJAX, disarankan untuk pergi ke W3C (klik saya, klik saya) untuk belajar sedikit.
Berbicara tentang HTML, ini melibatkan masalah akses GET dan akses POST.
Jika Anda kurang memahami aspek ini, Anda dapat membaca artikel ini dari W3C: "GET vs. POST".
Aha, saya tidak akan menjelaskan detailnya di sini.
Lalu, selanjutnya kita perlu menggunakan Java untuk meng-crawl konten halaman web.
Saat ini, Baidu kita akan berguna.
Benar, dia bukan lagi penguji kecepatan Internet yang tidak dikenal, dia akan menjadi kelinci percobaan reptil kita! ~
Mari kita lihat beranda Baidu terlebih dahulu:
Saya yakin semua orang tahu bahwa halaman seperti ini adalah hasil kerja sama HTML dan CSS.
Kami klik kanan halaman di browser dan pilih "Lihat kode sumber halaman":
Itu benar, kira-kira seperti ini. Ini adalah kode sumber halaman Baidu.
Tugas kita selanjutnya adalah menggunakan crawler kita untuk mendapatkan hal yang sama.
Pertama mari kita lihat kode sumber sederhana:
import java.io.*;
impor java.net.*;
kelas publik Utama {
public static void main(String[] args) {
// Tentukan link yang akan dikunjungi
String url = "http://www.baidu.com";
//Tentukan string untuk menyimpan konten halaman web
Hasil string = "";
//Tentukan aliran input karakter yang di-buffer
BufferedReader di = null;
mencoba {
//Konversi string menjadi objek url
URL realUrl = URL baru(url);
// Inisialisasi tautan ke url itu
Koneksi URLConnection = realUrl.openConnection();
// Mulai koneksi sebenarnya
koneksi.koneksi();
//Inisialisasi aliran input BufferedReader untuk membaca respons URL
di = BufferedReader baru(InputStreamReader baru(
koneksi.getInputStream()));
// Digunakan untuk menyimpan sementara data dari setiap baris yang diambil
garis senar;
while ((baris = masuk.readLine()) != null) {
//Lintasi setiap baris yang diambil dan simpan sebagai hasilnya
hasil += baris;
}
} tangkapan (Pengecualian e) {
System.out.println("Terjadi pengecualian saat mengirimkan permintaan GET!" + e);
e.printStackTrace();
}
// Gunakan akhirnya untuk menutup aliran input
Akhirnya {
mencoba {
jika (dalam != nol) {
melampirkan();
}
} tangkapan (Pengecualian e2) {
e2.printStackTrace();
}
}
System.out.println(hasil);
}
}
Di atas adalah simulasi Java untuk mengakses metode Utama Baidu.
Anda dapat menjalankannya untuk melihat hasilnya:
Aha, sama persis dengan yang kita lihat di browser tadi. Pada titik ini, crawler paling sederhana sudah siap.
Tapi tumpukan barang sebanyak itu mungkin tidak semuanya yang saya inginkan. Bagaimana saya bisa mendapatkan apa yang saya inginkan darinya?
Ambil contoh logo kaki besar Baidu.
Kebutuhan sementara:
Dapatkan link gambar kaki besar Logo Baidu.
Pertama mari kita bicara tentang metode tampilan browser.
Klik kanan gambar dan pilih Inspect Elements (Firefox, Google, dan IE11 semuanya memiliki fungsi ini, namun namanya berbeda):
Aha, Anda dapat melihat tag img yang buruk dikelilingi oleh banyak div.
Src ini adalah tautan ke gambar.
Jadi bagaimana kita melakukannya di java?
Harap dicatat sebelumnya bahwa untuk memfasilitasi demonstrasi kode, semua kode tidak dirangkum berdasarkan kelas, harap dipahami.
Pertama-tama mari kita rangkum kode sebelumnya ke dalam fungsi sendGet:
import java.io.*;
impor java.net.*;
kelas publik Utama {
String statis sendGet(String url) {
//Tentukan string untuk menyimpan konten halaman web
Hasil string = "";
//Tentukan aliran input karakter yang di-buffer
BufferedReader di = null;
mencoba {
//Konversi string menjadi objek url
URL realUrl = URL baru(url);
// Inisialisasi tautan ke url itu
Koneksi URLConnection = realUrl.openConnection();
// Mulai koneksi sebenarnya
koneksi.koneksi();
//Inisialisasi aliran input BufferedReader untuk membaca respons URL
di = BufferedReader baru(InputStreamReader baru(
koneksi.getInputStream()));
// Digunakan untuk menyimpan sementara data dari setiap baris yang diambil
garis senar;
while ((baris = masuk.readLine()) != null) {
// Lintasi setiap baris yang diambil dan simpan sebagai hasilnya
hasil += baris;
}
} tangkapan (Pengecualian e) {
System.out.println("Terjadi pengecualian saat mengirimkan permintaan GET!" + e);
e.printStackTrace();
}
// Gunakan akhirnya untuk menutup aliran input
Akhirnya {
mencoba {
jika (dalam != nol) {
melampirkan();
}
} tangkapan (Pengecualian e2) {
e2.printStackTrace();
}
}
hasil pengembalian;
}
public static void main(String[] args) {
// Tentukan link yang akan dikunjungi
String url = "http://www.baidu.com";
//Akses tautan dan dapatkan konten halaman
Hasil string = sendGet(url);
System.out.println(hasil);
}
}
Ini terlihat sedikit lebih rapi, mohon maafkan gangguan obsesif-kompulsif saya.
Tugas selanjutnya adalah mencari link gambar dari banyak hal yang didapat.
Metode pertama yang dapat kita pikirkan adalah dengan menggunakan fungsi indexof untuk mencari substring String pada hasil string kode sumber halaman.
Ya, cara ini bisa mengatasi masalah ini secara perlahan, seperti langsung indexOf("src") mencari nomor seri awal, lalu segera mendapatkan nomor seri akhir.
Namun cara ini tidak bisa selalu kita gunakan, lagipula sandal jerami hanya cocok untuk jalan-jalan saja. Nantinya, kita tetap perlu memotong kaki palsunya untuk menopang kepala.
Mohon maafkan gangguan saya dan lanjutkan.
Jadi bagaimana kita menemukan src dari gambar ini?
Benar sekali, seperti yang dikatakan penonton di bawah, pencocokan biasa.
Jika ada siswa yang tidak yakin tentang ekspresi reguler, Anda dapat merujuk ke artikel ini: [Python] Web Crawler (7): Tutorial Ekspresi Reguler dengan Python.
Sederhananya, regex itu seperti mencocokkan.
Misalnya, ada tiga pria gemuk yang berdiri di sini, mengenakan baju merah, baju biru, dan baju hijau.
Aturannya adalah: tangkap yang berwarna hijau!
Lalu dia menangkap pria gemuk berwarna hijau itu sendirian.
Sesederhana itu.
Namun tata bahasa regulernya masih luas dan mendalam, dan tidak dapat dipungkiri bahwa Anda akan sedikit bingung saat pertama kali mengenalnya.
Saya merekomendasikan alat pengujian online reguler untuk semua orang: pengujian online ekspresi reguler.
Dengan keteraturan sebagai senjata ajaib, bagaimana cara menggunakan keteraturan di java?
Mari kita lihat buah plum kecil yang sederhana terlebih dahulu.
Ah, salah, kastanye kecil.
// Tentukan template gaya, menggunakan ekspresi reguler, dan konten yang akan diambil ada dalam tanda kurung
// Ini sama dengan mengubur jebakan dan akan jatuh jika cocok.
Pola pola = Pattern.compile("href=/"(.+?)/"");
//Tentukan pencocokan untuk pencocokan
Matcher matcher = pattern.matcher("<a href=/"index.html/">Beranda saya</a>");
// jika ditemukan
if (pencocokan.temukan()) {
// cetak hasilnya
System.out.println(matcher.group(1));
}
Hasil berjalan:
indeks.html
Ya, ini adalah kode reguler pertama kami.
Tautan untuk mengambil gambar di aplikasi ini harus ada di ujung jari Anda.
Kami merangkum pencocokan reguler ke dalam suatu fungsi, dan kemudian memodifikasi kode sebagai berikut:
import java.io.*;
impor java.net.*;
import java.util.regex.*;
kelas publik Utama {
String statis SendGet(String url) {
//Tentukan string untuk menyimpan konten halaman web
Hasil string = "";
//Tentukan aliran input karakter yang di-buffer
BufferedReader di = null;
mencoba {
//Konversi string menjadi objek url
URL realUrl = URL baru(url);
// Inisialisasi tautan ke url itu
Koneksi URLConnection = realUrl.openConnection();
// Mulai koneksi sebenarnya
koneksi.koneksi();
//Inisialisasi aliran input BufferedReader untuk membaca respons URL
di = BufferedReader baru(InputStreamReader baru(
koneksi.getInputStream()));
// Digunakan untuk menyimpan sementara data dari setiap baris yang diambil
garis senar;
while ((baris = masuk.readLine()) != null) {
// Lintasi setiap baris yang diambil dan simpan sebagai hasilnya
hasil += baris;
}
} tangkapan (Pengecualian e) {
System.out.println("Terjadi pengecualian saat mengirimkan permintaan GET!" + e);
e.printStackTrace();
}
// Gunakan akhirnya untuk menutup aliran input
Akhirnya {
mencoba {
jika (dalam != nol) {
melampirkan();
}
} tangkapan (Pengecualian e2) {
e2.printStackTrace();
}
}
hasil pengembalian;
}
String statis RegexString(String targetStr, String patternStr) {
// Tentukan template gaya, menggunakan ekspresi reguler, dan konten yang akan diambil ada dalam tanda kurung
// Ini sama dengan mengubur jebakan dan akan jatuh jika cocok.
Pola pola = Pattern.compile(patternStr);
//Tentukan pencocokan untuk pencocokan
Pencocokan pencocokan = pattern.matcher(targetStr);
// jika ditemukan
if (pencocokan.temukan()) {
// cetak hasilnya
return matcher.group(1);
}
kembali "";
}
public static void main(String[] args) {
// Tentukan link yang akan dikunjungi
String url = "http://www.baidu.com";
//Akses tautan dan dapatkan konten halaman
Hasil string = SendGet(url);
// Gunakan ekspresi reguler untuk mencocokkan konten src gambar
String imgSrc = RegexString(hasil, "Tata bahasa reguler yang akan datang");
// mencetak hasil
Sistem.keluar.println(imgSrc);
}
}
Oke, sekarang semuanya sudah siap, tinggal tata bahasa biasa!
Jadi pernyataan reguler mana yang lebih tepat?
Kami menemukan bahwa selama kami mengambil string src="xxxxxx", kami dapat mengambil seluruh tautan src.
Jadi pernyataan reguler sederhana: src=/"(.+?)/"
Kode lengkapnya adalah sebagai berikut:
import java.io.*;
impor java.net.*;
import java.util.regex.*;
kelas publik Utama {
String statis SendGet(String url) {
//Tentukan string untuk menyimpan konten halaman web
Hasil string = "";
//Tentukan aliran input karakter yang di-buffer
BufferedReader di = null;
mencoba {
//Konversi string menjadi objek url
URL realUrl = URL baru(url);
// Inisialisasi tautan ke url itu
Koneksi URLConnection = realUrl.openConnection();
// Mulai koneksi sebenarnya
koneksi.koneksi();
//Inisialisasi aliran input BufferedReader untuk membaca respons URL
di = BufferedReader baru(InputStreamReader baru(
koneksi.getInputStream()));
// Digunakan untuk menyimpan sementara data dari setiap baris yang diambil
garis senar;
while ((baris = masuk.readLine()) != null) {
// Lintasi setiap baris yang diambil dan simpan sebagai hasilnya
hasil += baris;
}
} tangkapan (Pengecualian e) {
System.out.println("Terjadi pengecualian saat mengirimkan permintaan GET!" + e);
e.printStackTrace();
}
// Gunakan akhirnya untuk menutup aliran input
Akhirnya {
mencoba {
jika (dalam != nol) {
melampirkan();
}
} tangkapan (Pengecualian e2) {
e2.printStackTrace();
}
}
hasil pengembalian;
}
String statis RegexString(String targetStr, String patternStr) {
// Tentukan template gaya, menggunakan ekspresi reguler, dan konten yang akan diambil ada dalam tanda kurung
// Ini sama dengan mengubur jebakan dan akan jatuh jika cocok.
Pola pola = Pattern.compile(patternStr);
//Tentukan pencocokan untuk pencocokan
Pencocokan pencocok = pattern.matcher(targetStr);
// jika ditemukan
if (pencocokan.temukan()) {
// cetak hasilnya
return matcher.group(1);
}
kembalikan "Tidak Ada";
}
public static void main(String[] args) {
// Tentukan link yang akan dikunjungi
String url = "http://www.baidu.com";
//Akses tautan dan dapatkan konten halaman
Hasil string = SendGet(url);
// Gunakan ekspresi reguler untuk mencocokkan konten src gambar
String imgSrc = RegexString(hasil, "src=/"(.+?)/"");
// mencetak hasil
Sistem.keluar.println(imgSrc);
}
}
Dengan cara ini, kita bisa menggunakan java untuk mengambil link ke LOGO Baidu.
Meskipun saya telah menghabiskan banyak waktu untuk membicarakan Baidu, fondasinya harus diletakkan dengan kokoh. Lain kali kita akan secara resmi mulai fokus pada Zhihu! ~