Au début, nous avons exploré le titre sous ce lien :
http://www.zhihu.com/explore/recommendations
Mais évidemment, cette page ne peut pas fournir la réponse.
Une page de questions complète ressemblerait à ceci :
http://www.zhihu.com/question/22355264
En y regardant de plus près, aha, notre classe d'encapsulation doit être davantage emballée. Au moins une questionDescription est nécessaire pour stocker la description de la question :
importer java.util.ArrayList ;
classe publique Zhihu {
question de chaîne publique ; // question
public String questionDescription ; // Description de la question
chaîne publique zhihuUrl ; // Lien vers une page Web
public ArrayList<String> réponses ; // Tableau pour stocker toutes les réponses
// Le constructeur initialise les données
public Zhihu() {
question = "" ;
questionDescription = "";
zhihuUrl = "";
réponses = new ArrayList<String>();
}
@Outrepasser
chaîne publique versChaîne() {
renvoie "Question :" + question + "/n" + "Description :" + questionDescription + "/n"
+ "Lien :" + zhihuUrl + "/nanswer :" + réponses + "/n" ;
}
}
Nous ajoutons un paramètre au constructeur de Zhihu pour définir la valeur de l'URL. Étant donné que l'URL est déterminée, la description et la réponse à la question peuvent être capturées.
Modifions la méthode de Spider pour obtenir les objets Zhihu et obtenons uniquement l'URL :
static ArrayList<Zhihu> GetZhihu(Contenu de la chaîne) {
// Prédéfinir une ArrayList pour stocker les résultats
ArrayList<Zhihu> résultats = new ArrayList<Zhihu>();
// Utilisé pour correspondre à l'url, qui est le lien vers la question
Modèle urlPattern = Pattern.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Matcher urlMatcher = urlPattern.matcher(content);
// S'il existe un objet correspondant avec succès
booléen isFind = urlMatcher.find();
tandis que (estFind) {
//Définissez un objet Zhihu pour stocker les informations capturées
Zhihu zhihuTemp = nouveau Zhihu(urlMatcher.group(1));
//Ajouter des résultats de correspondance réussis
results.add(zhihuTemp);
// Continuer à trouver le prochain objet correspondant
isFind = urlMatcher.find();
}
renvoyer les résultats ;
}
Ensuite, dans la méthode de construction de Zhihu, obtenez toutes les données détaillées via l'URL.
Nous devons d’abord traiter l’url, car pour certaines réponses, son url est :
http://www.zhihu.com/question/22355264/answer/21102139
Certains sont spécifiques au problème, et son URL est :
http://www.zhihu.com/question/22355264
Ensuite, ce dont nous avons évidemment besoin, c'est du deuxième type, nous devons donc utiliser des règles régulières pour couper le premier type de lien en deuxième type. Cela peut être fait en écrivant une fonction dans Zhihu.
// gérer l'URL
booléen getRealUrl (URL de chaîne) {
// Modification http://www.zhihu.com/question/22355264/answer/21102139
//Convertir en http://www.zhihu.com/question/22355264
// Sinon, aucun changement
Modèle modèle = Pattern.compile("question/(.*?)/");
Matcher matcher = motif.matcher(url);
si (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} autre {
renvoie faux ;
}
renvoie vrai ;
}
L'étape suivante consiste à obtenir les différentes pièces.
Voyons d'abord le titre :
Saisissez simplement cette classe sous sa forme régulière. L'instruction régulière peut être écrite comme suit : zm-editable-content/">(.+?)<
Exécutez-le pour voir les résultats :
Aïe, pas mal.
Ensuite, récupérez la description du problème :
Aha, c'est le même principe, récupérez la classe, car elle devrait en être l'identifiant unique.
Méthode de vérification : cliquez avec le bouton droit pour afficher le code source de la page, ctrl+F pour voir s'il y a d'autres chaînes dans la page.
Plus tard, après vérification, quelque chose s'est vraiment mal passé :
La classe devant le titre et le contenu de la description est la même.
Cela ne peut être récupéré qu'en modifiant le modèle régulier :
// correspond au titre
pattern = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = motif.matcher(contenu);
si (matcher.find()) {
question = matcher.group(1);
}
// Description de la correspondance
motif=Motif
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = motif.matcher(contenu);
si (matcher.find()) {
questionDescription = matcher.group(1);
}
La dernière chose est de faire une boucle pour saisir la réponse :
Déclaration régulière provisoire préliminaire : /answer/content.+?<div.+?>(.*?)</div>
Après avoir modifié le code, nous constaterons que le logiciel fonctionne beaucoup plus lentement car il doit visiter chaque page Web et en capturer le contenu.
Par exemple, s'il y a 20 questions recommandées par l'éditeur, vous devrez alors visiter la page Web 20 fois et la vitesse ralentira.
Essayez-le, ça a l'air bien :
OK, laissons ça comme ça pour l'instant ~ La prochaine fois, nous continuerons à faire quelques ajustements détaillés, comme le multi-threading, l'écriture locale des flux IO, etc.
Ci-joint le code source du projet :
Zhihu.java
importer java.util.ArrayList ;
importer java.util.regex.Matcher ;
importer java.util.regex.Pattern ;
classe publique Zhihu {
question de chaîne publique ; // question
public String questionDescription ; // Description de la question
chaîne publique zhihuUrl ; // Lien vers une page Web
public ArrayList<String> réponses ; // Tableau pour stocker toutes les réponses
// Le constructeur initialise les données
public Zhihu (URL de la chaîne) {
//Initialiser les propriétés
question = "" ;
questionDescription = "";
zhihuUrl = "";
réponses = new ArrayList<String>();
// Détermine si l'URL est légale
si (getRealUrl(url)) {
System.out.println("ramper" + zhihuUrl);
// Récupère les détails de la question et de la réponse en fonction de l'URL
Contenu de la chaîne = Spider.SendGet(zhihuUrl);
Modèle de motif ;
Matcheur ;
// correspond au titre
pattern = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = motif.matcher(contenu);
si (matcher.find()) {
question = matcher.group(1);
}
// Description de la correspondance
motif=Motif
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = motif.matcher(contenu);
si (matcher.find()) {
questionDescription = matcher.group(1);
}
// Correspond à la réponse
pattern = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
matcher = motif.matcher(contenu);
booléen isFind = matcher.find();
tandis que (estFind) {
réponses.add(matcher.group(1));
isFind = matcher.find();
}
}
}
// Récupérez vos propres questions, descriptions et réponses en fonction de votre propre URL
public booléen getAll() {
renvoie vrai ;
}
// gérer l'URL
booléen getRealUrl (URL de chaîne) {
// Modification http://www.zhihu.com/question/22355264/answer/21102139
//Convertir en http://www.zhihu.com/question/22355264
// Sinon, aucun changement
Modèle modèle = Pattern.compile("question/(.*?)/");
Matcher matcher = motif.matcher(url);
si (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} autre {
renvoie faux ;
}
renvoie vrai ;
}
@Outrepasser
chaîne publique versChaîne() {
renvoie "Question :" + question + "/n" + "Description :" + questionDescription + "/n"
+ "Lien :" + zhihuUrl + "/nAnswer :" + réponses.size() + "/n" ;
}
}
Araignée.java
importer java.io.BufferedReader ;
importer java.io.InputStreamReader ;
importer java.net.URL ;
importer java.net.URLConnection ;
importer java.util.ArrayList ;
importer java.util.regex.Matcher ;
importer java.util.regex.Pattern ;
classe publique Araignée {
Chaîne statique SendGet (URL de chaîne) {
//Définit une chaîne pour stocker le contenu d'une page Web
Résultat de la chaîne = "" ;
//Définit un flux d'entrée de caractères mis en mémoire tampon
BufferedReader dans = null ;
essayer {
//Convertir la chaîne en objet URL
URL realUrl = nouvelle URL(url);
// Initialise un lien vers cette URL
Connexion URLConnection = realUrl.openConnection();
// Démarre la connexion réelle
connexion.connect();
//Initialisez le flux d'entrée BufferedReader pour lire la réponse de l'URL
in = nouveau BufferedReader (nouveau InputStreamReader (
connexion.getInputStream(), "UTF-8"));
// Utilisé pour stocker temporairement les données de chaque ligne capturée
Ligne de ficelle ;
while ((line = in.readLine()) != null) {
// Parcourez chaque ligne capturée et stockez-la dans le résultat
résultat += ligne ;
}
} attraper (Exception e) {
System.out.println("Une exception s'est produite lors de l'envoi de la requête GET!" + e);
e.printStackTrace();
}
// Utiliser enfin pour fermer le flux d'entrée
enfin {
essayer {
si (dans != null) {
joindre();
}
} attraper (Exception e2) {
e2.printStackTrace();
}
}
renvoyer le résultat ;
}
// Obtenez tout le contenu Zhihu recommandé par les éditeurs
static ArrayList<Zhihu> GetRecommendations (Contenu de la chaîne) {
// Prédéfinir une ArrayList pour stocker les résultats
ArrayList<Zhihu> résultats = new ArrayList<Zhihu>();
// Utilisé pour correspondre à l'url, qui est le lien vers la question
Modèle de motif = Modèle
.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Matcher matcher = pattern.matcher(content);
// S'il existe un objet correspondant avec succès
Booléen isFind = matcher.find();
tandis que (estFind) {
//Définissez un objet Zhihu pour stocker les informations capturées
Zhihu zhihuTemp = nouveau Zhihu(matcher.group(1));
//Ajouter des résultats de correspondance réussis
results.add(zhihuTemp);
// Continuer à trouver le prochain objet correspondant
isFind = matcher.find();
}
renvoyer les résultats ;
}
}
Main.java
importer java.util.ArrayList ;
classe publique Principale {
public static void main (String[] arguments) {
// Définir le lien à visiter
URL de chaîne = "http://www.zhihu.com/explore/recommendations" ;
//Accédez au lien et récupérez le contenu de la page
Contenu de la chaîne = Spider.SendGet(url);
// Obtenez les recommandations de l'éditeur
ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(content);
// imprimer les résultats
System.out.println(myZhihu);
}
}
Ce qui précède est le dossier complet de la saisie des réponses de Zhihu. Il est très détaillé. Les amis dans le besoin peuvent s'y référer.