由于种种原因,需要获取一批尺寸相同的头像图片,所以学了一下Fiddler的数据抓取,最后锁定移动端的某直播APP,通过Java代码处理和下载图片信息!
Fiddler的使用就不再这里讲了,百度上一大堆,包括PC端和移动端,这里主要说的是对数据包(接口)进行分析,包括url的参数,以及通过json映射成我们需要的Java对象,最后过滤到我们想要的信息。
实现思路: 想想看,要得到某一个直播厅内的在线人数的所有头像,也就是抓取进入直播间的url,里面肯定包含一些主播信息,以及用户List信息(不同的主播在不同的直播间有不同的在线人数),这里面就包含了一些分析和猜的思想。
光书面上讲然并卵,上代码:
public class FetchImg {
private static final String IMG_SUFFIXES = ".jpg";
private static final Gson gson = new Gson();
public static void main(String[] args) throws Exception {
// Lives(直播列表): http://116.211.167.106/api/live/simpleall?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&
// 某个主播厅的在线用户信息:http://116.211.167.106/api/live/users?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&count=20&id=1467986016489595&start=0
// 某个在线用户头像图片 :http://image.scale.inke.com/imageproxy2/dimgm/scaleImage?url=http%3A%2F%2Fimg.meelive.cn%2FOTc3MDYxNDYzNjU0MDc4.jpg&w=72&s=80&h=72&c=0&o=0
long startTime=System.currentTimeMillis();
Set allLiveRoomAllUser = new HashSet();
Set allLiveRoomAllPortrait = new HashSet();
String urlContent2Room = FetchUtils.fetchUrlInfo(
"http://120.55.238.158/api/live/simpleall?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&");
Rooms rooms = gson.fromJson(urlContent2Room, Rooms.class);
for(Live live :rooms.getLives()){
System.out.println("主播ID: "+live.getId());
for (int i = 0; i < 100000; i++) {
String urlContent2Live = FetchUtils.fetchUrlInfo(
"http://120.55.238.158/api/live/users?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&count=20&id="+live.getId()+"&start="
+ i);
UserInfo userInfo = gson.fromJson(urlContent2Live, UserInfo.class);
if(userInfo.getUsers().isEmpty() || userInfo.getUsers().size() == 0){
System.out.println("主播ID为:" + live.getId() +"所在直播厅的在线人数为: " + i);
break;
}
allLiveRoomAllUser.addAll(userInfo.getUsers());
}
}
System.out.println("allLiveRoomAllUser size :"+allLiveRoomAllUser.size());
for (User user : allLiveRoomAllUser) {
if (user.getPortrait().contains(IMG_SUFFIXES)) {
StringBuffer sb = new StringBuffer();
sb.append("http://image.scale.inke.com/imageproxy2/dimgm/scaleImage?url=")
.append(UrlEncoded.encodeString("http://img.meelive.cn/")).append(user.getPortrait())
.append("&w=72&s=80&h=72&c=0&o=0");
System.out.println(sb.toString());
allLiveRoomAllPortrait.add(sb.toString());
}
}
System.out.println("allLiveRoomAllPortrait size :"+allLiveRoomAllPortrait.size());
FetchUtils.imgDownLoad(allLiveRoomAllPortrait);
long endTime=System.currentTimeMillis();
System.out.println("运行时常:"+(float)(endTime-startTime)/1000+"s");
}
}
Step1:
// 某个主播厅的在线用户信息:http://116.211.167.106/api/live/users?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&count=20&id=1467986016489595&start=0
得到某个直播间的信息后,通过JSON解析,你会发现JSON对象中有个List
Step2:
以上portrait属性存放的只是某个用户的图片信息,我们要的是能够下载到的图片url地址,那么还需要去抓包.
// 某个在线用户头像图片 :http://image.scale.inke.com/imageproxy2/dimgm/scaleImage?url=http%3A%2F%2Fimg.meelive.cn%2FOTc3MDYxNDYzNjU0MDc4.jpg&w=72&s=80&h=72&c=0&o=0
当你点击这个URl的时候,你会发现显示的是头像图片,我们要的就是这个,剩下的就交给Java来给我们Download,但是不可能一个一个的吧url传给java去下载,这尼玛太坑爹了!
so,你会发现不同的用户头像信息只是FOTc3MDYxNDYzNjU0MDc4.jpg不同,我们只需要把刚才转换的User对象的portrait属性值拼接进去(还包含一个前缀的Encode ,UrlEncoded.encodeString("http://img.meelive.cn/")),就得到了所有的用户的URL
再把URL集合交给Java去下载就OK了!!
FetchUtils.imgDownLoad(allLiveRoomAllPortrait);
Step3:
你看到某个直播厅的在线人数有多少万人,其实都是乘以过相关基数的,所以距离20w的图片还是远远不够!(不信你把下载到的图片个数和你看到的在线人数比较一下你就知道了!)
所以你还需要去抓包。
获取当前直播列表中的每一个直播厅的在线人数集合,这样应该差不多了!
具体思路: 你要找到step1中的url的上层接口,也就是提供不同的主播id(可以理解为不同的直播厅),这里你还要分析不同的直播厅的url有什么参数不同,你会发现每个直播厅的id不同(id=1467986016489595),其他都是一致,这就需要上层接口来提供这个id了,你不可能手动去更换每一个直播厅id,这更上面每次只下一张图片一个性质性质!
你需要找到直播id集合。
// Lives(直播列表): http://116.211.167.106/api/live/simpleall?imsi=&uid=140772639&proto=7&idfa=0207882E-BD03-474E-8B82-DB4DB97A9801&lc=0000000000000029&cc=TG0001&imei=&sid=20XfFcVXrKFc6o6xSAsnGELBSTpVg2jHXmdzgNf9nZN4RTk9M9&cv=IK3.2.50_Iphone&devi=aef437d0af012a4e5da5a1ebdda65c9a6110bc09&conn=Wifi&ua=iPhone%205s&idfv=1B2E671F-8694-498A-B4F3-EF8670FF2C5D&osversion=ios_8.400000&
上面的url你通过JSON转换你会发现,里面有个id的集合,这应该就是每个主播的id,这个当时也是猜的!!
最后像上述操作一样拼接成直播列表的url的集合(貌似是一个直播列表中有200个直播,size=200,默认按热门进行排序的)
step4:
这样就得到了当前直播列表中的每一个直播厅的所有在线人数的信息,然后交给Java去下载!ok了,我是用了循环来进行下载的,还有Set去重,效率有点低,有点low,你可以用Redis!!!
最后,一些Common的方法【读取URL(FetchUtils.fetchUrlInfo),io下载(FetchUtils.imgDownLoad)】和JSON对应的实体类的代码就不上传了,soEZ!!!
附上效果图:
PS:你发现实际在线人数和你看到的在线人数有多大差距~~~^_^