事情来源
在家闲来无事,想学习下大牛们的心得,于是打开极客时间app准备安心学习,突然映入眼帘一则广告炫“装备”大赛#开始啦简单撸了一眼,咱也不是爱凑热闹的人(咱也不差这点钱~),于是打开课程开始学习。

这一学不要紧,学习的太过投入到了吃饭的时间,吃饭前肯定要刷会手机啊,进去极客时间部落去看个热闹,这一看可来了兴致,小编发的一张图很有意思,作为一个技术流是时候展现真正的技术了。

咱就按小编说的干,抢个点赞第一!!!说干就干!!!
本来想用抓包工具分析app接口的,还好多思考了下,极客时间有网页版,网页有部落功能吗?
打开网页,登录果真有!这下省事了,不用抓包app了,直接chrome F12就能搞定了,天助我也!!!
查看robots协议
User-agent: *
Disallow: /data/
Disallow: /plus/
Disallow: /content/
Disallow: /*.php$
Disallow: /*.asp$
Sitemap: https://time.geekbang.org/sitemap.txt
作为一个小爬虫还是有必要关心下这些常识的,看着可以干!就这么搞了!
分析接口流程
帖子列表
- 浏览器打开开发者模式,F12进入
- 根据小编提示进入
我是数码控活动页面 - 选择
network下的xhr选项,这里列出了所有的ajax请求接口

极客时间的接口定义还是比较清楚的,根据接口见名知意的原则初步定位https://horde.geekbang.org/serv/v1/channel/posts这个接口是帖子列表接口
复制此接口的response信息到json编辑器观察下结果(我用的是notepad++的jstool插件),结果太多只截取关键部分。

从图中可以分析出关键信息字段,没错这就是我们要的接口。
往下滑动会发现分页也是请求的这个接口,进一步确认了我们定位的信息。
从分页请求观察请求参数可以发现参数比较简单,下一页请求index信息来源于上一页的结果

点赞列表
观察点赞列表可以发现当点赞人数超过20个,会出现等点燃了动态字样,不经意鼠标一点击分页显示了点赞人员,观察xhr请求会发现请求的接口路径是https://horde.geekbang.org/serv/v1/likes/list,参数和结果分析同动态列表不在赘述。

这里有个强调的地方index参数来源于上一页请求结构返回的current+1。为什么接口不统一?

顺带点赞操作
点击小火苗按钮观察请求接口https://horde.geekbang.org/serv/v1/likes/add

- 分析到这里我们需要的接口足够了
- 接下来开始写代码
编码
认证怎么做?
关于认证的详情这里不做赘述,只说明本次使用cookie进行认证。
难道还要研究登录接口吗?NO!!! 我们就是一锤子买卖没必要做那么复杂,直接复制request header的cookie信息。
亮出大杀器
maven 依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.11</version>
</dependency>
分析接口的时候我们发现三个接口使用的数据提交方式是一致的,统一使用的post json的形式,可以简单封装一个方法进行数据请求。
关键代码
public String sendJsonPost(String uri, Map<String, Object> param) {
String html = "";
HttpPost post = new HttpPost(uri);
addHeader(post);
String paramJson = JSON.toJSONString(param);
StringEntity requestEntity = new StringEntity(paramJson, "utf-8");
requestEntity.setContentEncoding("UTF-8");
post.setHeader("Content-type", "application/json");
post.setEntity(requestEntity);
CloseableHttpClient client = getHttpClient();
CloseableHttpResponse httpResponse = null;
try {
httpResponse = client.execute(post);
HttpEntity entity = httpResponse.getEntity();
html = EntityUtils.toString(entity);
System.out.println(html);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 很重要
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return html;
}
- addHeader 方法添加request信息,直接从浏览器复制下来的信息
- getHttpClient 封装的工具类
- httpResponse.close(); 这一句很重要,很多人是不写的,在运行次数很少的情况下是不会出问题的,如果一直循环运行不关闭的话会出现报错导致程序停止
最终结果分析
点赞最多的:horde.geekbang.org/message/det…
总共发布话题221次 总共点赞8474次 点赞最多的次数95次,第二名69 点赞最少的12次 点赞前三的次数221,220,219(5个) 点赞前三的用户Alex,BIZGO-WX😊ི,(Aspirin,miion,ran,Leeby,Geek_a46f6a)
统计sql
SELECT * FROM horde.post ORDER BY post.like_count DESC;
SELECT SUM(p.like_count) FROM horde.post p;
SELECT COUNT(*) c,post_like_user.post_id FROM horde.post_like_user GROUP BY post_like_user.post_id ORDER BY c DESC;
SELECT COUNT(*) c,post_like_user.user_id FROM horde.post_like_user GROUP BY post_like_user.user_id ORDER BY c DESC;
小小的遗憾
- 虽然写了脚本但是没有一直运行,不然也得拿个点赞最多啊,下次再有活动一定一直运行~
- 极客时间点赞列表里面没有返回点赞的时间,有时间字段的话可以分析下点赞频率看下是机器人还是手动点赞,我觉得后台肯定是有存储的
PS: 10点就关机睡觉了~
自己的点赞数据 210 排名12
