Pada tahap awal, kami merayapi judul di bawah tautan ini:
http://www.zhihu.com/explore/recommendations
Namun yang jelas halaman ini tidak bisa mendapatkan jawabannya.
Halaman pertanyaan lengkap akan terlihat seperti ini:
http://www.zhihu.com/question/22355264
Melihat lebih dekat, aha, kelas enkapsulasi kita perlu dikemas lebih lanjut. Setidaknya diperlukan questionDescription untuk menyimpan deskripsi pertanyaan:
impor java.util.ArrayList;
kelas publik Zhihu {
pertanyaan String publik; // pertanyaan
Deskripsi pertanyaan String publik; // Deskripsi pertanyaan
String publik zhihuUrl;//Tautan halaman web
public ArrayList<String> jawaban; // Array untuk menyimpan semua jawaban
// Konstruktor menginisialisasi data
Zhihu publik() {
pertanyaan = "";
pertanyaanDeskripsi = "";
zhihuUrl = "";
jawaban = Daftar Array baru<String>();
}
@Mengesampingkan
String publik keString() {
kembalikan "Pertanyaan:" + pertanyaan + "/n" + "Deskripsi:" + questionDescription + "/n"
+ "Tautan:" + zhihuUrl + "/njawaban:" + jawaban + "/n";
}
}
Kami menambahkan parameter ke konstruktor Zhihu untuk menyetel nilai URL. Karena URL ditentukan, deskripsi dan jawaban atas pertanyaan dapat diambil.
Mari kita ubah metode Spider dalam mendapatkan objek Zhihu dan hanya mendapatkan URL-nya saja:
static ArrayList<Zhihu> GetZhihu(Konten string) {
// Tentukan terlebih dahulu ArrayList untuk menyimpan hasilnya
ArrayList<Zhihu> hasil = ArrayList<Zhihu>();
// Digunakan untuk mencocokkan url yang merupakan link ke pertanyaan
Pola urlPattern = Pattern.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Pencocokan urlMatcher = urlPattern.matcher(konten);
// Apakah ada objek pencocokan yang berhasil
boolean isFind = urlMatcher.find();
sementara (isFind) {
//Tentukan objek Zhihu untuk menyimpan informasi yang diambil
Zhihu zhihuTemp = Zhihu baru(urlMatcher.group(1));
//Tambahkan hasil pencocokan yang berhasil
hasil.tambahkan(zhihuTemp);
// Lanjutkan untuk menemukan objek berikutnya yang cocok
isFind = urlMatcher.find();
}
mengembalikan hasil;
}
Selanjutnya, dalam metode konstruksi Zhihu, dapatkan semua data detail melalui url.
Kita perlu mengolah urlnya terlebih dahulu, karena untuk beberapa jawaban, urlnya adalah:
http://www.zhihu.com/question/22355264/answer/21102139
Beberapa khusus untuk masalahnya, dan urlnya adalah:
http://www.zhihu.com/question/22355264
Maka yang jelas kita butuhkan adalah tipe kedua, jadi kita perlu menggunakan aturan reguler untuk memotong tipe link pertama menjadi tipe kedua.
// menangani url
boolean getRealUrl(String url) {
// Ubah http://www.zhihu.com/question/22355264/answer/21102139
//Konversikan ke http://www.zhihu.com/question/22355264
// Jika tidak, tidak ada perubahan
Pola pola = Pattern.compile("question/(.*?)/");
Pencocokan pencocokan = pattern.matcher(url);
if (pencocokan.temukan()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} kalau tidak {
kembali salah;
}
kembali benar;
}
Langkah selanjutnya adalah mendapatkan berbagai bagian.
Mari kita lihat judulnya terlebih dahulu:
Pahami saja kelas itu dalam bentuk reguler. Pernyataan reguler dapat ditulis sebagai: zm-editable-content/">(.+?)<
Jalankan untuk melihat hasilnya:
Aduh, lumayan.
Selanjutnya ambil deskripsi masalahnya:
Aha, prinsipnya sama, ambil kelasnya, karena itu harus menjadi pengenal uniknya.
Metode verifikasi: Klik kanan untuk melihat kode sumber halaman, ctrl+F untuk melihat apakah ada string lain di halaman.
Kemudian, setelah verifikasi, ada yang tidak beres:
Kelas di depan judul dan isi deskripsinya sama.
Itu hanya dapat ditangkap kembali dengan memodifikasi pola reguler:
// judul pertandingan
pattern = Pattern.compile("zh-pertanyaan-judul.+?<h2.+?>(.+?)</h2>");
matcher = pola.matcher(konten);
if (pencocokan.temukan()) {
pertanyaan = matcher.group(1);
}
// Cocokkan deskripsi
pola=Pola
.compile("zh-pertanyaan-detail.+?<div.+?>(.*?)</div>");
matcher = pola.matcher(konten);
if (pencocokan.temukan()) {
questionDescription = matcher.group(1);
}
Hal terakhir adalah mengulang untuk mendapatkan jawabannya:
Pernyataan reguler tentatif awal: /answer/content.+?<div.+?>(.*?)</div>
Setelah mengubah kode, kita akan menemukan bahwa perangkat lunak berjalan jauh lebih lambat karena perlu mengunjungi setiap halaman web dan menangkap konten di dalamnya.
Misalnya, jika ada 20 pertanyaan yang direkomendasikan oleh editor, maka Anda perlu mengunjungi halaman web tersebut sebanyak 20 kali, dan kecepatannya akan melambat.
Cobalah, kelihatannya bagus:
Oke, biarkan saja seperti ini untuk saat ini~ Lain kali kami akan terus melakukan beberapa penyesuaian mendetail, seperti multi-threading, menulis aliran IO secara lokal, dll.
Terlampir adalah kode sumber proyek:
Zhihu.java
impor java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
kelas publik Zhihu {
pertanyaan String publik; // pertanyaan
Deskripsi pertanyaan String publik; // Deskripsi pertanyaan
String publik zhihuUrl;//Tautan halaman web
public ArrayList<String> jawaban; // Array untuk menyimpan semua jawaban
// Konstruktor menginisialisasi data
Zhihu publik(String url) {
//Inisialisasi properti
pertanyaan = "";
pertanyaanDeskripsi = "";
zhihuUrl = "";
jawaban = Daftar Array baru<String>();
// Tentukan apakah url tersebut legal
jika (getRealUrl(url)) {
System.out.println("merangkak" + zhihuUrl);
// Dapatkan detail soal dan jawaban berdasarkan url
Konten string = Spider.SendGet(zhihuUrl);
Pola pola;
pencocokan pencocokan;
// judul pertandingan
pattern = Pattern.compile("zh-pertanyaan-judul.+?<h2.+?>(.+?)</h2>");
matcher = pola.matcher(konten);
if (pencocokan.temukan()) {
pertanyaan = matcher.group(1);
}
// Cocokkan deskripsi
pola=Pola
.compile("zh-pertanyaan-detail.+?<div.+?>(.*?)</div>");
matcher = pola.matcher(konten);
if (pencocokan.temukan()) {
questionDescription = matcher.group(1);
}
// Cocokkan jawaban
pattern = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
matcher = pola.matcher(konten);
boolean isFind = matcher.find();
sementara (isFind) {
jawaban.tambahkan(matcher.grup(1));
isFind = matcher.find();
}
}
}
// Ambil pertanyaan, deskripsi, dan jawaban Anda sendiri berdasarkan url Anda sendiri
boolean publik getAll() {
kembali benar;
}
// menangani url
boolean getRealUrl(String url) {
// Ubah http://www.zhihu.com/question/22355264/answer/21102139
//Konversikan ke http://www.zhihu.com/question/22355264
// Jika tidak, tidak ada perubahan
Pola pola = Pattern.compile("question/(.*?)/");
Pencocokan pencocokan = pattern.matcher(url);
if (pencocokan.temukan()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} kalau tidak {
kembali salah;
}
kembali benar;
}
@Mengesampingkan
String publik keString() {
kembalikan "Pertanyaan:" + pertanyaan + "/n" + "Deskripsi:" + questionDescription + "/n"
+ "Tautan:" + zhihuUrl + "/nJawaban:" + jawaban.size() + "/n";
}
}
laba-laba.java
impor java.io.BufferedReader;
impor java.io.InputStreamReader;
impor java.net.URL;
impor java.net.URLConnection;
impor java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
laba-laba kelas publik {
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(), "UTF-8"));
// 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;
}
// Dapatkan semua konten Zhihu yang direkomendasikan oleh editor
static ArrayList<Zhihu> DapatkanRekomendasi(Konten string) {
// Tentukan terlebih dahulu ArrayList untuk menyimpan hasilnya
ArrayList<Zhihu> hasil = ArrayList<Zhihu>();
// Digunakan untuk mencocokkan url yang merupakan link ke pertanyaan
Pola pola = Pola
.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Pencocokan pencocokan = pattern.matcher(konten);
// Apakah ada objek pencocokan yang berhasil
Boolean isFind = matcher.find();
sementara (isFind) {
//Tentukan objek Zhihu untuk menyimpan informasi yang diambil
Zhihu zhihuTemp = new Zhihu(matcher.group(1));
//Tambahkan hasil pencocokan yang berhasil
hasil.tambahkan(zhihuTemp);
// Lanjutkan untuk menemukan objek berikutnya yang cocok
isFind = matcher.find();
}
mengembalikan hasil;
}
}
Main.java
impor java.util.ArrayList;
kelas publik Utama {
public static void main(String[] args) {
// Tentukan link yang akan dikunjungi
String url = "http://www.zhihu.com/explore/recommendations";
//Akses tautan dan dapatkan konten halaman
Konten string = Spider.SendGet(url);
// Dapatkan rekomendasi editor
ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(konten);
// mencetak hasil
Sistem.keluar.println(myZhihu);
}
}
Di atas adalah keseluruhan catatan perolehan jawaban Zhihu, sangat detail. Teman-teman yang membutuhkan bisa merujuknya.