Ich habe auch zuvor Crawler verwendet, z. B. Nutsch zum Kriechen eines bestimmten Saatguts, die Suche nach den Krabbendaten und ungefähr einen Quellcode. Natürlich berücksichtigt Nutsch Crawler sehr umfassend und akribisch. Immer wenn ich die Webseiteninformationen und die Verarbeitung von Informationen sehe, die über den Bildschirm gekrodelt wurden, bin ich immer der Meinung, dass dies eine sehr dunkle Technologie ist. Dieses Mal nutzte ich die Gelegenheit, die Frühlings -MVC zu sortieren, und wollte alleine einen kleinen Kriechen machen. Es spielt keine Rolle, ob ich leicht ein paar kleine Fehler bekommen kann. Alles was ich brauche ist eine Saatgut -Website, die die gewünschten Informationen kriechen kann. Wenn es eine Ausnahme gibt, kann dies daran liegen, dass einige APIs nicht ordnungsgemäß verwendet werden oder sie auf einen abnormalen HTTP -Anforderungsstatus stoßen oder ein Problem beim Lesen und Schreiben von Datenbanks vorliegt. Bei der Berichterstattung über Ausnahmen und Lösung von Ausnahmen kann Jewelcrawler (Son -Spitzname des Sohnes) bereits Daten unabhängig kriechen, und es gibt auch eine kleine Fähigkeit zur emotionalen Analyse basierend auf dem Word2VEC -Algorithmus.
Es kann unbekannte Ausnahmen geben, die darauf warten, später gelöst zu werden, und eine gewisse Leistung muss optimiert werden, z. B. die Interaktion mit der Datenbank, das Lesen und Schreiben von Daten usw. Ich habe jedoch nicht viel Energie, um dies im Jahr zu setzen, daher werde ich heute eine einfache Zusammenfassung geben. Die ersten beiden Artikel konzentrieren sich hauptsächlich auf Funktionen und Ergebnisse. In diesem Artikel wird darüber gesprochen, wie Jewelcrawler geboren wurde und den Code auf GitHub platziert (die Quellcodeadresse befindet sich am Ende des Artikels). Wenn Sie interessiert sind, können Sie aufpassen (nur für Kommunikation und Lernen, bitte Doppel. Bitte doppelte. Seien Sie aufrichtiger und weniger Schaden).
Umwelteinführung
Entwicklungsinstrumente: Intellij Idee 14
Datenbank: MySQL 5.5 + Datenbankverwaltungs -Tool Navicat (kann zur Verbindung zu Abfragedatenbanken verwendet werden)
Sprache: Java
JAR -Paketmanagement: Maven
Versionsverwaltung: Git
Verzeichnisstruktur
In
com.ansj.vec ist die Implementierung der Java -Version des Word2VEC -Algorithmus
com.jackie.crawler.doubanmovie ist ein Crawler -Implementierungsmodul, das auch enthält
Einige Pakete sind leer, weil diese Module noch nicht verwendet werden, darunter
Das Ressourcenmodul speichert Konfigurationsdateien und Ressourcendateien, wie z. B.
Das Testmodul ist ein Testmodul, das zum Schreiben von UT verwendet wird.
Datenbankkonfiguration
1. Abhängigkeitspakete hinzufügen
Jewelcrawler verwendet Maven Management, sodass Sie die entsprechenden Abhängigkeiten in pom.xml nur hinzufügen müssen.
<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> <gruppeId> commons-dbcp </GroupId> <artifactId> commons-dbcp </artifactId> <artifactId> commons-dbcp </artifactId> <artifactId> commons-dbcp </artifactId> <version> 1.4 </Version> </abhängig> </gruppe </gruppe> </gruppen> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version></dependency><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version></dependency>
2. Deklarieren Sie die Datenquellenbohne
Wir müssen die Bohnen der Datenquelle in Beans.xml deklarieren
<Kontext: Property-Placeholder-Standort = "ClassPath*:*. Properties"/> <bean id = "dataSource" Destroy-method = "Close"> <Property name = "DriverClassName" value = "$ {JDBC.DRIVER}"/> <Property name = "url" value = "$ {jdbc.url}}"/< value = "$ {jdbc.username}"/> <Eigenschaft name = "password" value = "$ {jdbc.password}"/>Hinweis: Hier ist die externe Konfigurationsdatei JDBC.Properties gebunden, und die Parameter der spezifischen Datenquelle werden aus dieser Datei gelesen.
Wenn Sie auf das Problem stoßen, "SQL [in Benutzer (ID) -Werte einfügen (?)]; Feld 'Name' hat keinen Standardwert;" Die Lösung besteht darin, das entsprechende Feld der Tabelle auf ein selbstwachsendes Feld zu setzen.
Probleme auftreten beim Parsen von Seiten
Für die von Ihnen gekrabbten Webseitendaten müssen Sie die DOM -Struktur analysieren und die gewünschten Daten abrufen. Während dieser Zeit begegnen Sie den folgenden Fehler
org.htmlparser.node ist nicht erkannt
Lösung: Fügen Sie die Abhängigkeit von JAR -Paket hinzu
<Depopenty> <gruppe> org.htmlParser </Groupid> <artifactId> htmlParser </artifactId> <version> 1.6 </Version> </abhängig>
org.apache.http.httpentity wird nicht erkannt
Lösung: Fügen Sie die Abhängigkeit von JAR -Paket hinzu
<Depopenty> <gruppe> org.apache.httpcomponents </Groupid> <artifactid> httpclient </artifactid> <version> 4.5.2 </Version> </abhängig>
Dies ist natürlich ein Problem, das im Zeitraum aufgetreten ist, und die von JSOUP durchgeführte Seitenanalyse wird schließlich verwendet.
Maven Warehouse Download -Geschwindigkeit ist langsam
Ich habe zuvor das Standard -Repository des Maven Central Repository verwendet, und die Geschwindigkeit des Herunterladens von JAR -Paketen war sehr langsam. Ich weiß nicht, ob es mein Netzwerkproblem oder andere Gründe war. Später fand ich das Maven -Repository von Alibaba Cloud online. Nach dem Update wurde empfohlen, im Vergleich zu zuvor Blut zu erbrechen.
<Mirrors> <Mirror> <ID> Alimaven </id> <name> Aliyun Maven </name> <URL> http://maven.aliyun.com/nexus/content/groups/public/ </url> <mirrorof> zentral </minorof> </minor> </minor> </minor> </minor> </minor> </minor> </minor> </minor> </minor> </minor> </minor> </mirror
Suchen Sie die Datei "Settings.xml" von Maven und fügen Sie dieses Bild hinzu.
Eine Möglichkeit, Dateien unter dem Ressourcenmodul zu lesen
Lesen Sie beispielsweise die Datei Seed.Properties -Datei
@Test public void testFile () {Datei SeedFile = neue Datei (this.getClass (). GetResource ("/Seed.Properties"). GetPath ()); System.out.print ("==========" + SeedFile.length () + "==========="); }Über reguläre Ausdrücke
Wenn Sie RegRex -reguläre Ausdrücke verwenden, müssen Sie die Fundmethode des Matchers aufrufen, bevor Sie die Gruppenmethode verwenden können, um das Substring zu finden. Es gibt keine Möglichkeit, das gewünschte Ergebnis zu finden, indem Sie die Gruppenmethode direkt aufrufen.
Ich habe mir den Quellcode der obigen Spielklasse angesehen
Paket java.util.regex; Import Java.util.Objects; Public Final Class Matcher implementiert MatchResult { /*** Das Musterobjekt, das diesen Match erstellt hat. */ Muster parentSpattern; /*** Der von Gruppen verwendete Speicher. Sie können ungültige Werte enthalten, wenn * während der Übereinstimmung eine Gruppe übersprungen wurde. */ int [] Gruppen; /*** Der Bereich innerhalb der Sequenz, die übereinstimmt. Anchors * stimmt an diesen "harten" Grenzen überein. Ändern der Region * ändert diese Werte. */ int von, bis; /** * LookBehind verwendet diesen Wert, um sicherzustellen, dass die Suberexpression * übereinstimmt, an dem Punkt, an dem das LookBehind angetroffen wurde. */ int LookBehindto; /*** Die ursprüngliche Zeichenfolge wird abgestimmt. */ Charsequence text; /*** Matcher -Status, der vom letzten Knoten verwendet wird. Der Noanchor wird verwendet, wenn eine * Übereinstimmung nicht alle Eingaben konsumieren muss. Endanchor ist der Modus, der zum Abgleich aller Eingaben verwendet wird. */ static Final int Endanchor = 1; statischer Final INT Noanchor = 0; int AcceptMode = Noanchor; /*** Der Zeichenfolgenbereich, der zuletzt zum Muster übereinstimmte. Wenn das letzte * Match fehlgeschlagen ist, ist zuerst -1; Zunächst hält anfangs 0, dann hält es * den Index des letzten Spiels (in dem die nächste Suche beginnt). */ int First = -1, last = 0; /*** Der Endindex dessen, was in der letzten Spieloperation übereinstimmt. */ int OldLast = -1; /*** Der Index der letzten Position in einer Substitution. */ int lastAppendPosition = 0; /** * Speicher verwendet von Knoten, um zu sagen, auf welcher Wiederholung sie sich in * einem Muster befinden und wo Gruppen beginnen. Die Knoten selbst sind Staatenlos *, so dass sie sich auf dieses Feld verlassen, um während eines Spiels den Status zu halten. */ int [] Einheimische; /** * boolean angibt, ob mehr Eingaben die Ergebnisse der letzten Übereinstimmung ändern können oder nicht. * * Wenn Hitend wahr ist und ein Match gefunden wurde, kann mehr Eingabe * zu einer anderen Übereinstimmung kommen. * Wenn Hitend wahr ist und ein Match nicht gefunden wurde, kann mehr * Eingaben zu einem Match zu finden. * Wenn Hitend falsch ist und ein Match nicht gefunden wurde, wird ein Übereinstimmung nicht mehr eingebracht. */ boolean Hitend; /** * boolean angibt, ob sich mehr Eingaben ändern können * eine positive Übereinstimmung in eine negative. * * Wenn die Anforderung wahr ist und ein Match gefunden wurde, kann mehr * Eingaben dazu führen, dass das Match verloren geht. * Wenn die Anforderung falsch ist und ein Match gefunden wurde, kann mehr * Eingaben das Spiel ändern, aber das Spiel wird nicht verloren gehen. * Wenn keine Übereinstimmung gefunden wurde, hat die Anforderung keine Bedeutung. */ boolean fordern; /** * Wenn transparentgebunden wahr ist, sind die Grenzen der Region dieses * Matcher -Region für die Konstrukte von Aussichtsputz-, LookBehind- und Grenzübereinstimmungskonstrukten transparent, die versuchen, über sie hinaus zu sehen. */ boolean transparentBounds = false; /** * Wenn Verankerungsbounds wahr sind, stimmen die Grenzen der Region dieses Matchers an Verankerungen wie ^ und $. */ boolean verankerungsgebunden = true; /*** Kein Standardkonstruktor. * / Matcher () {} / *** Alle Matcher haben den Status, den Muster während einer Übereinstimmung verwendet. */Matcher (Muster übergeordnet, charsequence text) {this.ParentPattern = Eltern; this.text = text; // Statusspeicher int parentGroupCount = math.max (parent.capturingGroupCount, 10); gruppen = new int [parentgroupCount * 2]; locals = new int [parent.localCount]; // Felder in die ersten Zustände reset ();} ..../*** Gibt die Eingangsuntersuchung zurück, die durch das vorherige Spiel übereinstimmt. * * <p> für einen Matcher <i> m </i> mit Eingabesequenz <i> s </i>, * Die Ausdrücke <i> m. </i> <tt> Group () </tt> und * <i> s. <i> m. </i> <tt> end ()) </tt> * sind äquivalent. </p> * * <p> Beachten Sie, dass einige Muster, z. B. <tt> a * </tt>, mit der leeren * Zeichenfolge übereinstimmen. Diese Methode gibt die leere Zeichenfolge zurück, wenn das Muster * erfolgreich mit der leeren Zeichenfolge in der Eingabe übereinstimmt. </p> * * @return die (möglicherweise leere) Sequenz, die durch das vorherige Spiel übereinstimmt, * in String -Form * * @throws illegalStateException * Wenn noch kein Übereinstimmung versucht wurde, * oder wenn die vorherige Übereinstimmung fehlgeschlagen ist * * <p> Für einen Matcher <i> m <i> s. </i> <tt> substring (</tt> <i> m. </p> * * <p> <a href = "muster.html#cg"> Gruppen erfassen </a> werden von links bis rechts angezeigt, beginnend bei einem. Gruppe Null bezeichnet das gesamte Muster, also * Der Ausdruck <Tt> M.group (0) </tt> entspricht <tt> m.group () </tt>. * </p> * * <p> Wenn die Übereinstimmung erfolgreich war, die angegebene Gruppe jedoch nicht übereinstimmt. Beachten Sie *, dass einige Gruppen, beispielsweise <tt> (a *) </tt>, mit der leeren Zeichenfolge übereinstimmen. * Diese Methode gibt die leere Zeichenfolge zurück, wenn eine solche Gruppe erfolgreich mit der leeren Zeichenfolge in der Eingabe übereinstimmt. </p> * @param Group * Der Index einer erfassenden Gruppe in diesem Match -Muster * * @return die (möglicherweise leere) nach der Gruppe erfasst von der Gruppe * während des vorherigen Spiels oder <Tt> null </tt> Wenn die Gruppe * nicht übereinstimmte, dass der Teil des Eingangs der Vorgänge der vorherige Übereinstimmung mit dem vorherigen Spiel * @throws illegalStateException * @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @| Keine Erfassungsgruppe im Muster * mit dem angegebenen Index */öffentliche String -Gruppe (int -Gruppe) {if (zuerst <0) neue illegaleStateException ("no Match gefunden"); if (Gruppe <0 || Group> GroupCount ()). if ((Gruppen [Gruppen*2] == -1) || (Gruppen [Gruppen*2+1] == -1)) return null; return getSubsequence (Gruppen [Gruppen * 2], Gruppen [Gruppe * 2 + 1]). toString ();}/** * Versucht, die nächste Sequenz der Eingabebereich zu finden, die dem Muster entspricht. * * <p> Diese Methode beginnt am Anfang der Region dieses Spielers oder, wenn * ein früherer Aufruf der Methode erfolgreich war und der Match * seitdem nicht zurückgesetzt wurde, beim ersten Charakter, der nicht durch das vorherige * Match übereinstimmt. * * <p> Wenn die Übereinstimmung erfolgreich ist, können weitere Informationen über die Methoden von * <Tt> Start </tt>, <Tt> End </tt> und <Tt> -Gruppe erhalten werden. </p> * * @return <tt> true </tt> if und nur wenn eine Sequenz der Eingabe * -Sequenz mit dem Muster dieses Matchers übereinstimmt */public boolean find () {int NextSearchIndex = last; if (NextSearchIndex == zuerst) NextSearchIndex ++; // Wenn die nächste Suche vor der Region beginnt, starten Sie es in der Region, wenn (NextSearchIndex <von) NextSearchIndex = von; // Wenn die nächste Suche über die Region hinaus beginnt, fällt es fehl, wenn (NextSearchIndex> to) {für (int i = 0; i <Groups.length; i ++) Gruppen [i] = -1; false zurückgeben; } Rückgabesuche (NextSearchIndex);} /*** initiiert eine Suche, um ein Muster innerhalb der angegebenen Grenzen zu finden. * Die Gruppen sind mit Standardwerten gefüllt und die Übereinstimmung der Stamme * der Zustandsmaschine wird aufgerufen. Die Staatsmaschine wird den Status * des Spiels halten, wenn es in diesem Match fortgesetzt wird. * * Matcher.from ist hier nicht festgelegt, da es sich um die "harte" Grenze * des Beginns der Suche handelt, auf die die Anker festgelegt werden. Der aus Param * ist die "weiche" Grenze des Beginns der Suche, was bedeutet, dass der * Regex versucht, an diesem Index übereinzustimmen, aber dort nicht übereinstimmt. Nachfolgende * Aufrufe der Suchmethoden beginnen an einer neuen "weichen" Grenze, die das Ende der vorherigen Übereinstimmung ist. */boolesche Suche (int von) {this.hitend = false; this.requireend = false; von = von <0? 0: von; this.First = from; this.oldLast = alteLast <0? Von: OldLast; für (int i = 0; i <Groups.length; i ++) Gruppen [i] = -1; AcceptMode = Noanchor; boolean result = parentSpattern.root.match (this, von, text); if (! Ergebnis) this.First = -1; this.oldLast = this.last; Rückgabeergebnis;} ...}Der Grund dafür ist: Wenn Sie die Find -Methode nicht zuerst aufrufen und die Gruppe direkt anrufen, können Sie feststellen, dass die Gruppenmethode Gruppengruppe (int Group) aufruft. Es gibt, wenn zuerst <0 im Methodekörper der Methode. Offensichtlich ist diese Bedingung hier wahr, da der Anfangswert von zuerst -1 ist, daher wird eine Ausnahme hierher geworfen. Wenn Sie jedoch die Find -Methode aufrufen, können Sie diese Suche (NextSearchIndex) ermitteln, letztendlich aufgerufen wird. Beachten Sie, dass der NextSearchIndex hier vom letzten und der Wert von Last 0 zugewiesen wurde, und springen Sie dann zur Suchmethode
boolesche Suche (int von) {this.hitend = false; this.requireend = false; von = von <0? 0: von; this.First = from; this.oldLast = alteLast <0? Von: OldLast; für (int i = 0; i <Groups.length; i ++) Gruppen [i] = -1; AcceptMode = Noanchor; boolean result = parentSpattern.root.match (this, von, text); if (! Ergebnis) this.First = -1; this.oldLast = this.last; Rückgabeergebnis;} Dieser NextSearchIndex wird an aus übergeben und von der Ersten in der Method -Karosserie zugeordnet. Nach dem Aufrufen der Find -Methode ist der erste davon nicht mehr -1, und es macht keine Ausnahme.
Der Quellcode wurde auf Baidu NetDisk hochgeladen: http://pan.baidu.com/s/1dfwtvnz
Die oben genannten Probleme sind relativ erschüttert und sind eine Zusammenfassung, wenn sie Probleme stoßen und diese lösen. Es wird andere Probleme während der bestimmten Operationen geben. Wenn Sie Fragen oder Vorschläge haben, zeichnen Sie sich bitte gerne an ^^.
Setzen Sie schließlich bisher ein paar krabble Daten ein
Aufzeichnungstabelle
Unter ihnen werden 79.032 gelagert und 48.471 gekrabbte Webseiten sind
Filmtisch
Derzeit wurden 2964 Film- und Fernsehwerke gekrabbelt
Kommentare Tabelle
29.711 Aufzeichnungen wurden gekrabbelt
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.