java 库知乎_基于原生Java API爬取最新版本知乎百万用户数据

基于原生Java API爬取最新版本知乎200万用户数据

简介

作为中国知名的网络问答平台,截至2017年,知乎注册用户数已经超越1亿,汇集了中国各个领域的青年才俊。从某种程度上而言,知乎用户代表了中国中青年群体。通过分析知乎用户分布情况,可以从地域、行业、教育等方面得出一些有意义的结论。然而,随着知乎反爬系统的不断增强,获取大规模数据越来越困难。针对这一问题,不少同仁已经给出了一些解决方案。例如,知乎用户@KKys以多线程方式获得了10万的用户数据,并对这些数据进行了可视化展示;知乎用户@口可口可针对最新版知乎,解决了自动登陆的难题;知乎用户@Ionny使用深度学习框架,自动识别了验证码。尽管这些方法在实际使用中起到了很大作用,但仍然存在一些问题:首先,一部分方法使用了爬虫框架,诸如Crawler4j、Scrapy等。当然,爬虫框架功能更加强大,但就这一具体问题而言,缺乏灵活性。此外,这些方法多数基于早期知乎版本,不具有现势性。本文在这些方法的基础上,利用原生Java API,基于最新版本知乎 (2018年6月),爬取到200万知乎用户数据,并对这些数据进行简要分析及可视化。

方法

本文用到的技术主要有:

Java URL API (HttpURLConnection),用于发起HTTP请求。

Java Thread Pool API (ThredPoolExecutor),用于以多线程方式爬取数据

Java Security API,用于生成登录时所需的数字签名

Swing,用于显示验证码

JDBC,用于访问数据库

正则表达式,用于数据抽取

fastjson,用于将JSON转换为Java对象

可以说,用到的都是比较基本的Java SE API。流程图如下所示:

登录

登陆过程参照了@口可口可的方法 (https://zhuanlan.zhihu.com/p/34073256) 。登录是爬虫程序最重要的环节之一,知乎在这一环节做了不少的工作,显著地增强了网站的安全性。具体而言,主要有三方面:防止跨域请求伪造的x-xsrftoken首部、避免数据伪造的signature字段,以及验证码的captcha字段。这里提一下signature字段,这是一个使用了HMAC-SHA1算法,以grant_type+client_id+source+timestamep作为输入,同时设置密钥,计算得到的加密字段。

获得话题、子话题列表

进入知乎-话题广场 (https://www.zhihu.com/topics) 。上方列出了33个话题,每个话题包含若干个子话题,在下方显示。

这一步的目的是获得全部话题及子话题的ID号,话题的ID号包含在网页的源代码中,而子话题的ID号需要调用额外接口得到,如下所示:

获得关注者列表

进入子话题详情,以烹饪这一子话题为例 (https://www.zhihu.com/topic/19551805/hot)。 点击右侧的关注者,可以得到最多200个该子话题的关注者,如下所示:

这一步的目的是获得所有子话题的关注者的ID号,需要调用额外接口得到,如下所示:

获得用户信息

关于用户信息,从表面上看,它们应该存放在网页的HTML代码当中,但实际上,完整的用户数据隐藏在页面底部的div标签当中,如下所示:

该div标签的data-state属性保存了完整的用户数据, 它是一个JSON,格式化后如下图:

持久化

采用批量插入方式,将抓取的全部用户数据插入MySQL数据库中。

验证

由于在爬取过程中,知乎会不定时地弹出验证码并中断程序进行。考虑到建立深度学习训练样本集难度较大,并且知乎验证码类型不唯一,本文采用了传统的人工输入验证码方式。如下所示:

实验

结果

整个过程累计用时约38小时,爬取知乎用户数据200多万条。如图所示:

分析

讨论

问题

编写程序过程中,主要遇到了以下几点问题:

数据返回不完整。经过分析,这是由于频繁请求知乎服务器导致的,解决办法:每次请求结束后,都阻塞100毫秒,以降低请求速度。

网络IO抛出异常,诸如连接超时、读取数据超时、请求被拒绝,这很可能是被知乎服务器判定为DOS攻击,通过减少并发线程数、增加等待时间等可以减少这种情况的发生。

正则表达式匹配出错。这种问题是由于原始字符串中含有不可显示的字符导致的,解决方法是移除这些字符,再进行正则匹配。

你可能感兴趣的:(java,库知乎)