万网皆可爬-爬虫实战系列之-极客时间部落沦陷

3,166 阅读4分钟

事情来源

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

xuanzhuangbei

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

geek_tips

咱就按小编说的干,抢个点赞第一!!!说干就干!!!

本来想用抓包工具分析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请求接口

F12_network

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

shujubidui

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

post_param

点赞列表

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

likelist

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

likelist_param

顺带点赞操作

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

addlike

  • 分析到这里我们需要的接口足够了
  • 接下来开始写代码

编码

认证怎么做?

关于认证的详情这里不做赘述,只说明本次使用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

一个程序猿的异常