En la etapa inicial, rastreamos el título en este enlace:
http://www.zhihu.com/explore/recommendations
Pero obviamente esta página no puede obtener la respuesta.
Una página de preguntas completa se vería así:
http://www.zhihu.com/question/22355264
Mirando más de cerca, ajá, nuestra clase de encapsulación necesita empaquetarse más. Se necesita al menos una descripción de pregunta para almacenar la descripción de la pregunta:
importar java.util.ArrayList;
clase pública Zhihu {
pregunta de cadena pública // pregunta
public String questionDescription // Descripción de la pregunta
cadena pública zhihuUrl;//Enlace a página web
public ArrayList<String> respuestas; // Matriz para almacenar todas las respuestas
// El constructor inicializa los datos.
público Zhihu() {
pregunta = "";
descripción de la pregunta = "";
zhihuUrl = "";
respuestas = nueva ArrayList<String>();
}
@Anular
cadena pública toString() {
devolver "Pregunta:" + pregunta + "/n" + "Descripción:" + preguntaDescripción + "/n"
+ "Enlace:" + zhihuUrl + "/nanswer:" + respuestas + "/n";
}
}
Agregamos un parámetro al constructor de Zhihu para establecer el valor de la URL. Debido a que se determina la URL, se pueden capturar la descripción y la respuesta a la pregunta.
Cambiemos el método de Spider para obtener objetos Zhihu y obtengamos solo la URL:
estática ArrayList<Zhihu> GetZhihu(Contenido de cadena) {
// Predefinir un ArrayList para almacenar los resultados
ArrayList<Zhihu> resultados = nuevo ArrayList<Zhihu>();
// Se utiliza para hacer coincidir la URL, que es el enlace a la pregunta.
Patrón urlPattern = Pattern.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Matcher urlMatcher = urlPattern.matcher(contenido);
// Si hay un objeto coincidente exitoso
booleano isFind = urlMatcher.find();
mientras (isFind) {
//Definimos un objeto Zhihu para almacenar la información capturada
Zhihu zhihuTemp = nuevo Zhihu(urlMatcher.group(1));
//Agregar resultados coincidentes exitosos
resultados.add(zhihuTemp);
// Continuar buscando el siguiente objeto coincidente
isFind = urlMatcher.find();
}
devolver resultados;
}
A continuación, en el método de construcción de Zhihu, obtenga todos los datos detallados a través de la URL.
Primero necesitamos procesar la URL, porque para algunas respuestas, su URL es:
http://www.zhihu.com/question/22355264/answer/21102139
Algunos son específicos del problema y su URL es:
http://www.zhihu.com/question/22355264
Entonces, lo que obviamente necesitamos es el segundo tipo, por lo que debemos usar reglas regulares para cortar el primer tipo de enlace en el segundo tipo. Esto se puede hacer escribiendo una función en Zhihu.
// manejar la URL
booleano getRealUrl (URL de cadena) {
// Cambiar http://www.zhihu.com/question/22355264/answer/21102139
//Convertir a http://www.zhihu.com/question/22355264
// De lo contrario, no hay cambios
Patrón patrón = Pattern.compile("pregunta/(.*?)/");
Comparador de coincidencias = patrón.matcher(url);
si (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} demás {
devolver falso;
}
devolver verdadero;
}
El siguiente paso es obtener las distintas piezas.
Primero echemos un vistazo al título:
Simplemente comprenda esa clase en forma regular. La declaración regular se puede escribir como: zm-editable-content/">(.+?)<.
Ejecútelo para ver los resultados:
Ay, no está mal.
Luego tome la descripción del problema:
Ajá, el mismo principio, toma la clase, porque debería ser el identificador único de esto.
Método de verificación: haga clic derecho para ver el código fuente de la página, Ctrl+F para ver si hay otras cadenas en la página.
Más tarde, después de la verificación, algo realmente salió mal:
La clase delante del título y el contenido de la descripción es la misma.
Eso sólo se puede volver a capturar modificando el patrón regular:
// título del partido
patrón = Patrón.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
comparador = patrón.matcher(contenido);
si (matcher.find()) {
pregunta = matcher.group(1);
}
// Descripción del partido
patrón = patrón
.compile("zh-pregunta-detalle.+?<div.+?>(.*?)</div>");
comparador = patrón.matcher(contenido);
si (matcher.find()) {
descripción de la pregunta = matcher.group(1);
}
Lo último es hacer un bucle para obtener la respuesta:
Declaración regular tentativa preliminar: /answer/content.+?<div.+?>(.*?)</div>
Después de cambiar el código, encontraremos que el software se ejecuta significativamente más lento porque necesita visitar cada página web y capturar el contenido de ella.
Por ejemplo, si hay 20 preguntas recomendadas por el editor, entonces deberá visitar la página web 20 veces y la velocidad disminuirá.
Pruébalo, tiene buena pinta:
Bien, dejémoslo así por ahora ~ La próxima vez continuaremos haciendo algunos ajustes detallados, como subprocesos múltiples, escritura de flujos IO localmente, etc.
Adjunto el código fuente del proyecto:
zhihu.java
importar java.util.ArrayList;
importar java.util.regex.Matcher;
importar java.util.regex.Pattern;
clase pública Zhihu {
pregunta de cadena pública // pregunta
public String questionDescription // Descripción de la pregunta
cadena pública zhihuUrl;//Enlace a página web
public ArrayList<String> respuestas; // Matriz para almacenar todas las respuestas
// El constructor inicializa los datos.
público Zhihu (URL de cadena) {
//Inicializar propiedades
pregunta = "";
descripción de la pregunta = "";
zhihuUrl = "";
respuestas = nueva ArrayList<String>();
// Determinar si la URL es legal
si (getRealUrl(url)) {
System.out.println("rastreando" + zhihuUrl);
// Obtenga los detalles de la pregunta y la respuesta según la URL
Contenido de cadena = Spider.SendGet(zhihuUrl);
Patrón de patrón;
Emparejador emparejador;
// título del partido
patrón = Patrón.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
comparador = patrón.matcher(contenido);
si (matcher.find()) {
pregunta = matcher.group(1);
}
// Descripción del partido
patrón = patrón
.compile("zh-pregunta-detalle.+?<div.+?>(.*?)</div>");
comparador = patrón.matcher(contenido);
si (matcher.find()) {
descripción de la pregunta = matcher.group(1);
}
// Coincidencia de respuesta
patrón = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
comparador = patrón.matcher(contenido);
booleano isFind = matcher.find();
mientras (isFind) {
respuestas.add(matcher.group(1));
isFind = matcher.find();
}
}
}
// Obtenga sus propias preguntas, descripciones y respuestas basadas en su propia URL
público booleano getAll() {
devolver verdadero;
}
// manejar la URL
booleano getRealUrl (URL de cadena) {
// Cambiar http://www.zhihu.com/question/22355264/answer/21102139
//Convertir a http://www.zhihu.com/question/22355264
// De lo contrario, no hay cambios
Patrón patrón = Pattern.compile("pregunta/(.*?)/");
Comparador de coincidencias = patrón.matcher(url);
si (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} demás {
devolver falso;
}
devolver verdadero;
}
@Anular
cadena pública toString() {
devolver "Pregunta:" + pregunta + "/n" + "Descripción:" + preguntaDescripción + "/n"
+ "Enlace:" + zhihuUrl + "/nRespuesta:" + respuestas.tamaño() + "/n";
}
}
araña.java
importar java.io.BufferedReader;
importar java.io.InputStreamReader;
importar java.net.URL;
importar java.net.URLConnection;
importar java.util.ArrayList;
importar java.util.regex.Matcher;
importar java.util.regex.Pattern;
Araña de clase pública {
Cadena estática SendGet (URL de cadena) {
//Definir una cadena para almacenar el contenido de la página web
Resultado de cadena = "";
//Definir un flujo de entrada de caracteres almacenado en buffer
BufferedReader en = nulo;
intentar {
//Convierte cadena en objeto URL
URL realUrl = nueva URL(url);
// Inicializa un enlace a esa URL
Conexión URLConnection = realUrl.openConnection();
// Iniciar la conexión real
conexión.connect();
//Inicializa el flujo de entrada BufferedReader para leer la respuesta de la URL
en = nuevo BufferedReader (nuevo InputStreamReader (
conexión.getInputStream(), "UTF-8"));
// Se utiliza para almacenar temporalmente los datos de cada fila capturada
Línea de cuerda;
mientras ((línea = in.readLine()) != nulo) {
// recorre cada fila capturada y la almacena como resultado
resultado += línea;
}
} captura (Excepción e) {
System.out.println("¡Se produjo una excepción al enviar la solicitud GET!" + e);
e.printStackTrace();
}
// Usar finalmente para cerrar el flujo de entrada
finalmente {
intentar {
si (en! = nulo) {
cercar();
}
} captura (Excepción e2) {
e2.printStackTrace();
}
}
resultado de devolución;
}
// Obtén todo el contenido de Zhihu recomendado por los editores
static ArrayList<Zhihu> GetRecommendations(Contenido de cadena) {
// Predefinir un ArrayList para almacenar los resultados
ArrayList<Zhihu> resultados = nuevo ArrayList<Zhihu>();
// Se utiliza para hacer coincidir la URL, que es el enlace a la pregunta.
Patrón patrón = Patrón
.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Comparador de coincidencias = patrón.matcher(contenido);
// Si hay un objeto coincidente exitoso
Booleano isFind = matcher.find();
mientras (isFind) {
//Definimos un objeto Zhihu para almacenar la información capturada
Zhihu zhihuTemp = nuevo Zhihu(matcher.group(1));
//Agregar resultados coincidentes exitosos
resultados.add(zhihuTemp);
// Continuar buscando el siguiente objeto coincidente
isFind = matcher.find();
}
devolver resultados;
}
}
principal.java
importar java.util.ArrayList;
clase pública principal {
público estático vacío principal (String [] argumentos) {
//Definir el enlace a visitar
URL de cadena = "http://www.zhihu.com/explore/recommendations";
//Accede al enlace y obtén el contenido de la página.
Contenido de cadena = Spider.SendGet(url);
// Obtener recomendaciones del editor
ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(contenido);
// imprimir resultados
System.out.println(myZhihu);
}
}
Lo anterior es el registro completo de cómo obtener las respuestas de Zhihu. Los amigos que lo necesiten pueden consultarlo.