前言

考虑到这里有很多人没有接触过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依赖:

        <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.2</version>
</dependency>

请求网页和解析网页,我们都以推酷网:https://www.tuicool.com/为例子。

先看一个实例(本实例获取的是推酷网首页的热门文章的信息):

package news;

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; public class TuicoolHotArticles { public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String url = "https://www.tuicool.com/";
Document document = Jsoup.connect(url)
.userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0").get(); // #id: 通过ID查找元素,比如:#logo
Elements items = document.select(".list_article_item ");
System.out.println(items.size());
for (Element item : items) {
// 标题。(类名title下的 a标签的title属性获取)
String title = item.select(".title a").attr("title");
// 标题图片地址(类名article_thumb_image下的 img标签的src属性获取)
String picture_href = item.select(".article_thumb_image img").attr("src");
// 时间 。(类名tip下的最后一个span标签的文字获取)
String date = item.select(".tip span").last().text();
// 作者 。(类名tip下的第一个span标签的文字获取)
String author = item.select(".tip span").first().text(); System.out.println("标题: " + title);
System.out.println("标题图片地址:" + picture_href);
System.out.println("发布日期 " + date);
System.out.println("作者 " + author);
System.out.println();
System.out.println();
}
} }

实例结果:



实例分析:

1. 网页元素分析

元素位置->右键->查看元素(Inspent Element)



2. Jsoup解析

通过元素分析我们即可获取所在div类名以及元素的其他属性,通过这些属性我们即可获取该元素。上面代码我已经给你详细的注释,如果还有问题可以留言给我。

如果想了解更详细的Jsoup操作请查看 jsoup中文文档

②HttpClient请求网页分析

Maven依赖:

        <!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>

下面是一个获取推酷首页源代码的例子:

package www.java1234.com.httpclientDemo2;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils; /**
* TODO 在www.java1234.com.httpclientDemo.HelloWorld2我们获取推酷网热门文章
* 我们这里通过模拟浏览器的方法来重新获取
*
* @date 2017年12月16日
*/
public class GetTuicoolHotArticles { public static void main(String[] args) throws ClientProtocolException, IOException {
// TODO Auto-generated method stub
CloseableHttpClient httpClient = HttpClients.createDefault(); // 创建httpClient实例
HttpGet httpGet = new HttpGet("https://www.tuicool.com/"); // 创建httpget实例
// 设置请求头信息Uer-Agent模拟浏览器
httpGet.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0");
CloseableHttpResponse response = httpClient.execute(httpGet); // 执行httpget请求
// 获取响应状态
//System.out.println("响应状态为:" + response.getStatusLine());
HttpEntity entity = response.getEntity(); // 获取返回实体
System.out.println("网页内容:" + EntityUtils.toString(entity, "utf-8"));
// 获取响应内容类型Content-Type
// System.out.println("content-type:" + entity.getContentType());
response.close(); // response关闭
httpClient.close(); // httpClient关闭
} }

这个例子有一点需要说明的是因为推酷网设置了简单的反爬所以我们这里必须设置请求头信息Uer-Agent模拟浏览器访问,代码已经注释。

如果想深入学习HttpClient,请查看HttpClient官网

③Maven的简单使用

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

正式进入本案例

完整源码下载:https://github.com/Snailclimb/Spider

XXL-EXCEL的Maven依赖

<!-- http://repo1.maven.org/maven2/com/xuxueli/xxl-excel-core/ -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-excel</artifactId>
<version>1.0.0</version>
</dependency>

我一共新建了三个类:



Wangyiyun.java:网易云音乐实体类。

WangyiyunMinyao.java:网易云音乐工具类,用于获取存放歌曲对象打得Arraylist集合。

TestWangyiyun.java:测试类,测试获取网易云音乐民谣信息并且输出到Excel中。

因为一次抓取的是一个页面,所以抓取到控制台有输出,速度可能有点慢。

Wangyiyun.java

package com.xuxueli.poi.excel.test.model;

import org.apache.poi.hssf.util.HSSFColor;

import com.xuxueli.poi.excel.annotation.ExcelField;
import com.xuxueli.poi.excel.annotation.ExcelSheet; @ExcelSheet(name = "网易云音乐民谣分析", headColor = HSSFColor.HSSFColorPredefined.LIGHT_GREEN)
public class Wangyiyun { @ExcelField(name = "歌曲介绍")
private String description; @ExcelField(name = "歌曲链接地址")
private String href; @ExcelField(name = "歌曲播放次数")
private int playNums; public Wangyiyun() {
} public Wangyiyun(String description, String href, int playNums) {
this.description = description;
this.href = href;
this.playNums = playNums;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public String getHref() {
return href;
} public void setHref(String href) {
this.href = href;
} public int getPlayNums() {
return playNums;
} public void setPlayNums(int playNums) {
this.playNums = playNums;
} @Override
public String toString() {
return "Wangyiyun [歌曲介绍=" + description + ", 歌曲链接地址=" + href + ", 歌曲播放次数=" + playNums + "]";
} }

WangyiyunMinyao.java

package utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import com.xuxueli.poi.excel.test.model.Wangyiyun;
/**
* TODO 该类用于获取保存在Arraylist中的歌曲对象
* @date 2017年12月21日
*/ public class WangyiyunMinyao { /**
* 该方法爬取了歌曲标题和链接地址并且调用了GetTheNumberOfPlays()方法用于获取歌曲链接地址页面的详细播放次数
*
* @param url_str
* @param charset
* @throws ClientProtocolException
* @throws IOException
*/
public static ArrayList<Wangyiyun> Crawl(String url_str, String charset)
throws ClientProtocolException, IOException {
// 获取
CloseableHttpClient hc=HttpClients.createDefault();
//HttpClient hc = new DefaultHttpClient();
HttpGet hg = new HttpGet(url_str);
HttpResponse response = hc.execute(hg);
HttpEntity entity = response.getEntity(); InputStream htm_in = null;
ArrayList<Wangyiyun> arrayList = new ArrayList<>();
if (entity != null) {
htm_in = entity.getContent();
String htm_str = InputStream2String(htm_in, charset);
Document doc = Jsoup.parse(htm_str);
Elements links = doc.select("div[class=g-bd]").select("div[class=g-wrap p-pl f-pr]")
.select("ul[class=m-cvrlst f-cb]").select("div[class=u-cover u-cover-1");
for (Element link : links) {
Elements lin = link.select("a");
// 歌曲描述
String description = lin.attr("title");
// 歌曲链接地址
String href = lin.attr("href");
href = "http://music.163.com" + href;
/*
* System.out.print(re_title + " ");
* System.out.print(re_url + " "); int nums =
* GetTheNumberOfPlays(re_url, charset);
*/
int nums =GetTheNumberOfPlays(href, charset);
Wangyiyun wangyiyun = new Wangyiyun(description, href, nums);
arrayList.add(wangyiyun);
}
}
return arrayList;
} /**
* 该方法爬取歌曲链接地址页面的播放次数
*
* @param url_str
* @param charset
* @throws ClientProtocolException
* @throws IOExceptionGet
* the number of plays
*/
public static int GetTheNumberOfPlays(String url_str, String charset) throws ClientProtocolException, IOException {
CloseableHttpClient hc=HttpClients.createDefault();
HttpGet hg = new HttpGet(url_str);
HttpResponse response = hc.execute(hg);
HttpEntity entity = response.getEntity(); InputStream htm_in = null;
int nums = 0;
if (entity != null) {
htm_in = entity.getContent();
String htm_str = InputStream2String(htm_in, charset);
Document doc = Jsoup.parse(htm_str);
String links = doc.select("div[class=u-title u-title-1 f-cb]").select("div[class=more s-fc3]")
.select("strong").text();
nums = Integer.parseInt(links);
}
return nums;
} /*
* public static void saveHtml(String filepath, String str) {
*
* try { OutputStreamWriter outs = new OutputStreamWriter(new
* FileOutputStream(filepath, true), "utf-8");
* outs.write("http://www.dailystrength.org" + str + "\r\n"); outs.close();
* } catch (IOException e) { System.out.println("Error at save html...");
* System.out.println(str); e.printStackTrace(); } }
*/ public static String InputStream2String(InputStream in_st, String charset) throws IOException {
BufferedReader buff = new BufferedReader(new InputStreamReader(in_st, charset));
StringBuffer res = new StringBuffer();
String line = "";
while ((line = buff.readLine()) != null) {
res.append(line);
}
return res.toString();
}
}

TestWangyiyun.java

package com.xuxueli.poi.excel.test;

import java.io.IOException;
import java.util.ArrayList; import org.apache.http.client.ClientProtocolException; import com.xuxueli.poi.excel.ExcelExportUtil;
import com.xuxueli.poi.excel.test.model.Wangyiyun; import utils.WangyiyunMinyao; public class TestWangyiyun { public static void main(String[] args) throws ClientProtocolException, IOException {
int page = 0;
// 这里只爬取了3页数据
ArrayList<Wangyiyun> wangyiyunArraylist=new ArrayList<>();
for (int i = 0; i < 3; i++) {
// 爬取
String url_str = "http://music.163.com/discover/playlist/?order=hot&cat=民谣&limit=35&offset=" + page;
ArrayList<Wangyiyun> arrayList = WangyiyunMinyao.Crawl(url_str, "utf-8");
wangyiyunArraylist.addAll(arrayList);
for (Wangyiyun wangyiyun : arrayList) {
System.out.println(wangyiyun);
} /**
* Excel导出:Object 转换为 Excel
*/
// page参数加35(这个35是分析民谣栏)
page = page + 35;
}
String filePath = "wangyiyun.xls";
ExcelExportUtil.exportToFile(filePath, wangyiyunArraylist, wangyiyunArraylist);
} }

容易出现的错误

导入Maven依赖或者导入我的Maven项目后项目上会有感叹号,这种情况应该是Jar包下载出错。(笔主在这里卡了很长时间)

解决办法:



查看错误->找到出错的Jar->找到对应jar包存放位置->删除该jar包->去官网自己下载。

补充

刚才知道大家可能因为jar包下载错误或者各种问题有问题。

下面是我的项目的效果图。目前已经更新到Github。实在还有问题的可以把我的项目拷贝下来看看。

完整源码下载:https://github.com/Snailclimb/Spider(包含导入Excel的工具源码)

Java爬取网易云音乐民谣并导入Excel分析的更多相关文章

  1. 用Python爬取网易云音乐热评

    用Python爬取网易云音乐热评 本文旨在记录Python爬虫实例:网易云热评下载 由于是从零开始,本文内容借鉴于各种网络资源,如有侵权请告知作者. 要看懂本文,需要具备一点点网络相关知识.不过没有关 ...

  2. python爬虫:了解JS加密爬取网易云音乐

    python爬虫:了解JS加密爬取网易云音乐 前言 大家好,我是"持之以恒_liu",之所以起这个名字,就是希望我自己无论做什么事,只要一开始选择了,那么就要坚持到底,不管结果如何 ...

  3. 如何用Python网络爬虫爬取网易云音乐歌曲

    今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将网易云歌词抓取下来已经不再话下了,在抓取歌词的时候在函数中传入了歌手ID和歌曲名两 ...

  4. python网络爬虫&&爬取网易云音乐

    #爬取网易云音乐 url="https://music.163.com/discover/toplist" #歌单连接地址 url2 = 'http://music.163.com ...

  5. python爬虫+词云图,爬取网易云音乐评论

    又到了清明时节,用python爬取了网易云音乐<清明雨上>的评论,统计词频和绘制词云图,记录过程中遇到一些问题 爬取网易云音乐的评论 一开始是按照常规思路,分析网页ajax的传参情况.看到 ...

  6. 爬取网易云音乐评论!python 爬虫入门实战(六)selenium 入门!

    说到爬虫,第一时间可能就会想到网易云音乐的评论.网易云音乐评论里藏了许多宝藏,那么让我们一起学习如何用 python 挖宝藏吧! 既然是宝藏,肯定是用要用钥匙加密的.打开 Chrome 分析 Head ...

  7. Python爬取网易云音乐歌手歌曲和歌单

    仅供学习参考 Python爬取网易云音乐网易云音乐歌手歌曲和歌单,并下载到本地 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做 ...

  8. Python爬虫——request实例:爬取网易云音乐华语男歌手top10歌曲

    requests是python的一个HTTP客户端库,跟urllib,urllib2类似,但比那两个要简洁的多,至于request库的用法, 推荐一篇不错的博文:https://cuiqingcai. ...

  9. python爬取网易云音乐歌曲评论信息

    网易云音乐是广大网友喜闻乐见的音乐平台,区别于别的音乐平台的最大特点,除了“它比我还懂我的音乐喜好”.“小清新的界面设计”就是它独有的评论区了——————各种故事汇,各种金句频出.我们可以透过歌曲的评 ...

随机推荐

  1. sublime text 输入法不跟随光标

    1.引子 sublime text 有个BUG,那就是不支持中文的鼠标跟随(和PS类似输入的光标和文字候选框不在一起).如下图: 2.插件 安装IMESupport插件即可插件,这款插件是日本人写的. ...

  2. Tomcat 7优化配置

    Tomcat 的优化不像其它软件那样,简简单单的修改几个参数就可以了,它的优化主要有三方面,分为系统优化,Tomcat 本身的优化,Java 虚拟机(JVM)调优.系统优化就不在介绍了,接下来就详细的 ...

  3. 2018 杭电多校2 - Naive Operations

    题目链接 Problem Description In a galaxy far, far away, there are two integer sequence a and b of length ...

  4. [CQOI2012]交换棋子 网络流

    ---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...

  5. LOJ6368:请让本题永远沉睡于此——题解

    https://loj.ac/problem/6368 给一个分数,求对p=1e9+7取模的值. 给高一同学出的毒瘤模拟题,正好试试给loj传题,竟然过审了,虽然个人觉得很水,但是考试情况来看仅有一人 ...

  6. UVA.548 Tree(二叉树 DFS)

    UVA.548 Tree(二叉树 DFS) 题意分析 给出一棵树的中序遍历和后序遍历,从所有叶子节点中找到一个使得其到根节点的权值最小.若有多个,输出叶子节点本身权值小的那个节点. 先递归建树,然后D ...

  7. bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)

    为了1A我居然写了个暴力对拍... 那个式子本质上是求nk个数里选j个数,且j%k==r的方案数. 所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k].. ...

  8. TYVJ1423 GF和猫咪的玩具

    Description: GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金属环L,猫咪右手(或者 ...

  9. 四连测Day3

    题目链接:https://pan.baidu.com/s/1_vsHfMI_qO-9IDxmFLkHfg 密码: uza8 T1: 小奥的一笔画,判连通性,查奇偶点即可 #include<ios ...

  10. 剑桥offer(11~20)

    11.题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. class Solution { public: int NumberOf1(int n) { ; unsigned ...