Zhihu es una verdadera comunidad de preguntas y respuestas en línea con una atmósfera comunitaria amigable, racional y seria que conecta a élites de todos los ámbitos de la vida. Comparten el conocimiento profesional, la experiencia y las ideas de cada uno y proporcionan continuamente información de alta calidad para la Internet china.
Primero, dedica de tres a cinco minutos a diseñar un Logo =. = ¡Como programador, siempre he tenido un corazón para ser artista!
Vale, es un poco improvisado, así que me conformaré con ello por ahora.
A continuación, comenzamos a hacer el rastreador de Zhihu.
Primero, determine el primer objetivo: la recomendación del editor.
Enlace web: http://www.zhihu.com/explore/recommendations
Modificamos ligeramente el último código para lograr primero la capacidad de obtener el contenido de la página:
importar java.io.*;
importar java.net.*;
importar java.util.regex.*;
clase pública principal {
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()));
// 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;
}
cadena estática RegexString (cadena targetStr, cadena patrónStr) {
//Definimos una plantilla de estilo, usando expresiones regulares, y el contenido a capturar está entre paréntesis
// Equivale a enterrar una trampa y caerá si coincide.
Patrón patrón = Pattern.compile(patternStr);
//Definir un comparador para hacer coincidir
Comparador de coincidencias = patrón.matcher(targetStr);
// si se encuentra
si (matcher.find()) {
//imprime el resultado
devolver matcher.group(1);
}
devolver "Nada";
}
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.
Resultado de cadena = SendGet(url);
// Usa expresiones regulares para hacer coincidir el contenido src de la imagen
//String imgSrc = RegexString(resultado, "src=/"(.+?)/"");
// imprimir resultados
System.out.println(resultado);
}
}
No hay ningún problema después de ejecutarlo. El siguiente paso es un problema de coincidencia regular.
Primero, respondamos todas las preguntas en esta página.
Haga clic derecho en el título e inspeccione el elemento:
Ajá, puedes ver que el título es en realidad una etiqueta a, que es un hipervínculo, y lo que se puede distinguir de otros hipervínculos debería ser la clase, que es el selector de clases.
Entonces sale nuestra declaración habitual: question_link.+?href=/"(.+?)/"
Llame a la función RegexString y pásele parámetros:
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.
Resultado de cadena = SendGet(url);
// Usa expresiones regulares para hacer coincidir el contenido src de la imagen
String imgSrc = RegexString(resultado, "question_link.+?>(.+?)<");
// imprimir resultados
System.out.println(imgSrc);
}
Ah, ja, puedes ver que capturamos con éxito un título (nota, solo uno):
Espera un momento, ¿qué es todo este lío? !
No te pongas nervioso =. =Son sólo caracteres confusos.
Para problemas de codificación, consulte: Conjunto de caracteres HTML
En términos generales, las codificaciones principales con mejor compatibilidad con el chino son las codificaciones UTF-8, GB2312 y GBK.
La página web puede configurar la codificación de la página web a través del juego de caracteres de la metaetiqueta, por ejemplo:
<meta juego de caracteres="utf-8" />
Hagamos clic derecho para ver el código fuente de la página:
Como puede ver, Zhihu usa codificación UTF-8.
Aquí te explicaré la diferencia entre ver el código fuente de la página e inspeccionar elementos.
Ver el código fuente de la página muestra todo el código de toda la página. No está formateado según las etiquetas HTML. Es equivalente a ver el código fuente directamente. Este método es más útil para ver la información de toda la página web. meta.
Inspeccionar elemento, o algunos navegadores lo llaman ver elemento, que consiste en ver el elemento en el que hace clic con el botón derecho, como un div o img. Es más adecuado para ver los atributos y etiquetas de un objeto individualmente.
Bien, ahora sabemos que el problema radica en la codificación, el siguiente paso es convertir la codificación del contenido capturado.
La implementación en java es muy simple, simplemente especifica el método de codificación en InputStreamReader:
//Inicializa el flujo de entrada BufferedReader para leer la respuesta de la URL
en = nuevo BufferedReader (nuevo InputStreamReader (
conexión.getInputStream(),"UTF-8"));
Si ejecuta el programa nuevamente en este momento, encontrará que el título se puede mostrar normalmente:
¡DE ACUERDO! ¡muy bien!
Pero ahora sólo hay un título, necesitamos todos los títulos.
Modificamos ligeramente la expresión regular y almacenamos los resultados buscados en un ArrayList:
importar java.io.*;
importar java.net.*;
importar java.util.ArrayList;
importar java.util.regex.*;
clase pública principal {
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;
}
static ArrayList<String> RegexString(String targetStr, String patrónStr) {
// Predefinir un ArrayList para almacenar los resultados
ArrayList<String> resultados = nuevo ArrayList<String>();
//Definimos una plantilla de estilo, usando expresiones regulares, y el contenido a capturar está entre paréntesis
Patrón patrón = Pattern.compile(patternStr);
//Definir un comparador para hacer coincidir
Comparador de coincidencias = patrón.matcher(targetStr);
// si se encuentra
booleano isFind = matcher.find();
// Usa un bucle para buscar y reemplazar todos los kelvin en la oración y agregar el contenido a sb
mientras (isFind) {
//Agregar resultados coincidentes exitosos
resultados.add(matcher.group(1));
// Continuar buscando el siguiente objeto coincidente
isFind = matcher.find();
}
devolver resultados;
}
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.
Resultado de cadena = SendGet(url);
// Usa expresiones regulares para hacer coincidir el contenido src de la imagen
ArrayList<String> imgSrc = RegexString(resultado, "question_link.+?>(.+?)<");
// imprimir resultados
System.out.println(imgSrc);
}
}
Esto coincidirá con todos los resultados (debido a que ArrayList se imprime directamente, habrá algunos corchetes y comas):
Bien, este es el primer paso del rastreador Zhihu.
Pero podemos ver que no hay manera de capturar todas las preguntas y respuestas de esta manera.
Necesitamos diseñar una clase de encapsulación Zhihu para almacenar todos los objetos capturados.
Código fuente de Zhihu.java:
importar java.util.ArrayList;
clase pública Zhihu {
pregunta de cadena pública // 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 = "";
zhihuUrl = "";
respuestas = nueva ArrayList<String>();
}
@Anular
cadena pública toString() {
return "Pregunta:" + pregunta + "/nEnlace:" + zhihuUrl + "/nRespuesta:" + respuestas + "/n";
}
}
Cree una nueva clase Spider para almacenar algunas funciones de rastreadores de uso común.
Código fuente de Spider.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;
}
estática ArrayList<Zhihu> GetZhihu(Contenido de cadena) {
// Predefinir un ArrayList para almacenar los resultados
ArrayList<Zhihu> resultados = nuevo ArrayList<Zhihu>();
// Se utiliza para unir títulos
Patrón preguntaPatrón = Pattern.compile("question_link.+?>(.+?)<");
Matcher questionMatcher = questionPattern.matcher(contenido);
// Se utiliza para hacer coincidir la URL, que es el enlace a la pregunta.
Patrón urlPattern = Pattern.compile("question_link.+?href=/"(.+?)/"");
Matcher urlMatcher = urlPattern.matcher(contenido);
//Tanto la pregunta como el enlace deben coincidir
booleano isFind = questionMatcher.find() && urlMatcher.find();
mientras (isFind) {
//Definimos un objeto Zhihu para almacenar la información capturada
Zhihu zhuhuTemp = nuevo Zhihu();
zhuhuTemp.question = questionMatcher.group(1);
zhuhuTemp.zhihuUrl = "http://www.zhihu.com" + urlMatcher.group(1);
//Agregar resultados coincidentes exitosos
resultados.add(zhuhuTemp);
// Continuar buscando el siguiente objeto coincidente
isFind = questionMatcher.find() && urlMatcher.find();
}
devolver resultados;
}
}
El último método principal es responsable de llamar.
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 todos los objetos Zhihu en esta página
ArrayList<Zhihu> myZhihu = Spider.GetZhihu(contenido);
// imprimir resultados
System.out.println(myZhihu);
}
}
Bien, eso es todo. Ejecútelo y vea los resultados:
Buenos resultados.
El siguiente paso es acceder al enlace y obtener todas las respuestas.
Lo presentaremos la próxima vez.
Bien, lo anterior es una breve introducción a todo el proceso de cómo usar Java para capturar el contenido recomendado por los editores de Zhihu. Es muy detallado y fácil de entender. Los amigos que lo necesiten pueden consultarlo y ampliarlo libremente.