Na fase inicial, rastreamos o título neste link:
http://www.zhihu.com/explore/recommendations
Mas obviamente esta página não pode obter a resposta.
Uma página de perguntas completa ficaria assim:
http://www.zhihu.com/question/22355264
Olhando mais de perto, aha, nossa classe de encapsulamento precisa ser empacotada ainda mais. Pelo menos uma questionDescription é necessária para armazenar a descrição da pergunta:
importar java.util.ArrayList;
classe pública Zhihu {
questão de String pública // pergunta
public String questionDescription; // Descrição da pergunta
public String zhihuUrl; // link da página da Web
public ArrayList<String> respostas; // Array para armazenar todas as respostas;
//Construtor inicializa os dados
público Zhihu() {
pergunta = "";
perguntaDescrição = "";
zhihuUrl = "";
respostas = new ArrayList<String>();
}
@Substituir
string pública paraString() {
return "Pergunta:" + pergunta + "/n" + "Descrição:" + perguntaDescrição + "/n"
+ "Link:" + zhihuUrl + "/nresposta:" + respostas + "/n";
}
}
Adicionamos um parâmetro ao construtor de Zhihu para definir o valor do URL. Como o URL é determinado, a descrição e a resposta à pergunta podem ser capturadas.
Vamos mudar o método do Spider para obter objetos Zhihu e obter apenas o URL:
static ArrayList<Zhihu> GetZhihu(String conteúdo) {
// Pré-defina um ArrayList para armazenar os resultados
ArrayList<Zhihu> resultados = new ArrayList<Zhihu>();
// Usado para corresponder ao URL, que é o link para a pergunta
Padrão urlPattern = Pattern.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Correspondente urlMatcher = urlPattern.matcher(conteúdo);
// Se existe um objeto correspondente bem-sucedido
booleano isFind = urlMatcher.find();
enquanto (éEncontrar) {
//Define um objeto Zhihu para armazenar as informações capturadas
Zhihu zhihuTemp = novo Zhihu(urlMatcher.group(1));
//Adiciona resultados de correspondência bem-sucedidos
resultados.add(zhihuTemp);
//Continua para encontrar o próximo objeto correspondente
isFind = urlMatcher.find();
}
retornar resultados;
}
A seguir, no método de construção de Zhihu, obtenha todos os dados detalhados por meio da url.
Primeiro precisamos processar a url, pois para algumas respostas, sua url é:
http://www.zhihu.com/question/22355264/answer/21102139
Alguns são específicos para o problema e seu URL é:
http://www.zhihu.com/question/22355264
Então, obviamente, precisamos do segundo tipo, então precisamos usar regras regulares para transformar o primeiro tipo de link no segundo tipo. Isso pode ser feito escrevendo uma função em Zhihu.
// lida com URL
boolean getRealUrl(String url) {
// Alterar http://www.zhihu.com/question/22355264/answer/21102139
//Converter para http://www.zhihu.com/question/22355264
// Caso contrário, nenhuma alteração
Padrão padrão = Pattern.compile("question/(.*?)/");
Correspondente correspondente = padrão.matcher(url);
if (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} outro {
retornar falso;
}
retornar verdadeiro;
}
O próximo passo é obter as diversas peças.
Vamos dar uma olhada no título primeiro:
Basta entender essa classe na forma regular. A instrução regular pode ser escrita como: zm-editable-content/">(.+?)<
Execute-o para ver os resultados:
Ai, nada mal.
Em seguida, pegue a descrição do problema:
Aha, o mesmo princípio, pegue a classe, pois deve ser o identificador único desta.
Método de verificação: clique com o botão direito para visualizar o código-fonte da página, ctrl+F para ver se há outras strings na página.
Mais tarde, após verificação, algo realmente deu errado:
A classe na frente do título e do conteúdo da descrição é a mesma.
Isso só pode ser capturado novamente modificando o padrão regular:
//corresponde ao título
padrão = Padrão.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = padrão.matcher(conteúdo);
if (matcher.find()) {
pergunta = matcher.grupo(1);
}
//Descrição da correspondência
padrão=Padrão
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = padrão.matcher(conteúdo);
if (matcher.find()) {
perguntaDescrição = matcher.group(1);
}
A última coisa é fazer um loop para obter a resposta:
Declaração regular provisória preliminar: /answer/content.+?<div.+?>(.*?)</div>
Depois de alterar o código, descobriremos que o software fica significativamente mais lento porque precisa visitar cada página da web e capturar o conteúdo dela.
Por exemplo, se houver 20 perguntas recomendadas pelo editor, você precisará visitar a página da web 20 vezes e a velocidade diminuirá.
Experimente, parece bom:
OK, vamos deixar assim por enquanto ~ Da próxima vez continuaremos a fazer alguns ajustes detalhados, como multi-threading, gravação de fluxos de IO localmente, etc.
Em anexo está o código fonte do projeto:
Zhihu.java
importar java.util.ArrayList;
importar java.util.regex.Matcher;
importar java.util.regex.Pattern;
classe pública Zhihu {
questão de String pública // pergunta
public String questionDescription; // Descrição da pergunta
public String zhihuUrl; // link da página da Web
public ArrayList<String> respostas; // Array para armazenar todas as respostas;
//Construtor inicializa os dados
público Zhihu(String url) {
//Inicializa propriedades
pergunta = "";
perguntaDescrição = "";
zhihuUrl = "";
respostas = new ArrayList<String>();
// Determina se o URL é legal
if (getRealUrl(url)) {
System.out.println("rastreamento" + zhihuUrl);
// Obtenha os detalhes da pergunta e resposta com base na URL
Conteúdo da string = Spider.SendGet(zhihuUrl);
Padrão padrão;
Combinador de correspondência;
//corresponde ao título
padrão = Padrão.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
matcher = padrão.matcher(conteúdo);
if (matcher.find()) {
pergunta = matcher.grupo(1);
}
//Descrição da correspondência
padrão=Padrão
.compile("zh-question-detail.+?<div.+?>(.*?)</div>");
matcher = padrão.matcher(conteúdo);
if (matcher.find()) {
perguntaDescrição = matcher.group(1);
}
//Corresponde à resposta
padrão = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
matcher = padrão.matcher(conteúdo);
booleano isFind = matcher.find();
enquanto (éEncontrar) {
respostas.add(matcher.group(1));
isFind = matcher.find();
}
}
}
// Pegue suas próprias perguntas, descrições e respostas com base em seu próprio URL
public boolean getAll() {
retornar verdadeiro;
}
// lida com URL
boolean getRealUrl(String url) {
// Alterar http://www.zhihu.com/question/22355264/answer/21102139
//Converter para http://www.zhihu.com/question/22355264
// Caso contrário, nenhuma alteração
Padrão padrão = Pattern.compile("question/(.*?)/");
Correspondente correspondente = padrão.matcher(url);
if (matcher.find()) {
zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
} outro {
retornar falso;
}
retornar verdadeiro;
}
@Substituir
string pública paraString() {
return "Pergunta:" + pergunta + "/n" + "Descrição:" + perguntaDescrição + "/n"
+ "Link:" + zhihuUrl + "/nResposta:" + respostas.size() + "/n";
}
}
Aranha.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;
classe pública Aranha {
String estática SendGet(String url) {
//Define uma string para armazenar o conteúdo da página web
Resultado da string = "";
//Define um fluxo de entrada de caracteres em buffer
BufferedReader em = null;
tentar {
//Converte string em objeto url
URL realUrl = nova URL(url);
// Inicializa um link para essa URL
Conexão URLConnection = realUrl.openConnection();
// Inicia a conexão real
conexão.connect();
//Inicializa o stream de entrada do BufferedReader para ler a resposta da URL
in = novo BufferedReader(novo InputStreamReader(
connection.getInputStream(), "UTF-8"));
// Usado para armazenar temporariamente os dados de cada linha capturada
Linha de corda;
while ((linha = in.readLine()) != null) {
// Percorre cada linha capturada e armazena-a no resultado
resultado += linha;
}
} catch (Exceção e) {
System.out.println("Ocorreu exceção ao enviar solicitação GET!" + e);
e.printStackTrace();
}
// Use finalmente para fechar o fluxo de entrada
finalmente {
tentar {
if (em! = nulo) {
in.close();
}
} catch (Exceção e2) {
e2.printStackTrace();
}
}
resultado de retorno;
}
// Obtenha todo o conteúdo do Zhihu recomendado pelos editores
static ArrayList<Zhihu> GetRecommendations(String content) {
// Pré-defina um ArrayList para armazenar os resultados
ArrayList<Zhihu> resultados = new ArrayList<Zhihu>();
// Usado para corresponder ao URL, que é o link para a pergunta
Padrão padrão = Padrão
.compile("<h2>.+?question_link.+?href=/"(.+?)/".+?</h2>");
Correspondente correspondente = padrão.matcher (conteúdo);
// Se existe um objeto correspondente bem-sucedido
Booleano isFind = matcher.find();
enquanto (éEncontrar) {
//Define um objeto Zhihu para armazenar as informações capturadas
Zhihu zhihuTemp = novo Zhihu(matcher.group(1));
//Adiciona resultados de correspondência bem-sucedidos
resultados.add(zhihuTemp);
//Continua para encontrar o próximo objeto correspondente
isFind = matcher.find();
}
retornar resultados;
}
}
Principal.java
importar java.util.ArrayList;
classe pública Principal {
public static void main(String[] args) {
//Define o link a ser visitado
String url = "http://www.zhihu.com/explore/recommendations";
//Acesse o link e obtenha o conteúdo da página
Conteúdo da string = Spider.SendGet(url);
// Obtenha recomendações do editor
ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(conteúdo);
// imprime resultados
System.out.println(meuZhihu);
}
}
O texto acima é o registro completo de obtenção de respostas de Zhihu. É muito detalhado. Amigos necessitados podem consultá-lo.