这一次终于到了分析b站视频了。开始体会到写博客非常占用学技术的时间,但是还是希望能总结,沉淀下来。
工具:使用Webmaigc框架,DBUtils,C3P0连接池。
分析过程:b站的搜索页面是这样的。如果浏览器右键查看源代码,你会发现是动态页面,也就是从后台通过ajax等在某个路径加载获得数据
于是初入爬虫的我,打算贪方便试一下selenium模拟浏览器行为,结果效果不太好。当时是b站的搜索页面经常显示的是 出错啦,后来我就苦苦思索,我通过b站的页面在F12开发者工具里,从请求路径里找到了b站视频的搜索url,https://search.bilibili.com/api/search,当时还是很激动的!
从这个路径进去,发现b站视频的数据实际上是一个大Json,通过看webmagic文档知道了它提供了JsonPath的拿取方法。于是就按JsonPath拿数据,原本是用xpath在html里拿数据。
先贴一下我的processor核心代码:
1 public class BilibiliSearchProcessor implementsPageProcessor{2 private Site site = Site.me().setUserAgent("Mozilla/5.0 (Windows NT 10.0; …e/59.0.3071.109 Safari/537.36")3 .setRetryTimes(3)4 .setTimeOut(30000)5 .setSleepTime(1800)6 .setCycleRetryTimes(3)7 .setUseGzip(true)8 .addHeader("Host","search.bilibili.com")9 .addHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")10 .addHeader("Accept-Language","zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")11 .addHeader("Accept-Encoding","gzip, deflate, br")12 ;13 private static final String man = "Pierre Bensusan";14 private static final String defineUrl = "https://search.bilibili.com/api/search?search_type=video&keyword="+man+"&from_source=banner_search&order=totalrank&duration=0&tids=0";15 //"井草圣二","伍伍慧","押尾光太郎","岸部真明","松井佑贵","小松原俊","郑成河","depapepe","Pierre Bensusan","TOMMY EMMANUEL","Daniel Padim","andy mckee"};
16 public voidprocess(Page page) {17 int numPage = Integer.parseInt(page.getJson().jsonPath("$.numPages").get());18 for (int i=0;i
22 List ups = page.getJson().jsonPath("$..author").all();23 page.putField("author", ups);24 //标题
25 List titles = page.getJson().jsonPath("$..title").all();26 page.putField("title", titles);27 //链接
28 List srcLinks = page.getJson().jsonPath("$..arcurl").all();29 page.putField("srcLinks", srcLinks);30 //时长
31 List durations = page.getJson().jsonPath("$..duration").all();32 page.putField("duration", durations);33 //观看数
34 List watchNums = page.getJson().jsonPath("$..play").all();35 page.putField("watchNum", watchNums);36 //上传时间 2017-08-09 150222263337 //2016-09-28 147505314238 //2018-05-18 1526650568
39 List uploadTimes = page.getJson().jsonPath("$..pubdate").all();40 page.putField("uploadTime", uploadTimes);41 //review
42 List reviews = page.getJson().jsonPath("$..review").all();43 //video_review
44 List video_reviews = page.getJson().jsonPath("$..video_review").all();45 //favorite
46 List favorites = page.getJson().jsonPath("$..favorites").all();47 //视频说明
48 List description = page.getJson().jsonPath("$..description").all();49 page.putField("description", description);50 for (int i=0;i
57 publicSite getSite() {58 returnsite;59 }60
61 public static voidmain(String[] args) {62 Spider.create(newBilibiliSearchProcessor())63 //.addUrl(urls)
64 .addUrl(defineUrl)65 .addPipeline(newConsolePipeline())66 .thread(5)67 .run();68 }69 }
有几个当时遇到的要点讲一下:
第一是site的header一定要加!!没有为什么,一定要加,因为要模拟更真实的浏览器访问!
第二是site的爬取频率,b站还是有限制的,.setSleepTime(1800)这样就可以了,不会太快。
第三是b站视频爬的pubdate也就是上传时间,实际上是秒为单位,但是平时java里转换用的是毫秒,当晚我没想明白这个数字该怎么转换成date格式,第二天早上突然就发现了,真是感恩。
另外,json里拿到title实际上带有关键词的高亮,于是写了个cutHtml的方法去replace.
第四是header的host要加对,我当时用selenium有时成功有时失败,我后来改成直接拿Json的时候突然发现我Host之前写的地址好像不对劲,不是search.bilibili.com,现在才渐渐明白估计也是参数错了.
第五是能分析动态分析页面,尽量分析,因为用selenium速度还是不快的,而且会造成java程序结束,chrome进程却没有退出的情况(开发者估计也还没优化!)
1 public classSimpleUtil {2 //短日期格式
3 public static String DATE_FORMAT = "yyyy-MM-dd";4
5 /**
6 * 将长整型数字转换为日期格式的字符串7 *8 *@paramtime9 *@return
10 */
11 public static String convert2String(longtime) {12 if (time > 0l) {13 SimpleDateFormat sf = newSimpleDateFormat(DATE_FORMAT);14 Date date = newDate(time);15 returnsf.format(date);16 }17 return "";18 }19
20 public staticString cutHtml(String str){21 return str.replaceAll("?[^>]+>", "");22 }23 }
Dao就不贴了,直接用DBUtils,QueryRunner执行sql语句save一个数据对象.
有什么疑问可以发我邮箱zhhiyp@qq.com