亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

零基礎(chǔ)寫(xiě)Java知乎爬蟲(chóng)之抓取知乎答案

 更新時(shí)間:2014年11月07日 11:13:06   投稿:hebedich  
上篇文章我們已經(jīng)能把知乎的問(wèn)題抓出來(lái)了,但是答案還木有抓出來(lái)。這一回合,我們就連著把答案也一起從網(wǎng)站中摳出來(lái)=。=

前期我們抓取標(biāo)題是在該鏈接下:

http://www.zhihu.com/explore/recommendations

但是顯然這個(gè)頁(yè)面是無(wú)法獲取答案的。

一個(gè)完整問(wèn)題的頁(yè)面應(yīng)該是這樣的鏈接:

http://www.zhihu.com/question/22355264

仔細(xì)一看,啊哈我們的封裝類(lèi)還需要進(jìn)一步包裝下,至少需要個(gè)questionDescription來(lái)存儲(chǔ)問(wèn)題描述:

import java.util.ArrayList;
public class Zhihu {
 public String question;// 問(wèn)題
 public String questionDescription;// 問(wèn)題描述
 public String zhihuUrl;// 網(wǎng)頁(yè)鏈接
 public ArrayList<String> answers;// 存儲(chǔ)所有回答的數(shù)組
 // 構(gòu)造方法初始化數(shù)據(jù)
 public Zhihu() {
  question = "";
  questionDescription = "";
  zhihuUrl = "";
  answers = new ArrayList<String>();
 }
 @Override
 public String toString() {
  return "問(wèn)題:" + question + "\n" + "描述:" + questionDescription + "\n"
    + "鏈接:" + zhihuUrl + "\n回答:" + answers + "\n";
 }
}

我們給知乎的構(gòu)造函數(shù)加上一個(gè)參數(shù),用來(lái)設(shè)定url值,因?yàn)閡rl確定了,這個(gè)問(wèn)題的描述和答案也就都能抓到了。

我們將Spider的獲取知乎對(duì)象的方法改一下,只獲取url即可:

 static ArrayList<Zhihu> GetZhihu(String content) {
  // 預(yù)定義一個(gè)ArrayList來(lái)存儲(chǔ)結(jié)果
  ArrayList<Zhihu> results = new ArrayList<Zhihu>();
  // 用來(lái)匹配url,也就是問(wèn)題的鏈接
  Pattern urlPattern = Pattern.compile("<h2>.+?question_link.+?href=\"(.+?)\".+?</h2>");
  Matcher urlMatcher = urlPattern.matcher(content);
  // 是否存在匹配成功的對(duì)象
  boolean isFind = urlMatcher.find();
  while (isFind) {
   // 定義一個(gè)知乎對(duì)象來(lái)存儲(chǔ)抓取到的信息
   Zhihu zhihuTemp = new Zhihu(urlMatcher.group(1));
   // 添加成功匹配的結(jié)果
   results.add(zhihuTemp);
   // 繼續(xù)查找下一個(gè)匹配對(duì)象
   isFind = urlMatcher.find();
  }
  return results;
 }

接下來(lái),就是在Zhihu的構(gòu)造方法里面,通過(guò)url獲取所有的詳細(xì)數(shù)據(jù)。

我們先要對(duì)url進(jìn)行一個(gè)處理,因?yàn)橛械尼槍?duì)回答的,它的url是:

http://www.zhihu.com/question/22355264/answer/21102139

有的針對(duì)問(wèn)題的,它的url是:

http://www.zhihu.com/question/22355264

那么我們顯然需要的是第二種,所以需要用正則把第一種鏈接裁切成第二種,這個(gè)在Zhihu中寫(xiě)個(gè)函數(shù)即可。

// 處理url
 boolean getRealUrl(String url) {
  // 將http://www.zhihu.com/question/22355264/answer/21102139
  // 轉(zhuǎn)化成http://www.zhihu.com/question/22355264
  // 否則不變
  Pattern pattern = Pattern.compile("question/(.*?)/");
  Matcher matcher = pattern.matcher(url);
  if (matcher.find()) {
   zhihuUrl = "  } else {
   return false;
  }
  return true;
 }

接下來(lái)就是各個(gè)部分的獲取工作了。

先看下標(biāo)題:

正則把握住那個(gè)class即可,正則語(yǔ)句可以寫(xiě)成:zm-editable-content\">(.+?)<

運(yùn)行下看看結(jié)果:

哎喲不錯(cuò)哦。

接下來(lái)抓取問(wèn)題描述:

啊哈一樣的原理,抓住class,因?yàn)樗鼞?yīng)該是這個(gè)的唯一標(biāo)識(shí)。

驗(yàn)證方法:右擊查看頁(yè)面源代碼,ctrl+F看看頁(yè)面中有沒(méi)有其他的這個(gè)字符串。

后來(lái)經(jīng)過(guò)驗(yàn)證,還真出了問(wèn)題:

標(biāo)題和描述內(nèi)容前面的class是一樣的。

那只能通過(guò)修改正則的方式來(lái)重新抓?。?/p>

// 匹配標(biāo)題
   pattern = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
   matcher = pattern.matcher(content);
   if (matcher.find()) {
    question = matcher.group(1);
   }
   // 匹配描述
   pattern = Pattern
     .compile("zh-question-detail.+?<div.+?>(.*?)</div>");
   matcher = pattern.matcher(content);
   if (matcher.find()) {
    questionDescription = matcher.group(1);
   }

最后就是循環(huán)抓取答案了:

初步暫定正則語(yǔ)句:/answer/content.+?<div.+?>(.*?)</div>

改下代碼之后我們會(huì)發(fā)現(xiàn)軟件運(yùn)行的速度明顯變慢了,因?yàn)樗枰L問(wèn)每個(gè)網(wǎng)頁(yè)并且把上面的內(nèi)容抓下來(lái)。

比如說(shuō)編輯推薦有20個(gè)問(wèn)題,那么就需要訪問(wèn)網(wǎng)頁(yè)20次,速度也就慢下來(lái)了。

試驗(yàn)一下,看上去效果不錯(cuò):


OK,那就先這樣好了~下次繼續(xù)進(jìn)行一些細(xì)節(jié)的調(diào)整,比如多線程,IO流寫(xiě)入本地等等。

附項(xiàng)目源碼:

Zhihu.java

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Zhihu {
 public String question;// 問(wèn)題
 public String questionDescription;// 問(wèn)題描述
 public String zhihuUrl;// 網(wǎng)頁(yè)鏈接
 public ArrayList<String> answers;// 存儲(chǔ)所有回答的數(shù)組
 // 構(gòu)造方法初始化數(shù)據(jù)
 public Zhihu(String url) {
  // 初始化屬性
  question = "";
  questionDescription = "";
  zhihuUrl = "";
  answers = new ArrayList<String>();
  // 判斷url是否合法
  if (getRealUrl(url)) {
   System.out.println("正在抓取" + zhihuUrl);
   // 根據(jù)url獲取該問(wèn)答的細(xì)節(jié)
   String content = Spider.SendGet(zhihuUrl);
   Pattern pattern;
   Matcher matcher;
   // 匹配標(biāo)題
   pattern = Pattern.compile("zh-question-title.+?<h2.+?>(.+?)</h2>");
   matcher = pattern.matcher(content);
   if (matcher.find()) {
    question = matcher.group(1);
   }
   // 匹配描述
   pattern = Pattern
     .compile("zh-question-detail.+?<div.+?>(.*?)</div>");
   matcher = pattern.matcher(content);
   if (matcher.find()) {
    questionDescription = matcher.group(1);
   }
   // 匹配答案
   pattern = Pattern.compile("/answer/content.+?<div.+?>(.*?)</div>");
   matcher = pattern.matcher(content);
   boolean isFind = matcher.find();
   while (isFind) {
    answers.add(matcher.group(1));
    isFind = matcher.find();
   }
  }
 }
 // 根據(jù)自己的url抓取自己的問(wèn)題和描述和答案
 public boolean getAll() {
  return true;
 }
 // 處理url
 boolean getRealUrl(String url) {
  // 將
http://www.zhihu.com/question/22355264/answer/21102139
  // 轉(zhuǎn)化成http://www.zhihu.com/question/22355264
  // 否則不變
  Pattern pattern = Pattern.compile("question/(.*?)/");
  Matcher matcher = pattern.matcher(url);
  if (matcher.find()) {
   zhihuUrl = "  } else {
   return false;
  }
  return true;
 }
 @Override
 public String toString() {
  return "問(wèn)題:" + question + "\n" + "描述:" + questionDescription + "\n"
    + "鏈接:" + zhihuUrl + "\n回答:" + answers.size() + "\n";
 }
}

Spider.java

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Spider {
 static String SendGet(String url) {
  // 定義一個(gè)字符串用來(lái)存儲(chǔ)網(wǎng)頁(yè)內(nèi)容
  String result = "";
  // 定義一個(gè)緩沖字符輸入流
  BufferedReader in = null;
  try {
   // 將string轉(zhuǎn)成url對(duì)象
   URL realUrl = new URL(url);
   // 初始化一個(gè)鏈接到那個(gè)url的連接
   URLConnection connection = realUrl.openConnection();
   // 開(kāi)始實(shí)際的連接
   connection.connect();
   // 初始化 BufferedReader輸入流來(lái)讀取URL的響應(yīng)
   in = new BufferedReader(new InputStreamReader(
     connection.getInputStream(), "UTF-8"));
   // 用來(lái)臨時(shí)存儲(chǔ)抓取到的每一行的數(shù)據(jù)
   String line;
   while ((line = in.readLine()) != null) {
    // 遍歷抓取到的每一行并將其存儲(chǔ)到result里面
    result += line;
   }
  } catch (Exception e) {
   System.out.println("發(fā)送GET請(qǐng)求出現(xiàn)異常!" + e);
   e.printStackTrace();
  }
  // 使用finally來(lái)關(guān)閉輸入流
  finally {
   try {
    if (in != null) {
     in.close();
    }
   } catch (Exception e2) {
    e2.printStackTrace();
   }
  }
  return result;
 }
 // 獲取所有的編輯推薦的知乎內(nèi)容
 static ArrayList<Zhihu> GetRecommendations(String content) {
  // 預(yù)定義一個(gè)ArrayList來(lái)存儲(chǔ)結(jié)果
  ArrayList<Zhihu> results = new ArrayList<Zhihu>();
  // 用來(lái)匹配url,也就是問(wèn)題的鏈接
  Pattern pattern = Pattern
    .compile("<h2>.+?question_link.+?href=\"(.+?)\".+?</h2>");
  Matcher matcher = pattern.matcher(content);
  // 是否存在匹配成功的對(duì)象
  Boolean isFind = matcher.find();
  while (isFind) {
   // 定義一個(gè)知乎對(duì)象來(lái)存儲(chǔ)抓取到的信息
   Zhihu zhihuTemp = new Zhihu(matcher.group(1));
   // 添加成功匹配的結(jié)果
   results.add(zhihuTemp);
   // 繼續(xù)查找下一個(gè)匹配對(duì)象
   isFind = matcher.find();
  }
  return results;
 }
}

Main.java

import java.util.ArrayList;
public class Main {
 public static void main(String[] args) {
  // 定義即將訪問(wèn)的鏈接
  String url = "
  // 訪問(wèn)鏈接并獲取頁(yè)面內(nèi)容
  String content = Spider.SendGet(url);
  // 獲取編輯推薦
  ArrayList<Zhihu> myZhihu = Spider.GetRecommendations(content);
  // 打印結(jié)果
  System.out.println(myZhihu);
 }
}

以上就是抓取知乎答案的全部記錄,非常的詳盡,有需要的朋友可以參考下

相關(guān)文章

  • Springboot?集成spring?cache緩存的解決方案

    Springboot?集成spring?cache緩存的解決方案

    這篇文章主要介紹了Springboot?集成spring?cache緩存,使用緩存最關(guān)鍵的一點(diǎn)就是保證緩存與數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性,本文給大家介紹最常用的緩存操作模式,對(duì)Springboot?集成spring?cache緩存操作流程感興趣的朋友一起看看吧
    2022-06-06
  • MyBatis配置的應(yīng)用與對(duì)比jdbc的優(yōu)勢(shì)

    MyBatis配置的應(yīng)用與對(duì)比jdbc的優(yōu)勢(shì)

    這篇文章主要介紹了MyBatis配置的使用與相對(duì)于jdbc的優(yōu)勢(shì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java中的5種同步輔助類(lèi)介紹

    Java中的5種同步輔助類(lèi)介紹

    你提交了一些任務(wù),但你想等它們都完成了再做另外一些事情;你提交了一些任務(wù),但是不想讓它們立刻執(zhí)行,等你喊123開(kāi)始的時(shí)候,它們才開(kāi)始執(zhí)行;等等這些場(chǎng)景,線程之間需要相互配合,或者等待某一個(gè)條件成熟執(zhí)行。這些場(chǎng)景想你就需要用到同步輔助類(lèi)
    2014-04-04
  • 詳解Java設(shè)計(jì)模式——命令模式

    詳解Java設(shè)計(jì)模式——命令模式

    這篇文章主要介紹了Java設(shè)計(jì)模式——命令模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • SpringBoot+Vue+Redis實(shí)現(xiàn)單點(diǎn)登錄(一處登錄另一處退出登錄)

    SpringBoot+Vue+Redis實(shí)現(xiàn)單點(diǎn)登錄(一處登錄另一處退出登錄)

    小編接到一個(gè)需求,需要實(shí)現(xiàn)用戶(hù)在瀏覽器登錄后,跳轉(zhuǎn)到其他頁(yè)面,當(dāng)用戶(hù)在其它地方又登錄時(shí),前面用戶(hù)登錄的頁(yè)面退出登錄,這篇文章主要介紹了SpringBoot+Vue+Redis實(shí)現(xiàn)單點(diǎn)登錄,需要的朋友可以參考下
    2019-12-12
  • 利用Java代碼寫(xiě)一個(gè)并行調(diào)用模板

    利用Java代碼寫(xiě)一個(gè)并行調(diào)用模板

    這篇文章主要介紹了利用Java代碼寫(xiě)一個(gè)并行調(diào)用模板,文章基于Java的相關(guān)內(nèi)容展開(kāi)寫(xiě)一個(gè)并行調(diào)用模板的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之時(shí)間復(fù)雜度與空間復(fù)雜度

    Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之時(shí)間復(fù)雜度與空間復(fù)雜度

    對(duì)于一個(gè)算法,其時(shí)間復(fù)雜度和空間復(fù)雜度往往是相互影響的,當(dāng)追求一個(gè)較好的時(shí)間復(fù)雜度時(shí),可能會(huì)使空間復(fù)雜度的性能變差,即可能導(dǎo)致占用較多的存儲(chǔ)空間,這篇文章主要給大家介紹了關(guān)于Java時(shí)間復(fù)雜度、空間復(fù)雜度的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • java?class?name實(shí)例深入精講

    java?class?name實(shí)例深入精講

    這篇文章主要為大家介紹了java?class?name實(shí)例深入精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java接口異步調(diào)用優(yōu)化技巧詳解

    Java接口異步調(diào)用優(yōu)化技巧詳解

    本文詳細(xì)介紹了在Java開(kāi)發(fā)中,如何通過(guò)異步調(diào)用等技巧來(lái)優(yōu)化接口的性能,有效避免阻塞和提高并發(fā)處理能力,提升系統(tǒng)的穩(wěn)定性和響應(yīng)速度
    2023-05-05
  • SpringBoot集成使用Redis及搭建過(guò)程

    SpringBoot集成使用Redis及搭建過(guò)程

    jackson-json 工具提供了 javabean 與 json 之 間的轉(zhuǎn)換能力,可以將 pojo 實(shí)例序列化成 json 格式存儲(chǔ)在 redis 中,也可以將 json 格式的數(shù)據(jù)轉(zhuǎn)換成 pojo 實(shí)例,本文給大家介紹SpringBoot集成使用Redis及搭建過(guò)程,感興趣的朋友一起看看吧
    2022-01-01

最新評(píng)論