• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Java爬取网易云音乐民谣并导入Excel分析

技术杂谈 勤劳的小蚂蚁 2个月前 (02-05) 116次浏览 已收录 0个评论 扫描二维码

前言

考虑到这里有很多人没有接触过Java网络爬虫,所以我会从很基础的Jsoup分析HttpClient获取的网页讲起。了解这些东西可以直接看后面的“正式进入案例”,跳过前面这些基础。我导入的是“Excel转换工具XXL-EXCEL”这个开源项目然后在这个基础上写的这个Demo(下面会详细分析).

项目分析

几天前用HttpClien+Jsoup网易云音乐的民谣抓取下来,可惜显示效果是下面这样的:
想着如果能像前几天用开源的爬虫爬取知乎后然后导入Excel简单分析也好一点,如下图(下图只是简单的对导入进去的一个人的关注者做了一个排序)
通过查阅文档知道Apache下有一个专门操作office各种文档的API:POI,用这个API的话操作起来原理也很简单,但是很麻烦需要写很多代码,而且条理也不是很清楚。所以去Github上找了找有没有更方便的方法,Github有很多关于这方面的开源项目,经过各种尝试,最终选择了:《Java对象和Excel转换工具XXL-EXCEL》,通过这个框架可以灵活的进行Java对象和Excel文档相互转换
然后最终就是下面这个效果:

案例基础

①Jsoup解析网页分析

Maven依赖:
  1.        <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
  2.        <dependency>
  3.            <groupId>org.jsoup</groupId>
  4.            <artifactId>jsoup</artifactId>
  5.            <version>1.7.2</version>
  6.        </dependency>
请求网页和解析网页,我们都以推酷网:https://www.tuicool.com/为例子。 先看一个实例(本实例获取的是推酷网首页的热门文章的信息):
  1. package news;
  2. import java.io.IOException;
  3. import org.jsoup.Jsoup;
  4. import org.jsoup.nodes.Document;
  5. import org.jsoup.nodes.Element;
  6. import org.jsoup.select.Elements;
  7. publicclassTuicoolHotArticles{
  8.    publicstaticvoid main(String[] args)throwsIOException{
  9.        // TODO Auto-generated method stub
  10.        String url ="https://www.tuicool.com/";
  11.        Document document =Jsoup.connect(url)
  12.                .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0").get();
  13.        // #id: 通过ID查找元素,比如:#logo
  14.        Elements items = document.select(".list_article_item ");
  15.        System.out.println(items.size());
  16.        for(Element item : items){
  17.            // 标题。(类名title下的 a标签的title属性获取)
  18.            String title = item.select(".title a").attr("title");
  19.            // 标题图片地址(类名article_thumb_image下的 img标签的src属性获取)
  20.            String picture_href = item.select(".article_thumb_image img").attr("src");
  21.            // 时间 。(类名tip下的最后一个span标签的文字获取)
  22.            String date = item.select(".tip span").last().text();
  23.            // 作者 。(类名tip下的第一个span标签的文字获取)
  24.            String author = item.select(".tip span").first().text();
  25.            System.out.println("标题:               "+ title);
  26.            System.out.println("标题图片地址:"+ picture_href);
  27.            System.out.println("发布日期           "+ date);
  28.            System.out.println("作者                  "+ author);
  29.            System.out.println();
  30.            System.out.println();
  31.        }
  32.    }
  33. }
实例结果

实例分析:
1 网页元素分析
元素位置->右键->查看元素(Inspent Element)
2 Jsoup解析 
通过元素分析我们即可获取所在div类名以及元素的其他属性,通过这些属性我们即可获取该元素。上面代码我已经给你详细的注释,如果还有问题可以留言给我。
如果想了解更详细的Jsoup操作请查看 jsoup中文文档:

②HttpClient请求网页分析

Maven依赖:
  1.        <!-- httpclient -->
  2.        <dependency>
  3.            <groupId>org.apache.httpcomponents</groupId>
  4.            <artifactId>httpclient</artifactId>
  5.            <version>4.5.4</version>
  6.        </dependency>
下面是一个获取推酷首页源代码的例子:
  1. package www.java1234.com.httpclientDemo2;
  2. import java.io.IOException;
  3. import org.apache.http.HttpEntity;
  4. import org.apache.http.client.ClientProtocolException;
  5. import org.apache.http.client.methods.CloseableHttpResponse;
  6. import org.apache.http.client.methods.HttpGet;
  7. import org.apache.http.impl.client.CloseableHttpClient;
  8. import org.apache.http.impl.client.HttpClients;
  9. import org.apache.http.util.EntityUtils;
  10. /**
  11. * TODO 在www.java1234.com.httpclientDemo.HelloWorld2我们获取推酷网热门文章
  12. * 我们这里通过模拟浏览器的方法来重新获取
  13. *
  14. * @date 2017年12月16日
  15. */
  16. publicclassGetTuicoolHotArticles{
  17.    publicstaticvoid main(String[] args)throwsClientProtocolException,IOException{
  18.        // TODO Auto-generated method stub
  19.        CloseableHttpClient httpClient =HttpClients.createDefault();// 创建httpClient实例
  20.        HttpGet httpGet =newHttpGet("https://www.tuicool.com/");// 创建httpget实例
  21.        // 设置请求头信息Uer-Agent模拟浏览器
  22.        httpGet.setHeader("User-Agent",
  23.                "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0");
  24.        CloseableHttpResponse response = httpClient.execute(httpGet);// 执行httpget请求
  25.        // 获取响应状态
  26.        //System.out.println("响应状态为:" + response.getStatusLine());
  27.        HttpEntity entity = response.getEntity();// 获取返回实体
  28.         System.out.println("网页内容:"+EntityUtils.toString(entity,"utf-8"));
  29.        // 获取响应内容类型Content-Type
  30.        // System.out.println("content-type:" + entity.getContentType());
  31.        response.close();// response关闭
  32.        httpClient.close();// httpClient关闭
  33.    }
  34. }
这个例子有一点需要说明的是因为推酷网设置了简单的反爬所以我们这里必须设置请求头信息Uer-Agent模拟浏览器访问,代码已经注释。
如果想深入学习HttpClient,请查看HttpClient官网:http://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html。

③Maven的简单使用

网上有很多这面的教程,而且Maven这个工具真的很实用,不会的可以在网上找一找教程。再不会留言找我,我教,?嘿嘿。

正式进入本案例

完整源码下载:https://github.com/Snailclimb/Spider
XXL-EXCEL的Maven依赖:
  1. <!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-excel-core/ -->
  2. <dependency>
  3.    <groupId>com.xuxueli</groupId>
  4.    <artifactId>xxl-excel</artifactId>
  5.    <version>1.0.0</version>
  6. </dependency>
我一共新建了三个类Wangyiyun.java:
网易云音乐实体类
WangyiyunMinyao.java:网易云音乐工具类,用于获取存放歌曲对象打得Arraylist集合。
TestWangyiyun.java:测试类,测试获取网易云音乐民谣信息并且输出到Excel中。 因为一次抓取的是一个页面,所以抓取到控制台有输出,速度可能有点慢。Wangyiyun.java
  1. package com.xuxueli.poi.excel.test.model;
  2. import org.apache.poi.hssf.util.HSSFColor;
  3. import com.xuxueli.poi.excel.annotation.ExcelField;
  4. import com.xuxueli.poi.excel.annotation.ExcelSheet;
  5. @ExcelSheet(name ="网易云音乐民谣分析", headColor =HSSFColor.HSSFColorPredefined.LIGHT_GREEN)
  6. publicclassWangyiyun{
  7.    @ExcelField(name ="歌曲介绍")
  8.    privateString description;
  9.    @ExcelField(name ="歌曲链接地址")
  10.    privateString href;
  11.    @ExcelField(name ="歌曲播放次数")
  12.    privateint playNums;
  13.    publicWangyiyun(){
  14.    }
  15.    publicWangyiyun(String description,String href,int playNums){
  16.        this.description = description;
  17.        this.href = href;
  18.        this.playNums = playNums;
  19.    }
  20.    publicString getDescription(){
  21.        return description;
  22.    }
  23.    publicvoid setDescription(String description){
  24.        this.description = description;
  25.    }
  26.    publicString getHref(){
  27.        return href;
  28.    }
  29.    publicvoid setHref(String href){
  30.        this.href = href;
  31.    }
  32.    publicint getPlayNums(){
  33.        return playNums;
  34.    }
  35.    publicvoid setPlayNums(int playNums){
  36.        this.playNums = playNums;
  37.    }
  38.    @Override
  39.    publicString toString(){
  40.        return"Wangyiyun [歌曲介绍="+ description +", 歌曲链接地址="+ href +", 歌曲播放次数="+ playNums +"]";
  41.    }
  42. }
WangyiyunMinyao.java
  1. package utils;
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.InputStreamReader;
  6. import java.util.ArrayList;
  7. import org.apache.http.HttpEntity;
  8. import org.apache.http.HttpResponse;
  9. import org.apache.http.client.ClientProtocolException;
  10. import org.apache.http.client.methods.HttpGet;
  11. import org.apache.http.impl.client.CloseableHttpClient;
  12. import org.apache.http.impl.client.HttpClients;
  13. import org.jsoup.Jsoup;
  14. import org.jsoup.nodes.Document;
  15. import org.jsoup.nodes.Element;
  16. import org.jsoup.select.Elements;
  17. import com.xuxueli.poi.excel.test.model.Wangyiyun;
  18. /**
  19. * TODO 该类用于获取保存在Arraylist中的歌曲对象
  20. * @date 2017年12月21日
  21. */
  22. publicclassWangyiyunMinyao{
  23.    /**
  24.     * 该方法爬取了歌曲标题和链接地址并且调用了GetTheNumberOfPlays()方法用于获取歌曲链接地址页面的详细播放次数
  25.     *
  26.     * @param url_str
  27.     * @param charset
  28.     * @throws ClientProtocolException
  29.     * @throws IOException
  30.     */
  31.    publicstaticArrayList<Wangyiyun>Crawl(String url_str,String charset)
  32.            throwsClientProtocolException,IOException{
  33.        // 获取
  34.        CloseableHttpClient hc=HttpClients.createDefault();
  35.        //HttpClient hc = new DefaultHttpClient();
  36.        HttpGet hg =newHttpGet(url_str);
  37.        HttpResponse response = hc.execute(hg);
  38.        HttpEntity entity = response.getEntity();
  39.        InputStream htm_in =null;
  40.        ArrayList<Wangyiyun> arrayList =newArrayList<>();
  41.        if(entity !=null){
  42.            htm_in = entity.getContent();
  43.            String htm_str =InputStream2String(htm_in, charset);
  44.            Document doc =Jsoup.parse(htm_str);
  45.            Elements links = doc.select("div[class=g-bd]").select("div[class=g-wrap p-pl f-pr]")
  46.                    .select("ul[class=m-cvrlst f-cb]").select("div[class=u-cover u-cover-1");
  47.            for(Element link : links){
  48.                Elements lin = link.select("a");
  49.                // 歌曲描述
  50.                String description = lin.attr("title");
  51.                // 歌曲链接地址
  52.                String href = lin.attr("href");
  53.                href ="http://music.163.com"+ href;
  54.                /*
  55.                 * System.out.print(re_title + "       ");
  56.                 * System.out.print(re_url + "       "); int nums =
  57.                 * GetTheNumberOfPlays(re_url, charset);
  58.                 */
  59.                int nums =GetTheNumberOfPlays(href, charset);
  60.                Wangyiyun wangyiyun =newWangyiyun(description, href, nums);
  61.                arrayList.add(wangyiyun);
  62.            }
  63.        }
  64.        return arrayList;
  65.    }
  66.    /**
  67.     * 该方法爬取歌曲链接地址页面的播放次数
  68.     *
  69.     * @param url_str
  70.     * @param charset
  71.     * @throws ClientProtocolException
  72.     * @throws IOExceptionGet
  73.     *             the number of plays
  74.     */
  75.    publicstaticintGetTheNumberOfPlays(String url_str,String charset)throwsClientProtocolException,IOException{
  76.        CloseableHttpClient hc=HttpClients.createDefault();
  77.        HttpGet hg =newHttpGet(url_str);
  78.        HttpResponse response = hc.execute(hg);
  79.        HttpEntity entity = response.getEntity();
  80.        InputStream htm_in =null;
  81.        int nums =0;
  82.        if(entity !=null){
  83.            htm_in = entity.getContent();
  84.            String htm_str =InputStream2String(htm_in, charset);
  85.            Document doc =Jsoup.parse(htm_str);
  86.            String links = doc.select("div[class=u-title u-title-1 f-cb]").select("div[class=more s-fc3]")
  87.                    .select("strong").text();
  88.            nums =Integer.parseInt(links);
  89.        }
  90.        return nums;
  91.    }
  92.    /*
  93.     * public static void saveHtml(String filepath, String str) {
  94.     *
  95.     * try { OutputStreamWriter outs = new OutputStreamWriter(new
  96.     * FileOutputStream(filepath, true), "utf-8");
  97.     * outs.write("http://www.dailystrength.org" + str + "rn"); outs.close();
  98.     * } catch (IOException e) { System.out.println("Error at save html...");
  99.     * System.out.println(str); e.printStackTrace(); } }
  100.     */
  101.    publicstaticStringInputStream2String(InputStream in_st,String charset)throwsIOException{
  102.        BufferedReader buff =newBufferedReader(newInputStreamReader(in_st, charset));
  103.        StringBuffer res =newStringBuffer();
  104.        String line ="";
  105.        while((line = buff.readLine())!=null){
  106.            res.append(line);
  107.        }
  108.        return res.toString();
  109.    }
  110. }
TestWangyiyun.java
  1. package com.xuxueli.poi.excel.test;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import org.apache.http.client.ClientProtocolException;
  5. import com.xuxueli.poi.excel.ExcelExportUtil;
  6. import com.xuxueli.poi.excel.test.model.Wangyiyun;
  7. import utils.WangyiyunMinyao;
  8. publicclassTestWangyiyun{
  9.    publicstaticvoid main(String[] args)throwsClientProtocolException,IOException{
  10.        int page =0;
  11.        // 这里只爬取了3页数据
  12.        ArrayList<Wangyiyun> wangyiyunArraylist=newArrayList<>();
  13.        for(int i =0; i <3; i++){
  14.            // 爬取
  15.            String url_str ="http://music.163.com/discover/playlist/?order=hot&cat=民谣&limit=35&offset="+ page;
  16.            ArrayList<Wangyiyun> arrayList =WangyiyunMinyao.Crawl(url_str,"utf-8");
  17.            wangyiyunArraylist.addAll(arrayList);
  18.            for(Wangyiyun wangyiyun : arrayList){
  19.                System.out.println(wangyiyun);
  20.            }
  21.            /**
  22.             * Excel导出:Object 转换为 Excel
  23.             */        
  24.            // page参数加35(这个35是分析民谣栏)
  25.            page = page +35;
  26.        }
  27.        String filePath ="wangyiyun.xls";
  28.        ExcelExportUtil.exportToFile(filePath, wangyiyunArraylist, wangyiyunArraylist);
  29.    }
  30. }

容易出现的错误

导入Maven依赖或者导入我的Maven项目后项目上会有感叹号,这种情况应该是Jar包下载出错。(笔主在这里卡了很长时间)
解决办法:查看错误->找到出错的Jar->找到对应jar包存放位置->删除该jar包->去官网自己下载。

补充

下面是我的项目的效果图。目前已经更新到Github。实在还有问题的可以把我的项目拷贝下来看看。 完整源码下载:https://github.com/Snailclimb/Spider(包含导入Excel的工具源码)

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Java爬取网易云音乐民谣并导入Excel分析
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00