[Java]知乎下巴第3集:来人啊快把知乎的答案装到篮子里去
来源:互联网 发布:现货黄金分时抛吸源码 编辑:程序博客网 时间:2024/04/30 11:14
上次我们已经能把知乎的问题抓出来了,但是答案还木有抓出来。
这一回合,我们就连着把答案也一起从网站中抠出来=。=
前期我们抓取标题是在该链接下:
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>();}@Overridepublic 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中写个函数即可。
// 处理urlboolean 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;}
接下来就是各个部分的获取工作了。
先看下标题:
正则把握住那个class即可,正则语句可以写成:zm-editable-content\">(.+?)<
运行下看看结果:
哎哟不错哦。
接下来抓取问题描述:
啊哈一样的原理,抓住class,因为它应该是这个的唯一标识。
验证方法:右击查看页面源代码,ctrl+F看看页面中有没有其他的这个字符串。
后来经过验证,还真出了问题:
标题和描述内容前面的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);}
最后就是循环抓取答案了:
初步暂定正则语句:/answer/content.+?<div.+?>(.*?)</div>
改下代码之后我们会发现软件运行的速度明显变慢了,因为他需要访问每个网页并且把上面的内容抓下来。
比如说编辑推荐有20个问题,那么就需要访问网页20次,速度也就慢下来了。
试验一下,看上去效果不错:
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;}// 处理urlboolean 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;}@Overridepublic 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);}}
好的,今天就是这样,晚安。
- [Java]知乎下巴第3集:来人啊快把知乎的答案装到篮子里去
- [Java]知乎下巴第3集:来人啊快把知乎的答案装到篮子里去
- [Java]知乎下巴第4集:再把抓到篮子里的知乎塞到硬盘里吧
- [Java]知乎下巴第4集:再把抓到篮子里的知乎塞到硬盘里吧
- [Java]知乎下巴第0集:让我们一起来做一个知乎爬虫吧哦耶
- [Java]知乎下巴第0集:让我们一起来做一个知乎爬虫吧哦耶
- [Java]知乎下巴第2集:使用爬虫来获取知乎的编辑推荐内容
- [Java]知乎下巴第2集:使用爬虫来获取知乎的编辑推荐内容
- [Java]知乎下巴第1集:爬虫世界百度不仅仅可以拿来测网速
- [Java] 知乎下巴第5集:使用HttpClient工具包和宽度爬虫
- [Java] 知乎下巴第5集:使用HttpClient工具包和宽度爬虫
- Java知乎爬虫之抓取知乎答案
- 第一篇哦~~知乎问题答案分析
- 零基础写Java知乎爬虫之抓取知乎答案
- 零基础写Java知乎爬虫之抓取知乎答案
- JAVA知乎爬虫
- 「新功能」知乎排名上线,快来查看你的知乎排名
- 知乎中用到的正则表达式。
- 晶振旁外接电容的选择
- 1003 Hit or Miss
- 单指令多数据并行提速(二)
- OCP-1Z0-新051-61题版本-33
- Data Block Dump
- [Java]知乎下巴第3集:来人啊快把知乎的答案装到篮子里去
- 电压源驱动和电流源驱动 输入阻抗和输出阻抗小结
- 三极管与MOS管区别
- 负反馈的类型及判定判别方法 及其优点
- hust1010TheMinimumLength(kmp,循环节)
- 0欧电阻作用
- 坑爹的LNK2005错误
- 电脑蓝屏问题排查
- 常用贴片电阻、电容、电感封装