一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 零基礎寫Java知乎爬蟲之抓取知乎答案

零基礎寫Java知乎爬蟲之抓取知乎答案

2019-12-04 11:30hebedich JAVA教程

上篇文章我們已經能把知乎的問題抓出來了,但是答案還木有抓出來。這一回合,我們就連著把答案也一起從網站中摳出來=。=

前期我們抓取標題是在該鏈接下:

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

但是顯然這個頁面是無法獲取答案的。

一個完整問題的頁面應該是這樣的鏈接:

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

仔細一看,啊哈我們的封裝類還需要進一步包裝下,至少需要個questionDescription來存儲問題描述:

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

我們給知乎的構造函數加上一個參數,用來設定url值,因為url確定了,這個問題的描述和答案也就都能抓到了。

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

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

接下來,就是在Zhihu的構造方法里面,通過url獲取所有的詳細數據。

我們先要對url進行一個處理,因為有的針對回答的,它的url是:

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

有的針對問題的,它的url是:

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

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

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

接下來就是各個部分的獲取工作了。

先看下標題:

零基礎寫Java知乎爬蟲之抓取知乎答案

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

運行下看看結果:

零基礎寫Java知乎爬蟲之抓取知乎答案

哎喲不錯哦。

接下來抓取問題描述:

零基礎寫Java知乎爬蟲之抓取知乎答案

啊哈一樣的原理,抓住class,因為它應該是這個的唯一標識。

驗證方法:右擊查看頁面源代碼,ctrl+F看看頁面中有沒有其他的這個字符串。

后來經過驗證,還真出了問題:

零基礎寫Java知乎爬蟲之抓取知乎答案

標題和描述內容前面的class是一樣的。

那只能通過修改正則的方式來重新抓取:

// 匹配標題
   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);
   }

最后就是循環抓取答案了:

零基礎寫Java知乎爬蟲之抓取知乎答案

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

改下代碼之后我們會發現軟件運行的速度明顯變慢了,因為他需要訪問每個網頁并且把上面的內容抓下來。

比如說編輯推薦有20個問題,那么就需要訪問網頁20次,速度也就慢下來了。

試驗一下,看上去效果不錯:

零基礎寫Java知乎爬蟲之抓取知乎答案

OK,那就先這樣好了~下次繼續進行一些細節的調整,比如多線程,IO流寫入本地等等。

附項目源碼:

Zhihu.java

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Zhihu {
 public String question;// 問題
 public String questionDescription;// 問題描述
 public String zhihuUrl;// 網頁鏈接
 public ArrayList<String> answers;// 存儲所有回答的數組
 // 構造方法初始化數據
 public Zhihu(String url) {
  // 初始化屬性
  question = "";
  questionDescription = "";
  zhihuUrl = "";
  answers = new ArrayList<String>();
  // 判斷url是否合法
  if (getRealUrl(url)) {
   System.out.println("正在抓取" + zhihuUrl);
   // 根據url獲取該問答的細節
   String content = Spider.SendGet(zhihuUrl);
   Pattern pattern;
   Matcher matcher;
   // 匹配標題
   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();
   }
  }
 }
 // 根據自己的url抓取自己的問題和描述和答案
 public boolean getAll() {
  return true;
 }
 // 處理url
 boolean getRealUrl(String url) {
  // 將http://www.zhihu.com/question/22355264/answer/21102139
  // 轉化成http://www.zhihu.com/question/22355264
  // 否則不變
  Pattern pattern = Pattern.compile("question/(.*?)/");
  Matcher matcher = pattern.matcher(url);
  if (matcher.find()) {
   zhihuUrl = "http://www.zhihu.com/question/" + matcher.group(1);
  } else {
   return false;
  }
  return true;
 }
 @Override
 public String toString() {
  return "問題:" + 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) {
  // 定義一個字符串用來存儲網頁內容
  String result = "";
  // 定義一個緩沖字符輸入流
  BufferedReader in = null;
  try {
   // 將string轉成url對象
   URL realUrl = new URL(url);
   // 初始化一個鏈接到那個url的連接
   URLConnection connection = realUrl.openConnection();
   // 開始實際的連接
   connection.connect();
   // 初始化 BufferedReader輸入流來讀取URL的響應
   in = new BufferedReader(new InputStreamReader(
     connection.getInputStream(), "UTF-8"));
   // 用來臨時存儲抓取到的每一行的數據
   String line;
   while ((line = in.readLine()) != null) {
    // 遍歷抓取到的每一行并將其存儲到result里面
    result += line;
   }
  } catch (Exception e) {
   System.out.println("發送GET請求出現異常!" + e);
   e.printStackTrace();
  }
  // 使用finally來關閉輸入流
  finally {
   try {
    if (in != null) {
     in.close();
    }
   } catch (Exception e2) {
    e2.printStackTrace();
   }
  }
  return result;
 }
 // 獲取所有的編輯推薦的知乎內容
 static ArrayList<Zhihu> GetRecommendations(String content) {
  // 預定義一個ArrayList來存儲結果
  ArrayList<Zhihu> results = new ArrayList<Zhihu>();
  // 用來匹配url,也就是問題的鏈接
  Pattern pattern = Pattern
    .compile("<h2>.+?question_link.+?href=\"(.+?)\".+?</h2>");
  Matcher matcher = pattern.matcher(content);
  // 是否存在匹配成功的對象
  Boolean isFind = matcher.find();
  while (isFind) {
   // 定義一個知乎對象來存儲抓取到的信息
   Zhihu zhihuTemp = new Zhihu(matcher.group(1));
   // 添加成功匹配的結果
   results.add(zhihuTemp);
   // 繼續查找下一個匹配對象
   isFind = matcher.find();
  }
  return results;
 }
}

Main.java

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久久国产综合精品女小说 | 好舒服好爽再快点视频 | 日韩视频一区二区 | yy8090韩国日本三理论免费 | 500福利第一巨人导航 | 侮辱丰满美丽的人妻 | 性欧美13处丶14处 | 国产成人亚洲精品一区二区在线看 | 极品美女写真菠萝蜜视频 | 青草视频免费观看在线观看 | 深夜福利一区 | 日本又黄又裸一级大黄裸片 | 网站在线观看 | 亚洲午夜小视频 | 日本最大的黄色网站 | 色吧 | 成年女人免费 | 天天天天天干 | 国产靠逼视频 | 免费特黄一区二区三区视频一 | 国产精品日韩欧美一区二区 | 好大好深受不了了快进来 | 免费在线观看日韩 | 无耻之徒第十一季在线观看 | 91传媒制片厂果冻有限公司 | 美女被绑着吸下部的故事 | 日本精品久久久久久久久免费 | 日本成人高清视频 | 欧美艳星julnaann | 久久国产香蕉 | porno中国xxxxx| 4455永久在线视频观看 | 99久久99久久免费精品蜜桃 | 免费视频亚洲 | 日韩欧美色 | 免费片在线观看高清 | 久久er99热精品一区二区 | 成人亚洲欧美日韩在线观看 | 久久久精品3d动漫一区二区三区 | 日本精品一区二区在线播放 | 国产一区二区三区四区波多野结衣 |