Pendahuluan: Sebelum menulis artikel ini, saya terutama membaca beberapa gaya menulis crawler yang serupa. Beberapa dari mereka menggunakan antrian untuk menulisnya, yang terasa tidak terlalu intuitif. Beberapa hanya memiliki satu permintaan dan kemudian melakukan analisis halaman. Mereka tidak bangun sama sekali secara otomatis. Ini juga disebut crawler? Karena itu, saya menulis tentang perayap sederhana berdasarkan ide -ide saya sendiri.
Pendahuluan Algoritma
Program ini menggunakan algoritma yang lebih luas dalam idenya, memulai permintaan untuk tautan yang tidak terpelajar satu demi satu, dan kemudian mem-parsing halaman yang dikembalikan dengan ekspresi reguler, mengeluarkan tautan baru yang belum ditemukan, menambahkannya ke koleksi, dan melintasi di loop berikutnya.
Implementasi spesifik menggunakan peta <string, boolean>, dan pasangan nilai kunci adalah tautan dan apakah akan dilalui. Dua koleksi peta digunakan dalam program ini, yaitu: Oldmap dan Newmap. Tautan awal ada di Oldmap, dan kemudian permintaan dibuat untuk tautan dengan bendera false di oldmap, parse halaman, dan gunakan reguler untuk menghapus tautan di bawah tag <a>. Jika tautan ini tidak ada di Oldmap dan Newmap, itu berarti bahwa ini adalah tautan baru. Pada saat yang sama, jika tautan ini adalah tautan dari situs web target yang perlu kami peroleh, kami akan memasukkan tautan ini ke newmap dan terus menguraikannya. Ketika halaman diuraikan, nilai tautan pada halaman saat ini di Oldmap diatur ke true, yang berarti telah dilalui.
Akhirnya, ketika seluruh tautan yang belum dilalui oleh Oldmap telah dilalui, jika Anda menemukan bahwa Newmap tidak kosong, itu berarti bahwa tautan baru telah dihasilkan dalam loop ini. Oleh karena itu, tautan baru ini ditambahkan ke OldMap dan terus melintasi secara rekursif. Kalau tidak, itu berarti bahwa tidak ada tautan baru yang dihasilkan dalam loop ini. Jika Anda terus mengulang, Anda tidak dapat lagi menghasilkan tautan baru. Karena tugas sudah berakhir, koleksi tautan Oldmap akan dikembalikan.
Dua implementasi program
Gagasan terkait di atas telah dijelaskan dengan sangat jelas, dan ada komentar di bidang utama dalam kode, jadi saya tidak akan membicarakannya di sini, kodenya adalah sebagai berikut:
Tindakan Paket; Impor java.io.bufferedReader; impor java.io.ioException; impor java.io.inputStream; import java.io.inputStreamReader; impor java.net.httpurlconnection; impor java.net.malformsception; impor java. java.util.linkedhashmap; import java.util.map; import java.util.regex.matcher; import java.util.regex.pattern; webcrawlerdemo public webcrawler (string = args) {webcrawlerdemo {public static Main (string [] args) {WebCrawlerDemo; webcrawlerdemo.myprint ("http://www.zifangsky.cn"); } public void myprint (String baseUrl) {peta <string, boolean> oldmap = new LinkedHashMap <string, boolean> (); // tautan penyimpanan-whether itu dilintasi // nilai kunci pair string oldlinkhost = ""; // Pola host p = pola.compile ("(https?: //)? [^/// s]*"); // misalnya: http://www.zifangsky.cn pencocokan m = p.matcher (baseUrl); if (m.find ()) {oldlinkhost = m.group (); } oldmap.put (baseUrl, false); oldmap = crawllinks (oldlinkhost, oldmap); untuk (MAP.ENTRY <String, Boolean> Pemetaan: oldmap.entryset ()) {System.out.println ("Link:" + Mapping.getKey ()); }} /*** Merayap semua tautan halaman web yang dapat dirangkak di situs web, dan menggunakan algoritma prioritas luas dalam ide tersebut. Permintaan mendapatkan secara konstan diprakarsai untuk tautan baru yang belum dilalui sampai set lengkap dilalui. This means that new links cannot be found, and the task ends * * @param oldLinkHost Domain name, such as: http://www.zifangsky.cn * @param oldMap Collection of links to be traversed* * @return Return all crawled link collections* */ private Map<String, Boolean> crawlLinks(String oldLinkHost, Map<String, Boolean> oldMap) { Peta <string, boolean> newMap = new LinkedHashMap <string, boolean> (); String oldlink = ""; untuk (map.entry <string, boolean> pemetaan: oldmap.entryset ()) {system.out.println ("tautan:" + mapping.getKey () + "--------- Periksa:" + mapping.getValue ()); // jika belum dilalui oleh (! Mapping.getValue ()) {oldlink = mapping.getKey (); // inisiasi permintaan get coba {url url = url baru (oldlink); HttpurlConnection connection = (httpurlConnection) url .openconnection (); connection.setRequestMethod ("get"); Connection.setConnectTimeOut (2000); Connection.setreadtimeout (2000); if (connection.getResponsecode () == 200) {inputStream inputStream = connection.getInputStream (); BufferedReader Reader = BufferedReader baru (InputStreamReader baru (InputStream, "UTF-8")); String line = ""; Pattern pattern = Pattern .compile("<a.*?href=[/"']?((https?://)?/?[^/"']+)[/"']?.*?>(.+)</a>"); Matcher matcher = null; while ((line = reader.readLine()) != null) { matcher = pattern.matcher(line); if (matcher.find ()) {string newLink = matcher.group (1) .trim (); // tautan // string title = matcher.group (3) .trim (); Newlink; ! newmap.containskey (newLink) && newlink.startswith (oldlinkhost)) {// system.out.println ("Temp2:" + Newlink); e.printstacktrace ();} coba {thread.sleep (1000); } catch (InterruptedException e) {E.PrintStackTrace (); } oldmap.replace (oldlink, false, true); }} // Ada tautan baru, lanjutkan ke traverse if (! Newmap.isempty ()) {oldmap.putAll (newMap); oldmap.putall (crawllinks (oldlinkhost, oldmap)); // Karena karakteristik peta, tidak akan ada duplikat pasangan nilai kunci} return oldmap; }}Tiga hasil tes akhir
PS: Faktanya, menggunakan rekursi tidak terlalu bagus, karena jika situs web memiliki lebih banyak halaman, konsumsi memori akan sangat besar jika program berjalan untuk waktu yang lama.
Terima kasih telah membaca, saya harap ini dapat membantu Anda. Terima kasih atas dukungan Anda untuk situs ini!