Saya juga pernah menggunakan crawler sebelumnya, seperti menggunakan Nutch untuk merangkak benih yang ditentukan, mencari berdasarkan data merayap, dan secara kasar melihat beberapa kode sumber. Tentu saja, Nutch menganggap perayap sangat komprehensif dan cermat. Setiap kali saya melihat informasi halaman web dan informasi pemrosesan yang telah dirangkak di atas layar, saya selalu merasa bahwa ini adalah teknologi yang sangat gelap. Kali ini, saya mengambil keuntungan dari kesempatan untuk memilah MVC musim semi dan ingin membuat perayap kecil sendirian. Tidak masalah jika saya bisa melakukannya dengan mudah, dan beberapa bug kecil tidak masalah. Yang saya butuhkan hanyalah situs web benih yang dapat merangkak informasi yang saya inginkan. Jika ada pengecualian, itu mungkin karena beberapa API digunakan secara tidak benar, atau mereka mungkin menghadapi status permintaan HTTP yang abnormal, atau ada masalah dengan membaca dan menulis database. Dalam proses pelaporan pengecualian dan memecahkan pengecualian, Jewelcrawler (nama panggilan SON) sudah dapat merangkak data secara mandiri, dan ada juga keterampilan kecil untuk analisis emosional berdasarkan algoritma Word2VEC.
Mungkin ada pengecualian yang tidak diketahui yang menunggu untuk diselesaikan nanti, dan beberapa kinerja perlu dioptimalkan, seperti interaksi dengan database, membaca dan menulis data, dll. Namun, saya tidak punya banyak energi untuk menempatkan ini di tahun ini, jadi saya akan memberikan ringkasan sederhana hari ini. Dua artikel pertama terutama fokus pada fungsi dan hasil. Artikel ini berbicara tentang bagaimana Jewelcrawler lahir dan menempatkan kode di GitHub (alamat kode sumber ada di akhir artikel). Jika Anda tertarik, Anda dapat memperhatikan (hanya untuk komunikasi dan pembelajaran, tolong doban. Harap doban. Jadilah lebih tulus dan lebih sedikit bahaya)
Pendahuluan Lingkungan
Alat Pengembangan: Ide Intellij 14
Database: MySQL 5.5 + Alat Manajemen Database Navicat (dapat digunakan untuk terhubung ke database kueri)
Bahasa: Java
Manajemen Paket JAR: Maven
Manajemen Versi: Git
Struktur Direktori
di dalam
com.ansj.vec adalah implementasi versi Java dari algoritma Word2vec
com.jackie.crawler.doBanmovie adalah modul implementasi crawler, yang juga termasuk
Beberapa paket kosong karena modul ini belum digunakan, di antaranya
Modul sumber daya menyimpan file konfigurasi dan file sumber daya, seperti
Modul uji adalah modul uji yang digunakan untuk menulis UT.
Konfigurasi Basis Data
1. Tambahkan paket ketergantungan
Jewelcrawler menggunakan manajemen Maven, jadi Anda hanya perlu menambahkan dependensi yang sesuai di pom.xml.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.1.RELEASE</version></dependency><dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version></dependency><dependency> <groupid> commons-dbcp </provationid> <ArTifactId> commons-dbcp </artifactid> <ArtifactId> commons-dbcp </artifactid> <ArtiFacTid> Commons-dbcp </arttifactid> <version> 1.4 </Versi> </Dependency> <groups> <groupsid> MysID> </Versi </Versi> </Dependency> <group> <group> Mysid> <ArTifactId> mysql-connector-java </stifactid> <version> 5.1.38 </version> </dependency> <dependency> <groupid> mysql </groupid> <ArTifactId> MySQL-Connector-java </artifactid> <version> 5.1.38 </Version> </Versi> </Versi> </Versi> </Versi> </Versi> </Versi> </Versi> </Versi> </Versi> </Versi> </Version> </Version> </Version> </Version> </Version> </Versi.
2. Deklarasikan Kacang Sumber Data
Kita perlu mendeklarasikan kacang sumber data di beans.xml
<Context: Properti-PlaceHolder Lokasi = "ClassPath*:*. Properties"/> <bean id = "DataSource" Destroy-Method = "Tutup"> <nama properti = "driverclassname" value = "$ {jdbc.driver}"/> <nama properti = "name =" USOME = "$ {jdbc.url}" value = "$ {jdbc.username}"/> <name properti = "kata sandi" value = "$ {jdbc.password}"/>Catatan: Berikut adalah file konfigurasi eksternal JDBC.Properties terikat, dan parameter sumber data spesifik dibaca dari file ini.
Jika Anda menghadapi masalah, "SQL [Sisipkan ke Nilai Pengguna (ID) (?)]; Field 'Name' tidak memiliki nilai default;" Solusinya adalah mengatur bidang tabel yang sesuai ke bidang pertumbuhan diri.
Masalah yang dihadapi saat parsing halaman
Untuk data halaman web yang Anda rangkak, Anda perlu menguraikan struktur DOM dan mendapatkan data yang Anda inginkan. Selama periode ini, Anda mengalami kesalahan berikut
org.htmlparser.node tidak dikenali
Solusi: Tambahkan ketergantungan paket jar
<dependency> <GroupId> org.htmlparser </groupId> <ArTifactId> htmlparser </stifactid> <version> 1.6 </version> </dependency>
org.apache.http.httpentity tidak dikenali
Solusi: Tambahkan ketergantungan paket jar
<dependency> <GroupId> org.apache.httpComponents </groupId> <ArTifactId> httpClient </artifactid> <version> 4.5.2 </version> </dependency>
Tentu saja, ini adalah masalah yang dihadapi selama periode tersebut, dan analisis halaman yang dilakukan oleh JSoup akhirnya digunakan.
Kecepatan unduhan gudang maven lambat
Saya menggunakan repositori maven central default sebelumnya, dan kecepatan mengunduh paket toples sangat lambat. Saya tidak tahu apakah itu masalah jaringan saya atau alasan lain. Kemudian, saya menemukan repositori Maven dari Alibaba Cloud Online. Setelah pembaruan, disarankan untuk muntah darah dibandingkan dengan sebelumnya.
<Mirrors> <ir mirror> <den> alimaven </dent> <name> aliyun maven </name> <ubl> http://maven.aliyun.com/nexus/content/groups/public/ </url> <mirrorof> central </mirrorof> </mirror>
Temukan file settings.xml Maven dan tambahkan gambar ini.
Cara Membaca File Di Bawah Modul Sumber Daya
Misalnya, baca file seed.properties
@Test public void testfile () {file seedFile = file baru (this.getClass (). GetResource ("/seed.properties"). GetPath ()); System.out.print ("===========" + seedfile.length () + "============"); }Tentang ekspresi reguler
Saat menggunakan Ekspresi Reguler Regrex, jika pola yang ditentukan dicocokkan, Anda perlu menghubungi metode pencocokan pencocokan sebelum Anda dapat menggunakan metode grup untuk menemukan substring. Tidak ada cara untuk menemukan hasil yang Anda inginkan dengan memanggil metode grup secara langsung.
Saya melihat kode sumber kelas pencocokan di atas
Paket java.util.regex; impor java.util.objects; Public Final Class Matcher mengimplementasikan MatchResult { /*** Objek pola yang membuat pencocokan ini. */ Pola parentpattern; /*** Penyimpanan yang digunakan oleh grup. Mereka mungkin berisi nilai -nilai yang tidak valid jika * grup dilewati selama pencocokan. */ Int [] grup; /*** Kisaran dalam urutan yang harus dicocokkan. Jangkar * akan cocok dengan batas -batas "keras" ini. Mengubah wilayah * mengubah nilai -nilai ini. */ int from, to; /** * LookBehind menggunakan nilai ini untuk memastikan bahwa kecocokan subekspresi * berakhir pada titik di mana lookbehind ditemui. */ int lookbehindto; /*** String asli dicocokkan. */ Teks Charsequence; /*** keadaan pencocokan yang digunakan oleh simpul terakhir. Noanchor digunakan ketika kecocokan * tidak harus mengkonsumsi semua input. Endanchor adalah * mode yang digunakan untuk mencocokkan semua input. */ Static Final Int Endanchor = 1; statis final int noanchor = 0; int acceptMode = noanchor; /*** Kisaran string yang terakhir cocok dengan polanya. Jika pertandingan * terakhir gagal maka pertama adalah -1; Terakhir awalnya memegang 0 lalu * memegang indeks akhir pertandingan terakhir (yang merupakan tempat pencarian * berikutnya dimulai). */ int first = -1, terakhir = 0; /*** Indeks akhir dari apa yang cocok dalam operasi pertandingan terakhir. */ int oldlast = -1; /*** Indeks posisi terakhir yang diterapkan dalam substitusi. */ int LastAppendPosition = 0; /** * Penyimpanan yang digunakan oleh node untuk memberi tahu pengulangan apa yang mereka lakukan dalam * sebuah pola, dan di mana kelompok dimulai. Node itu sendiri tanpa kewarganegaraan, * sehingga mereka mengandalkan bidang ini untuk menahan keadaan selama pertandingan. */ int [] penduduk setempat; /** * Boolean menunjukkan apakah lebih banyak input dapat mengubah * hasil pertandingan terakhir. * * Jika Hitend benar, dan kecocokan ditemukan, maka lebih banyak input * dapat menyebabkan kecocokan yang berbeda ditemukan. * Jika Hitend benar dan kecocokan tidak ditemukan, maka lebih banyak * input dapat menyebabkan kecocokan ditemukan. * Jika Hitend salah dan kecocokan tidak ditemukan, maka lebih banyak * input tidak akan menyebabkan kecocokan ditemukan. */ Boolean Hitend; /** * Boolean menunjukkan apakah lebih banyak input dapat mengubah * kecocokan positif menjadi yang negatif. * * Jika Perlu itu benar, dan kecocokan ditemukan, maka lebih banyak * input dapat menyebabkan kecocokan hilang. * Jika kebutuhannya salah dan kecocokan ditemukan, maka lebih banyak * input mungkin mengubah kecocokan tetapi pertandingan tidak akan hilang. * Jika suatu kecocokan tidak ditemukan, maka Needend tidak memiliki arti. */ Boolean memerlukan; /** * Jika transparentbounds benar maka batas -batas wilayah * pencocokan ini transparan untuk melihat, terlihat, * dan konstruksi pencocokan batas yang mencoba melihat di luarnya. */ boolean transparentbounds = false; /** * Jika jangkar adalah benar maka batas -batas jangkar pencocokan wilayah * pencocokan ini seperti ^ dan $. */ boolean anchoringbounds = true; /*** Tidak ada konstruktor default. * / Matcher () {} / *** Semua pencocokan memiliki status yang digunakan berdasarkan pola selama pertandingan. */Pencocokan (Pola induk, teks charsequence) {this.parentpattern = induk; this.text = teks; // Alokasikan penyimpanan negara int parentgroupCount = Math.max (Parent.CapturingGroupCount, 10); grup = int baru [parentgroupCount * 2]; penduduk setempat = int baru [parent.localcount]; // Masukkan bidang ke dalam status awal reset ();} ..../*** Mengembalikan input setelah yang cocok dengan pertandingan sebelumnya. * * <p> Untuk pencocokan <i> m </i> dengan urutan input <i> s </i>, * ekspresi <i> m. </i> <tt> grup () </tt> dan * <i> s. </i> <tt> substring (</tt> <i> m. <i> m. </i> <tt> end ()) </tt> * setara. </p> * * <p> Perhatikan bahwa beberapa pola, misalnya <tt> a * </tt>, cocokkan string * kosong. Metode ini akan mengembalikan string kosong saat pola * berhasil mencocokkan string kosong dalam input. </p> * * @return urutan (mungkin kosong) yang cocok dengan pertandingan sebelumnya, * dalam bentuk string * * @Throws IllegalStateException * Jika belum ada kecocokan yang dicoba, * atau jika operasi pertandingan sebelumnya gagal */grup string publik () {return group (0);}/** * mengembalikan input yang ditangkap oleh kelompok yang diberikan selama grup yang diberikan. * * <p> Untuk pencocokan <i> m </i>, urutan input <i> s </i>, dan indeks grup * <i> g </i>, ekspresi <i> m. </i> <tt> grup (</tt> <i> g </i> <tt> </i> </tt> dan * <i> s. </i> <tt> Substring (</tt> <i> m. </i> <tt> Mulai (</tt> <i> g </i> <tt>), </tt> <i> m. </i> </tt. </p> * * <p> <a href = "pola.html#cg"> Grup penangkap </a> diindeks dari kiri * ke kanan, mulai dari satu. Grup Zero menunjukkan seluruh pola, jadi * ekspresi <tt> m.group (0) </tt> setara dengan <tt> m.group () </tt>. * </p> * * <p> Jika kecocokan berhasil tetapi grup yang ditentukan gagal mencocokkan * bagian mana pun dari urutan input, maka <tt> null </tt> dikembalikan. Catatan * Bahwa beberapa grup, misalnya <Tt> (A *) </tt>, cocokkan string kosong. * Metode ini akan mengembalikan string kosong ketika grup seperti itu berhasil * mencocokkan string kosong di input. </p> * @param group * The index of a capturing group in this matcher's pattern * * @return The (possibly empty) subsequent captured by the group * during the previous match, or <tt>null</tt> if the group * failed to match part of the input * * @throws IllegalStateException * If no match has yet been attempted, * or if the previous match operation failed * * @throws IndexOutOfBoundsException * If Tidak ada grup penangkap dalam pola * dengan indeks */grup string publik (grup int) {if (pertama <0) melempar IllegalStateException baru ("No Match Found"); if (grup <0 || group> groupCount ()) lempar indexOutofboundsException baru ("no group" + grup); if ((grup [grup*2] == -1) || (grup [grup*2+1] == -1)) mengembalikan null; return getSubequence (grup [grup * 2], grup [grup * 2 + 1]). ToString ();}/** * Berusaha untuk menemukan urutan berikutnya dari urutan input yang cocok dengan * pola. * * <p> Metode ini dimulai pada awal wilayah pencocokan ini, atau, jika * permohonan metode sebelumnya berhasil dan pencocokan telah * sejak itu tidak diatur ulang, pada karakter pertama yang tidak cocok dengan kecocokan * sebelumnya. * * <p> Jika kecocokan berhasil maka informasi lebih lanjut dapat diperoleh melalui * <tt> Mulai </tt>, <tt> end </tt>, dan metode <tt> grup </tt>. </p> * * @return <tt> true </tt> if, dan hanya jika, urutan dari urutan input * cocok dengan pola pencocokan ini */public boolean find () {int nextSearchIndex = last; if (nextSearchIndex == pertama) nextSearchIndex ++; // Jika pencarian berikutnya dimulai sebelum wilayah, mulai di wilayah jika (nextsearchIndex <dari) nextsearchIndex = from; // Jika pencarian berikutnya dimulai di luar wilayah maka gagal jika (nextsearchIndex> to) {for (int i = 0; i <groups.length; i ++) grup [i] = -1; mengembalikan false; } return Search (nextSearchIndex);} /*** memulai pencarian untuk menemukan pola dalam batas yang diberikan. * Grup diisi dengan nilai default dan kecocokan root * mesin negara dipanggil. Mesin negara bagian akan menahan keadaan * dari pertandingan karena hasilnya dalam pencocokan ini. * * Matcher.dari tidak diatur di sini, karena itu adalah batas "keras" * dari awal pencarian yang akan diatur jangkar. Dari param * adalah batas "lunak" dari awal pencarian, yang berarti bahwa * Regex mencoba untuk mencocokkan pada indeks itu tetapi tidak akan cocok di sana. Panggilan * berikutnya ke metode pencarian dimulai pada batas "lunak" baru yang merupakan * akhir dari pertandingan sebelumnya. */pencarian boolean (int from) {this.hitend = false; this.requireend = false; dari = dari <0? 0: dari; this.first = from; this.oldLast = oldlast <0? dari: oldlast; untuk (int i = 0; i <groups.length; i ++) grup [i] = -1; acceptMode = noanchor; Hasil boolean = parentpattern.root.match (ini, dari, teks); if (! hasilnya) this.first = -1; this.oldLast = this.Last; Hasil pengembalian;} ...}Alasannya adalah ini: Jika Anda tidak memanggil metode Find Fored terlebih dahulu dan hubungi grup secara langsung, Anda dapat menemukan bahwa Metode Grup Panggilan Grup (Int Group). Ada jika pertama <0 dalam metode metode metode ini. Jelas, kondisi ini benar di sini, karena nilai awal pertama adalah -1, jadi pengecualian akan dilemparkan ke sini. Namun, jika Anda memanggil metode Find, Anda dapat menemukan pencarian (NextSearchIndex) pada akhirnya akan dipanggil. Perhatikan bahwa NextSearchIndex di sini telah ditetapkan oleh Last, dan Nilai yang terakhir adalah 0, dan kemudian melompat ke metode pencarian
pencarian boolean (int from) {this.hitend = false; this.requireend = false; dari = dari <0? 0: dari; this.first = from; this.oldLast = oldlast <0? dari: oldlast; untuk (int i = 0; i <groups.length; i ++) grup [i] = -1; acceptMode = noanchor; Hasil boolean = parentpattern.root.match (ini, dari, teks); if (! hasilnya) this.first = -1; this.oldLast = this.Last; Hasil pengembalian;} NextSearchIndex ini diteruskan ke dari, dan dari ditugaskan untuk pertama di badan metode. Oleh karena itu, setelah memanggil metode Find, yang pertama dari ini tidak lagi -1, dan tidak melempar pengecualian.
Kode sumber telah diunggah ke Baidu Netdisk: http://pan.baidu.com/s/1dfwtvnz
Masalah yang disebutkan di atas relatif hancur, dan mereka adalah beberapa ringkasan saat menghadapi masalah dan menyelesaikannya. Akan ada masalah lain selama operasi tertentu. Jika Anda memiliki pertanyaan atau saran, jangan ragu untuk menyebutkan ^^.
Akhirnya, letakkan beberapa potong data yang dirangkak sejauh ini
Tabel rekaman
Di antara mereka, 79.032 disimpan, dan 48.471 halaman web merangkak
Meja film
Saat ini, 2964 karya film dan televisi telah dirangkak
Tabel komentar
29.711 catatan dirangkak
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.