前几天写了一个上网爬取滑稽色图片(手动滑稽)的小爬虫,今天,突发奇想,想爬取视频看看。
以B站敖厂长的视频实验:
1.找到要爬取视频
2.右键查看源码:
与审查元素对比找到这里:EmbedPlayer('player', "///play.swf", "cid=26379702&aid=16164197&pre_ad=0");猜测这里调用的js的函数是嵌入播放器到这个里面;
3.去找页面引用的js里找EmbedPlayer()函数,发现在这个/js/core-v5/page.arc.js文件里;
虽然压缩了,但是网上有反压缩工具,轻松反压缩:
4.读了下js代码,发现"cid=26379702&aid=16164197&pre_ad=0"参数,也就是视频的资源id信息被切好封装到g中,然后
通过swfobject.embedSWF向"///play.swf"请求过去了。其实看到这个函数的调用形式就该猜到,我还是太菜了。
5.知道视频地址了,我就找过去(/play.swf?cid=26379702&aid=16164197&pre_ad=0)看看,果然
6.接下来开始爬取,代码先不贴了,因为又走弯路了。这个url爬过来的是一个swf的壳,也就是播放器的样式的壳,即这个玩意儿:
/play.swf,我早该想到的。。。
7.没有获取到视频数据,猜测是这个swf自己去向服务器请求的。但swf不可能查看源码,所以fiddler抓包去吧。
成功抓到flv视频流,看看这个域名中的cn-hnjz,莫不是中国湖南株洲(我这边是湖南长沙),这可能是b站在湖南地区的服务器结点,这种大型网站毕竟都是分布式的。
8.接下来向着这个URL爬过啊!mmp,403 forbidden。。。
其实也就是Referer没加上,被拦了。
9.在请求的request报头上加上Referer: /play.swf?cid=26379702&aid=16164197&pre_ad=0,然后,爬过去!
ok!下面是Java代码:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import .URL;
import .URLConnection;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String urlstr="https://cn-hnjz-cu-v-/vg1/6/8c/26379702-1-80.flv?expires=1510310100&platform=pc&ssig=-KvYiV9XoT1ggHN9ArX-zQ&oi=974402195&nfa=oHqC5M/eAoZsl45MAwqMEQ==&dynamic=1&hfa=823259&hfb=Yjk5ZmZjM2M1YzY4ZjAwYTMzMTIzYmIyNWY4ODJkNWI=";
File file=new File("D:/text/ccf/spider/webpage/swf/"+"aa.flv");
if(!file.exists()){
System.out.println("@创建文件:"+"aa.flv");
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("@创建文件异常:");
System.out.println("@"+e);
}
}
else
return;
//访问该URL,写入其HTML到对应文件中
try{
URL url = new URL(urlstr);
URLConnection con = url.openConnection();
con.setConnectTimeout(5*1000);
con.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
con.setRequestProperty("Referer", "/play.swf?cid=26379702&aid=16164197&pre_ad=0");
BufferedInputStream is = new BufferedInputStream(con.getInputStream());
FileOutputStream fs = new FileOutputStream(file);
try{
byte[] bs = new byte[1024];
int len;
while ((len = is.read(bs)) != -1){
fs.write(bs, 0, len);
}
}
catch(Exception e){
System.out.println("@IO异常:");
System.out.println("@"+e);
}
finally{
is.close();
fs.close();
System.out.println("@文件写入结束。");
}
}
catch(Exception e){
System.out.println("@请求URL异常:");
System.out.println("@"+e);
}
}
}
好了,虽然一个视频爬取解决了,但在抓包获取视频url的哪一步上怎么让程序自己解决呢,批量爬取怎么实现,swf里的URL数据有没有办法读出来呢?下次再试试吧!