⽹易云⾳乐java爬⾍_⽤Java实现⽹易云⾳乐爬⾍
起因
前两天在知乎上看到⼀个帖⼦《⽹易云⾳乐有哪些评论过万的歌曲?》,⼀时技痒,⽤Java实现了⼀个简单的爬⾍,这⾥简单记录⼀下。
最终的结果开放出来了,⼤家可以随意访问,请戳这⾥>>>>>> ⽹易云⾳乐爬⾍结果。
爬⾍简介
⽹络爬⾍是⼀种按照⼀定的规则,⾃动地抓取万维⽹信息的程序或者脚本,⼀个通⽤的⽹络爬⾍⼤致包含以下⼏个步骤:
⽹络爬⾍的⼤致流程如上图所⽰,⽆论你是做什么样的爬⾍应⽤,整体流程都是⼤同⼩异。现在,我们就根据⽹易云⾳乐来定制⼀个专门爬取⾳乐评论数量的特定⽹络爬⾍。
前期准备
古诗梅花⽹页类型分析
⾸先,我们需要对⽹易云⾳乐整个⽹站有个⼤致的了解,进⼊⽹易云⾳乐⾸页,浏览后发现其⼤概有这么⼏种类型的URL:推荐页⾯
排⾏榜列表以及排⾏榜页⾯
歌单列表以及歌单页⾯
主播电台列表以及主播电台页⾯
歌⼿列表以及歌⼿页⾯
专辑列表(新碟上架)以及专辑页⾯
歌曲页⾯
我们最终需要爬取的数据在歌曲页⾯中,该页⾯⾥包含了歌曲的名称以及歌曲的评论数量。
另外,我们还需要尽可能多的获取歌曲页⾯,这些信息我们可以从前⾯6种类型的页⾯拿到。其中,歌单列表以及歌单页⾯结构最简单,歌单列表直接分页就可以拿到。因此,我们选择歌单页⾯作为我们的初始页⾯,然后歌单列表--歌单--歌曲⼀路爬下去即可。
设计数据模型
通过上述分析,我们可以知道我们要做两件事情,⼀是爬取页⾯歌单列表--歌单--歌曲,⼆是将最终的结果存储起来。因此,我们只需要两个对象,⼀个⽤来存储页⾯相关的信息,url、页⾯类型、是否被爬过(html和title作为临时数据存储),另外⼀个⽤来存储歌曲相关信
息,url、歌曲名,评论数。因此,model类如下:
public class WebPage {
public enum PageType {
song, playlist, playlists;
}
public enum Status {
crawled, uncrawl;
}
private String url;
private String title;
private PageType type;
private Status status;
private String html;
...
}
public class Song {
private String url;
private String title;
private Long commentCount;
.
..
}
获取⽹页内容并解析
根据之前的分析,我们需要爬的页⾯有三种:歌单列表、歌单以及歌曲。为了验证想法的可⾏性,我们先⽤代码来解析这三种类型的⽹页,我们将⽹页内容获取以及解析的代码都放⼊CrawlerThread当中。
获取html
⽆论想要从什么⽹站中拿到数据,获取其html代码都是最最基础的⼀步,这⾥我们使⽤jsoup来获取页⾯信息,在CrawlerThread中添加如下代码:
private boolean fetchHtml(WebPage webPage) throws IOException {
Connection.Response response = Url()).timeout(3000).execute();
感恩教师节的话webPage.setHtml(response.body());
return response.statusCode() / 100 == 2 ? true : false;
内盘 外盘}
public static void main(String[] args) throws Exception {
WebPage playlists = new WebPage("music.163/#/discover/playlist/?
order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0", PageType.playlists);
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(playlists);
System.out.Html());
}
运⾏后即可看到html⽂本的输出
解析歌单列表页⾯
百听不厌的歌曲得到html后,我们来解析歌单列表,拿到页⾯中的所有歌单,Jsoup包含了html解析相关的功能,我们⽆需添加其他依赖,直接在CrawlerThread中添加如下代码:
private List parsePlaylist(WebPage webPage) {
Elements songs = Jsoup.Html()).select("ul.f-hide li a");
return songs.stream().map(e -> new WebPage(BASE_URL + e.attr("href"), PageType.song,
e.html())).List());
}
public static void main(String[] args) throws Exception {
WebPage playlists = new WebPage("music.163/discover/playlist/?
order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0", PageType.playlists);
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(playlists);
System.out.println(crawlerThread.parsePlaylists(playlists));
}
解析歌单页⾯
和歌单列表页⾯类似,只需要将歌曲相关的元素出来即可:
private List parsePlaylist(WebPage webPage) {
Elements songs = Jsoup.Html()).select("ul.f-hide li a");
return songs.stream().map(e -> new WebPage(BASE_URL + e.attr("href"), PageType.song,
e.html())).List());
}
public static void main(String[] args) throws Exception {
WebPage playlist = new WebPage("music.163/playlist?id=454016843", PageType.playlist);
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(playlist);
System.out.println(crawlerThread.parsePlaylist(playlist));
}
注意,这⾥为了⽅便,我们将歌曲的名称也拿到了,这样后⾯我们就不需要再次获取歌曲名称了。
解析歌曲页⾯
终于到歌曲页⾯了,这⾥⽹易云⾳乐做了反爬处理,获取数据时的参数需要经过加密处理,这⾥我们不纠结于具体算法,如果有兴趣的直接看参考代码,我们只看关键代码:
private Song parseSong(WebPage webPage) throws Exception {
return new Url(), Title(), Url().split("=")[1]));
}
public static void main(String[] args) throws Exception {
WebPage song = new WebPage("music.163/song?id=29999506", PageType.song, "test");
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(song);
System.out.println(crawlerThread.parseSong(song));
}
好吧,获取过程确实⽐较曲折,经过了多次的加密,不过不管怎么样,最终我们还是拿到了我们想要的数据。接下来,就是使⽤爬⾍将整套机制run起来了。
实现爬⾍
非常六加一重新回顾⼀下流程图,我们发现其中有很重要的⼀个对象是爬⾍队列,爬⾍队列的实现⽅法有很多种,⾃⼰实现,mysql、redis、MongoDB等等都可以满⾜我们的需求,不同的选择会导致我们实现的不⼀致。
综合考虑,我们使⽤Mysql+ Spring Data JPA + Spring MVC来跑我们的整套框架,最终还可以将爬下来的数据通过web服务展现出来。更深⼊地学习Spring MVC,请⼤家参考Spring MVC实战⼊门训练。
确定好之后,我们就可以开始⼀步步实现了。这⾥Spring Data JPA的代码就不展⽰了。了解Spring Data JPA,请参考Spring Data JPA 实战⼊门训练。直接上核⼼代码,所有和爬⾍整体流程相关的代码我们都放进CrawlerService中。
初始⽹址
第⼀步建⽴⼀个初始⽹址,我们可以根据歌单列表分页的特征得到:
private void init(String catalog) {
List webPages = wArrayList();
for(int i = 0; i < 43; i++) {
webPages.add(new WebPage("music.163/discover/playlist/?order=hot&cat=" + catalog + "&limit=35&offset=" + (i * 35), PageType.playlists));
}
webPageRepository.save(webPages);
}
public void init() {
webPageRepository.deleteAll();
init("全部");
init("华语");
init("欧美");
init("⽇语");
init("韩语");
init("粤语");
init("⼩语种");
init("流⾏");
init("摇滚");
init("民谣");
init("电⼦");
init("舞曲");
init("说唱");
init("轻⾳乐");
init("爵⼠");
init("乡村");
init("R&B/Soul"); init("古典");
init("民族");
init("英伦");
init("⾦属");
init("朋克");
init("蓝调");
init("雷⿁");
init("世界⾳乐");
init("拉丁");
init("另类/独⽴"); init("New Age"); init("古风");
init("后摇");
init("Bossa Nova"); init("清晨");
init("夜晚");
init("学习");
init("⼯作");
init("午休");
init("下午茶");
init("地铁");
init("驾车");
init("运动");
init("旅⾏");
init("散步");
init("酒吧");
init("怀旧");
init("清新");
init("浪漫");
init("性感");
init("伤感");
init("治愈");骨头汤里的白是蛋白质还是脂肪
init("放松");
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论