java知乎爬虫源码_java知乎爬虫写作过程和思路

2023-11-08

0.需要的知识点

正则表达式

java多线程线程池池知识

httpclient网络库及json和html结构

1.获取主话题

在知乎中一共有33个主话题,在33个主话题下又有15776个子话题,因此我们首先要获取到33个主话题

(ps:一开始打算用HttpURLConnection进行网络请求,由于后面需要以post形式访问并且提交form因此后面的代码改用了httpclient进行网络请求)

28a9bd3365c7?t=123

图中的data-id就是主话题的id

public static void getTopicId(){

new Thread(new Runnable() {

@Override

public void run() {

Connection connection;

int id = 1;

try {

URL url = new URL("https://www.zhihu.com/topics");

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.connect();

BufferedReader bfr = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));

String line = null;

StringBuilder sb = new StringBuilder();

while ((line = (bfr.readLine())) != null){

sb.append(line);

}

String result = sb.toString();

String regex = "data-id=\"[0-9]{0,6}\"";

Pattern pattern = Pattern.compile(regex);

Matcher m = pattern.matcher(result);

String regx = "href=\"#.*?\"";

Pattern p = Pattern.compile(regx);

Matcher mn = p.matcher(result);

while (m.find() && mn.find()){

String s = m.group();

s = s.substring(9,s.length() - 1);

String sn = mn.group();

sn = sn.substring(7,sn.length() - 1);

System.out.println(s + " " + sn);

connection = JDBCUtil.getConn();

PreparedStatement state = (PreparedStatement) connection.prepareStatement("insert into main_topic values(?,?,?)");

state.setInt(1, id++);

state.setInt(2, Integer.valueOf(s));

state.setString(3, sn);

state.execute();

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}).start();

}

2.获取各个主话题下的分话题

通过抓包我们可以发现在分话题页面通过post请求访问到服务器来加载分话题,没一次下拉到底部会多加载20个分话题,通过offset来控制,因此我们可以通过post请求服务器来获得json数据

28a9bd3365c7?t=123

post请求结构

28a9bd3365c7?t=123

通过postman模拟post请求得到返回数据

由于返回的json数据中的中文为unicode编码,因此运用了Utils类中的方法来转换为中文以便储存到数据库中

public static void getChildTopics(int topic_id,Connection conn) throws Exception{

int offset = 0;;

while (true){

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

CloseableHttpClient httpClient = HttpClients.custom()

.setRetryHandler(new DefaultHttpRequestRetryHandler())

.setConnectionManager(cm)

.build();

HttpPost req = new HttpPost("https://www.zhihu.com/node/TopicsPlazzaListV2");

List params = new ArrayList();

params.add(new BasicNameValuePair("method", "next"));

params.add(new BasicNameValuePair("params", "{\"topic_id\":" + topic_id + ",\"offset\":" + offset +",\"hash_id\":\"37492588249aa9b50ee49d1797e9af81\"}"));

req.setEntity(new UrlEncodedFormEntity(params,Consts.UTF_8));

HttpResponse resp = httpClient.execute(req);

String sb = EntityUtils.toString(resp.getEntity());

if (sb.length() < 25) break;

String regex = ".*?";

Pattern p = Pattern.compile(regex);

Matcher m = p.matcher(sb);

String regx = "href=\\\\\"\\\\/topic\\\\/[0-9]+\\\\\"";

Pattern p1 = Pattern.compile(regx);

Matcher m1 = p1.matcher(sb);

while (m.find() && m1.find()){

String temp = m.group().substring(8, m.group().length() - 10);

String sql = "insert into child_topic values(null,?,?,?)";

PreparedStatement state = (PreparedStatement) conn.prepareStatement(sql);

state.setInt(1,topic_id);

state.setString(2,m1.group().substring(16, m1.group().length() - 2));

state.setString(3,Utils.decodeUnicode(temp));

state.execute();

}

offset += 20;

}

}

通过主话题id来获取下面的子话题id

3.通过分话题id来获取热门问答

public static void loadOneTopicHotQA(int child_topic_id) throws Exception{

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

CloseableHttpClient httpClient = HttpClients.custom()

.setRetryHandler(new DefaultHttpRequestRetryHandler())

.setConnectionManager(cm)

.build();

HttpGet req = new HttpGet("https://www.zhihu.com/topic/" + child_topic_id + "/hot");

HttpResponse resp = httpClient.execute(req);

String result = EntityUtils.toString(resp.getEntity());

//正则匹配打不出来,后面以截图形式给出

Pattern p_qa_id = Pattern.compile(regex_qa_id);

Pattern p_qa_name = Pattern.compile(regex_qa_name);

Pattern p_qa_username = Pattern.compile(regex_qa_username);

Matcher m_qa_id = p_qa_id.matcher(result);

Matcher m_qa_name = p_qa_name.matcher(result);

Matcher m_qa_username = p_qa_username.matcher(result);

while (m_qa_id.find() && m_qa_name.find() && m_qa_username.find()){

String[] qanda_id = m_qa_id.group().split("/");

String q_id = qanda_id[2];

String a_id = qanda_id[4].substring(0, qanda_id[4].length() - 2);

String q_name = m_qa_name.group().split("\n")[1];

String temp = m_qa_username.group();

String q_username = null;

if (temp.contains("匿名用户")) q_username = "匿名用户";

else if (temp.contains("知乎用户")) q_username = "知乎用户";

else q_username = temp.substring(30, temp.length() - 1);

HotQA qa = new HotQA(child_topic_id,Integer.valueOf(q_id), q_name, Integer.valueOf(a_id), q_username);

DaoImpl daoimpl = new DaoImpl();

daoimpl.save(qa, child_topic_id);

}

}

28a9bd3365c7?t=123

正则匹配

由于未登陆情况下可能会出现答主名字被替换为知乎用户,因此要考虑答主名字为知乎用户这种情况

4.爬到的数据能做什么

28a9bd3365c7?t=123

数据

通过child_topic_id可知道问题属于哪个话题

通过question_id可以通过拼接url:https://www.zhihu.com/question/{question_id}来访问问题

同理可得url:https://www.zhihu.com/question/{question_id}/answer/{answer_id}来访问回答

5.扩展

在DAO层中提供了返回指定话题最新动态的方法,同时也包含了通过answer_id获取指定回答的方法,将来可能还会加入爬取用户信息的功能。

6.感谢

感谢看到这里,如果不嫌弃的话给gayhub项目一个star呗,关注一下我也是最最最最吼的

gayhub项目 可以直接点哟

另外大家可以也可以通过微博联系我哟:关耳金名

如何使用及编程过程中踩过的坑

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java知乎爬虫源码_java知乎爬虫写作过程和思路 的相关文章

  • yolov5 CUDA out of memory

    目录 yolov5 CUDA out of memory 训练笔记 训练时有时会可视化 生成anchors yolov5 CUDA out of memory yolov5训练 是1060 batch size为8 换一台电脑 batch
  • 技术选型:Sentinel vs Hystrix

    这是围绕 Sentinel 的使用场景 技术对比和实现 开发者实践等维度推出的系列文章的第三篇 第一篇回顾 Dubbo 的流量防卫兵 Sentinel如何通过限流实现服务的高可用性 传送门 第二篇回顾 RocketMQ 的保险丝 Senti
  • java jpa是什么_jpa是什么框架?jpa是什么意思?

    你了解jpa吗 很多人表示 对于jpa是一个什么框架并不是很了解 那么下面就一起通过下面的文章内容来了解一下jpa吧 jpa其实就是Java Persistence API的简称 它的中文名字是Java持久层API 是JDK 5 0注解或者
  • 【Java笔记+踩坑】MyBatisPlus基础

    导航 黑马Java笔记 踩坑汇总 JavaSE JavaWeb SSM SpringBoot 瑞吉外卖 SpringCloud SpringCloudAlibaba 黑马旅游 谷粒商城 目录 1 MyBatisPlus简介 1 1 回顾Sp
  • Vue声明周期(笔记-自己的理解)

    这是vue的生命图示 一共有八个生命周期函数 new Vue 创建Vue实例 相当于以下代码 var vm new Vue 之后就是init Event 和 LifeCycle 初始化事件和生命周期函数 beforeCreate 首先字面意
  • 一名全栈工程师的必备工具箱

    全栈工程师 也叫全端工程师 是指掌握多种技能 并能利用多种技能独立完成产品的人 全栈工程师熟悉多种开发语言 同时具备前端和后台开发能力 从需求分析 原型设计到产品开发 测试 部署 发布全流程都十分熟悉 全栈工程师由于经常研究各种技术 他不会
  • Responder与evil-winRM配合远程登录Windows

    0x01 evil winRM 0x01 1概述 在使用和介绍Responder之前 先来了解一下evil winRM evil winrm是Windows远程管理 WinRM Shell的终极版本 Windows远程管理是WS 管理协议的
  • 怎样判断两个链表相交并找到第一个相交点(微软数据结构面试题)

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com id 7 1 给出两个单向链表的头指针pHead1和pHead2 判断这两个链表是否相交 假设两个链表均不带环 如果两个链表相交于某一节点 那么在这
  • SpringMVC 中的视图如何使用 FreeMarker

    SpringMVC 中的视图如何使用 FreeMarker SpringMVC 是一个基于 Spring 框架的 Web 框架 它提供了一种方便的方式来处理 HTTP 请求和响应 在 SpringMVC 中 视图是用来渲染模型数据的组件 它
  • java es score_ES 使用FunctionScore实现自定义评分

    GET index type search explain query function score query 你的查询语句 field value factor field 字段 modifier log1p factor 0 1 bo
  • Python Requests模块session的使用建议

    本篇主要讲解Python Requests模块session的使用建议及整个会话中的所有cookie的方法 测试代码 服务端 下面是用flask做的一个服务端 用来设置cookie以及打印请求时的请求头 coding utf 8 from
  • 使用LinkedHashMap实现LRU算法

    LinkedHashMap是比HashMap多了一个链表的结构 与HashMap相比LinkedHashMap维护的是一个具有双重链表的HashMap LinkedHashMap支持2中排序一种是插入排序 即插入是什么顺序 读出来的就是什么
  • 什么是ConcurrentHashMap?

    文章目录 什么是ConcurrentHashMap ConcurrentHashMap 的主要特性 ConcurrentHashMap 的用法 ConcurrentHashMap 的实现原理 在什么场景使用ConcurrentHashMap
  • 47黑马QT笔记之Qt下Udp通信过程例子及实现广播与组播

    47黑马QT笔记之Qt下Udp通信过程例子及实现广播与组播 1 客户端 客户端需要注意一点 客户端没有绑定端口的话 服务端无法发送信息给客户端 Linux下可以是因为他们在同一端口 所以Qt下你也在同一端口内通信 即窗口内自己连自己的Ip和
  • 五.LLC谐振变换器

    LLC 谐振变换器启动过程分析 LLC 谐振变换器的组成结构中包含容性器件 为了尽可能减小输出电压纹波 钳位输出电压 此时希望输出滤波电容尽可能的大 因此也会在启动的时候 电容两端电压近似为 0 系统对电容进行充电 此时的电路电流很大 可以
  • ubuntu18.04 安装qt5.12.8及环境配置

    文章目录 一 下载安装包 二 安装 三 QT项目测试 环境 系统 ubuntu18 04 软件 qt5 12 8 一 下载安装包 下载地址http download qt io archive qt 5 12 5 12 8 点击需要的版本
  • idea 远程debug

    文章目录 tomcat startup bat Jboss springboot idea配置 tomcat startup bat 启动脚本添加 jpda Jboss JAVA OPTS JAVA OPTS Xrunjdwp transp
  • idea中使用git创建分支与标签

    目录 1 idea使用分支 2 在本地仓库中 添加分支 编辑 3 提交分支 4 push到远程仓库 编辑 gitignore文件通用模板 5 常用分支操作 5 1 分支创建 5 2 查看分支 5 3 合并 5 4 切换分支 5 5 删除分支
  • MATLAB金融工具箱(一)--快速入门

    一 快速入门 1 什么是金融工具箱 MATLAB和金融工具箱为金融分析和金融工程提供了一个完整的计算环境 并且金融工具箱提供了一切可帮助你完成金融数据的数学和统计分析的功能 并能将结果用高质量图像显示出来 你可以快速地提出 可视化并且解答复

随机推荐

  • java设计模式——工厂方法模式(Factory Method Pattern)

    简单工厂模式虽然简单 但也受到很大限制 扩展性太差 当系统中需要引入新产品时 由于静态工厂方法通过所传入参数的不同来创建不同的产品 这必定要修改工厂类的源代码 将违背 开闭原则 如何实现增加新产品而不影响已有代码 工厂方法模式应运而生 本文
  • 最近我MRI重建的一些进度

    写这篇文章 主要是因为我今天整理了最近一些研究的代码 放到了git上 想着既然整理完了 那就顺便推广一下我的方法 第一个想到的地方就是CSDN 其实不论是MRI重建还是其他问题比如超分辨 去模糊 基本的数学模型本质上还是相同的 都可以用相同
  • spring 容器结构/机制debug分析和几个重要概念以及IOC 的开发模式

    前言 本片文章是spring 容器结构 机制debug分析和几个重要概念以及IOC 的开发模式 个人主页 尘觉主页 https blog csdn net apple 67445472 type blog 个人简介 大家好 我是尘觉 希望我
  • kudu错误分析

    kudu启动错误 第一个问题 报错日志如下 E0919 21 40 31 290339 18387 master cc 189 Unable to init master catalog manager Not found Unable t
  • 浅析存储引擎(4)-对比B-tree和LSM-tree

    浅析日志结构的存储引擎 1 bitcask浅析日志结构的存储引擎 2 SSTable和LSM Tree浅析存储引擎 3 B tree 一 磁盘碎片率 由于B tree存储引擎按固定页写入 那么通常每一页都会有些空间无法使用 而LSM tre
  • Metro UI CSS 学习笔记之组件(侧边栏)

    Metro UI CSS Demo案例
  • Linux mmap系统调用视角看缺页中断

    问题 1 mmap具体是怎么实现比read write少一次内存copy的 2 mmap共享映射和私有映射在内核实现的时候到底有什么区别 3 mmap的文件映射和匿名映射在内核实现的时候到底有什么区别 4 父子进程的COW具体怎么实现的 概
  • 配置typeAliasesPackage支持通配符包路径扫描

    mybatis的xml文件中需要写类的全限定名 较繁琐 可以配置自动扫描包路径给类配置别名 两种配置方式 方式一 mybatis config xml中配置
  • Linux进阶

    创作不易 来了的客官点点关注 收藏 订阅一键三连 前言 运维之基础 Linux 我是一个即将毕业的大学生 超超 如果你也在学习Linux 不妨跟着萌新超超一起学习Linux 拿下Linux 一起加油 共同努力 拿到理想offer 系列文章
  • python os.path.expanduser os.path.expandvars

    os path expanduser path 在linux平台下 可以用 来代表 home 你的用户名 这个路径 那么python是不认识 这个符号的 如果你写路径的时候直接写 pic 程序是执行不了的 但是你非要用 这时候这个os pa
  • http原理与dns原理总结

    1 HTTPS原理 HTTPS 超文本传输安全协议 是一种以安全为基础的HTTP传输通道 HTTP是超文本传输协议 是TCP IP组中协议之一 也是互联网上应用最为广泛的协议之一 所有的WWW 万维网 文件都必须遵循这个标准 因为HTTP也
  • 输出100以内所有能被3整除但不能被5整除的数,按每5个数的形式输出。

    include
  • vue 数组添加元素_用vue.js做一个列表,类似于百度的搜索排名,用v-for来循环

    先看效果吧 如下图 用vue来实现 比较简单 更多文章请关注我的头条号 我是落笔承冰 一 加入vue js链接库 添加一个父组件 一个全局子组件 二 这个时候网页一定是空的 所以我们在子组件添加模板吧 然后在vmd中调用 三 我们把三行li
  • 代码注入:动态解析代码_保护您的代码:开发更安全代码的17个技巧

    代码注入 动态解析代码 网络上的恐怖故事变得越来越糟 首先 一些信用卡号被盗 然后有几千 现在 我们听到数以百万计的财务记录被安全漏洞暴露 并且我们对潜在的威胁变得麻木了 信用卡号码几乎无法触及坏蛋的目标 而且研究网络战争的实验室还传出了更
  • iOS_Unity打包报错MapFileParser.sh:Permission denied

    1 前言 使用unity打包出的IOS包 在XCode进行ARchive到最后的时候出现了MapFileParser sh Permission denied的错误 2 解决办法 打开终端输入如下命令后回车即可 chmod a x User
  • 剪切板复制粘贴工具 PopClip mac中文版

    PopClip mac是一款文本操作工具 它可以在你选中文本时自动弹出菜单 提供了多种常用的文本操作选项 包括复制 剪切 粘贴 搜索 翻译 发送到其他应用程序等 PopClip 通过插件的形式支持了许多第三方应用程序 例如 Google T
  • 安装ceres-solver

    2023 6 8 10 11 安装ceres solver 开源C 库 用于建模和解决大型 复杂的优化问题 它可用于解决具有边界约束的非线性最小二乘问题和一般无约束优化问题 是谷歌开发的一款用于非线性优化的库 在谷歌的开源激光雷达slam项
  • Kotlin集合框架分析

    一 Kotlin中集合框架和Java集合框架特别相似 掌握以下例子就Ok了 package cn kotliner kotlin collections Created by wangdong 集合框架 kotlin中集合的映射 最终都映射
  • 2020-10-14

    今天为大家分享一些可以接私单的平台 相信大家学习编程未来是希望成为一个软件工程师或者码农 找到好的工作 有好的发展 但是在还没有找工作之前 大家可以通过一些平台接一些兼职 一来能够赚钱 在主页保持稳定的情况下能够发展自己的副业 二来通过接项
  • java知乎爬虫源码_java知乎爬虫写作过程和思路

    0 需要的知识点 正则表达式 java多线程线程池池知识 httpclient网络库及json和html结构 1 获取主话题 在知乎中一共有33个主话题 在33个主话题下又有15776个子话题 因此我们首先要获取到33个主话题 ps 一开始