├── .gitignore
├── 5sing.iml
├── README.md
├── build
└── 5sing.war
├── pom.xml
└── src
├── main
├── java
│ └── net
│ │ └── zfeng
│ │ └── sing
│ │ ├── api
│ │ ├── controller
│ │ │ ├── MusicianController.java
│ │ │ ├── SearchController.java
│ │ │ └── SongController.java
│ │ └── service
│ │ │ ├── IMusicianService.java
│ │ │ ├── ISearchService.java
│ │ │ ├── ISongService.java
│ │ │ └── impl
│ │ │ ├── MusicianService.java
│ │ │ ├── SearchService.java
│ │ │ └── SongService.java
│ │ ├── exception
│ │ └── SingDataException.java
│ │ ├── filter
│ │ └── OriginFilter.java
│ │ ├── model
│ │ ├── Musician.java
│ │ ├── MusicianList.java
│ │ ├── ResModel.java
│ │ ├── Song.java
│ │ └── SongList.java
│ │ ├── parser
│ │ ├── IMusicianParser.java
│ │ ├── IParser.java
│ │ ├── ISearchParser.java
│ │ ├── ISongParser.java
│ │ ├── config
│ │ │ ├── SingCategory.java
│ │ │ ├── SingType.java
│ │ │ └── SingUrl.java
│ │ └── impl
│ │ │ ├── MusicianParserImpl.java
│ │ │ ├── ParserImpl.java
│ │ │ ├── SearchParserImpl.java
│ │ │ └── SongParserImpl.java
│ │ └── utils
│ │ └── Conversion.java
├── resources
│ ├── config.properties
│ ├── spring-mvc.xml
│ ├── spring-mybatis.xml
│ └── spring.xml
└── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
└── test
└── net
└── zfeng
└── sing
└── parser
└── ParserTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | target
3 | .DS_Store
4 | 5sing.iml
--------------------------------------------------------------------------------
/5sing.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | file://$MODULE_DIR$/src/main/resources/spring-mvc.xml
22 | file://$MODULE_DIR$/src/main/resources/spring.xml
23 | file://$MODULE_DIR$/src/main/resources/spring-mybatis.xml
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 5singAPI
2 | 已废弃,请使用原生API https://github.com/i5sing/5sing-mobile-api
3 |
4 | ## Usage
5 | ##### header
6 | ```javascript
7 | content-type: 'application/json'
8 | ```
9 |
10 | ### [get]/api/songs
11 |
12 | 获取热门歌曲
13 |
14 | #### query
15 | | key | value | |
16 | | -------------------|:---------------------------------------------:|:----:|
17 | | type(歌曲类型) | yc(原创) fc(翻唱) bz(伴奏) | 必须 |
18 | | category(歌曲类别) | tj(推荐) hx(候选) zj(自荐) zx(最新) hot(热门) | 必须 |
19 | | page(页数) | 数字1-50 | 可选 |
20 |
21 | ####response
22 | ```json
23 | {
24 | "code": "200",
25 | "message": "",
26 | "data": {
27 | "page": 2,
28 | "list": [
29 | {
30 | "id": "3000014",
31 | "name": "【雁引歌】天地神风鉴",
32 | "author": "平纱落雁音乐团队",
33 | "style": "",
34 | "clickNumber": 1471275,
35 | "likeNumber": 179,
36 | "downNumber": 0,
37 | "lrcs": "",
38 | "introduction": "",
39 | "address": ""
40 | }
41 | ]
42 | }
43 | }
44 | ```
45 |
46 | ### [get]/api/songs/:songId
47 |
48 | 获取歌曲详情
49 |
50 | #### query
51 | | key | value | |
52 | | -------------------|:---------------------------------------------:|:----:|
53 | | type(歌曲类型) | yc(原创) fc(翻唱) bz(伴奏) | 必须 |
54 | | page(页数) | 数字1-50 | 可选 |
55 |
56 | #### response
57 | ```json
58 | {
59 | "code": "200",
60 | "message": "",
61 | "data": {
62 | "id": "3014194",
63 | "name": "烟灰",
64 | "author": "三亩地",
65 | "authorImg": "http://img5.5sing.kgimg.com/force/T1sK__Byxv1RXrhCrK_72_72.jpg",
66 | "style": "三亩地",
67 | "clickNumber": 499182,
68 | "likeNumber": 0,
69 | "downNumber": 0,
70 | "lrcs": "烟灰在夜空中飘散,而我已彻底的凌乱,因为又想起你的脸。 还记得单车后的你,像孩子一样的顽皮,那笑容如此的温暖。 穿过繁华落幕的街,独自一人再吃碗面,那味道已不如从前。 惊醒在每一个夜里,我知道已不属于你,就让这梦随风散去。 曾经每个夜里***疯狂,已经变成破碎不堪的幻象。 那些关于争吵对错的执着,已变成孤独后冰冷的呼吸。 不经意间,哭了,所有思念,已变成烈酒,在每个周末狂欢,醉了,依然心痛,在最后一 杯酒中我醒了。 遗忘在角落的相片,用他来点燃这诺言,这样才会好过点。 在没有你睡的房间,点燃一根事后烟,这感觉撕裂我胸膛。 临界在疯狂的边缘,我用力摔碎这思念,让情绪全部发泄。 沉默的我如同死去,在这寂寞的世界里,让我最后一次再爱你。 那些错与对的全部都抛开,让我们享受进入一瞬间。 让这爱与恨全部到达顶点,在这永恒的绝望里回不来。 在爱的顶点,哭了,所有欲望,混合味道,在冰冷的空气里,散了,就这样别了,在最后 的一次疯狂中。",
71 | "introduction": "烟灭了",
72 | "address": "http://data.5sing.kgimg.com/G051/M09/10/1F/04YBAFafJ7OAfPUNAFPj09Dp9pk347.m4a",
73 | "uploadTime": ""
74 | }
75 | }
76 | ```
77 |
78 | ### [get]/api/musicians
79 |
80 | 获取热门音乐人
81 |
82 | #### query
83 | | key | value | |
84 | | -------------------|:---------------------------------------------:|:----:|
85 | | page(页数) | 数字1-50 | 可选 |
86 |
87 | #### response
88 | ```json
89 | {
90 | "code": "200",
91 | "message": "",
92 | "data": {
93 | "page": 1,
94 | "list": [
95 | {
96 | "imgAddress": "http://img9.5sing.kgimg.com/force/T1mkd0BybT1RXrhCrK_75_75.jpg",
97 | "name": "NOVO乐队",
98 | "id": "54228108",
99 | "introduction": ""
100 | }
101 | ]
102 | }
103 | }
104 | ```
105 |
106 | ### [get]/api/songs/space/:userId
107 |
108 | 获取音乐人歌曲
109 |
110 | #### query
111 | | key | value | |
112 | | -------------------|:---------------------------------------------:|:----:|
113 | | type(歌曲类型) | yc(原创) fc(翻唱) bz(伴奏) | 必须 |
114 | | page(页数) | 数字1-50 | 可选 |
115 |
116 | #### response
117 | ```json
118 | {
119 | "code": "200",
120 | "message": "",
121 | "data": {
122 | "page": 0,
123 | "list": [
124 | {
125 | "id": "",
126 | "name": "时光约定【暖暖同人歌】",
127 | "author": "",
128 | "authorImg": "",
129 | "style": "",
130 | "clickNumber": 9563022,
131 | "likeNumber": 0,
132 | "downNumber": 0,
133 | "lrcs": "",
134 | "introduction": "",
135 | "address": "",
136 | "uploadTime": "2014-12-20"
137 | }
138 | ]
139 | }
140 | }
141 | ```
142 |
143 | ### [get]/api/musicians/space/:userId
144 |
145 | 获取音乐人粉丝
146 |
147 | #### query
148 | | key | value | |
149 | | -------------------|:---------------------------------------------:|:----:|
150 | | page(页数) | 数字1-50 | 可选 |
151 |
152 | #### response
153 | ```json
154 | {
155 | "code": "200",
156 | "message": "",
157 | "data": {
158 | "page": 0,
159 | "list": [
160 | {
161 | "imgAddress": "http://static.5sing.kugou.com/images/nan_48.jpg",
162 | "name": "3WT2AHT508",
163 | "id": "54574939",
164 | "introduction": "TA还没有添加简介"
165 | }
166 | ]
167 | }
168 | }
169 | ```
170 |
171 | ### [post]/api/search
172 |
173 | 搜索
174 |
175 | #### body
176 | | key | value | |
177 | | -------------------|:---------------------------------------------:|:----:|
178 | | type | yc(原创) fc(翻唱) bz(伴奏) user(会员) | 可选 |
179 | | key | 搜索关键字 | 可选 |
180 | | page(页数) | 数字1-50 | 可选 |
181 |
182 | #### response
183 | ```json
184 | //songs
185 | {
186 | "code": "200",
187 | "message": "",
188 | "data": {
189 | "page": 1,
190 | "list": [
191 | {
192 | "id": "2493529",
193 | "name": "《14forever》",
194 | "author": "陈美伊",
195 | "authorImg": "",
196 | "style": "",
197 | "clickNumber": 0,
198 | "likeNumber": 0,
199 | "downNumber": 0,
200 | "lrcs": "",
201 | "introduction": "",
202 | "address": "",
203 | "uploadTime": ""
204 | }
205 | ]
206 | }
207 | }
208 |
209 | //users
210 | {
211 | "code": "200",
212 | "message": "",
213 | "data": {
214 | "page": 1,
215 | "list": [
216 | {
217 | "imgAddress": "",
218 | "name": "可心小屋",
219 | "id": "8888383",
220 | "introduction": "我是一个热爱音乐的女孩,1999年2月出生,2010年7月开始课余进行声乐训练。几年来,我陆续录制了..."
221 | }
222 | ]
223 | }
224 | }
225 | ```
226 |
227 | ## Demo
228 |
229 | http://139.129.24.142:8080/5sing/
230 |
--------------------------------------------------------------------------------
/build/5sing.war:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/i5sing/5singAPI/6901dabd059890d5a3ad2f9561ac4050e60986b0/build/5sing.war
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | net.zfeng
5 | 5sing
6 | war
7 | 1.0
8 | 5sing Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | junit
13 | junit
14 | 3.8.1
15 | test
16 |
17 |
18 | javax
19 | javaee-api
20 | 7.0
21 |
22 |
23 |
24 | org.springframework
25 | spring-context
26 | 4.2.4.RELEASE
27 |
28 |
29 | org.springframework
30 | spring-core
31 | 4.2.4.RELEASE
32 |
33 |
34 | org.springframework
35 | spring-beans
36 | 4.2.4.RELEASE
37 |
38 |
39 | org.springframework
40 | spring-web
41 | 4.2.4.RELEASE
42 |
43 |
44 | org.springframework
45 | spring-webmvc
46 | 4.2.4.RELEASE
47 |
48 |
49 | org.springframework
50 | spring-aop
51 | 4.2.4.RELEASE
52 |
53 |
54 | org.springframework
55 | spring-aspects
56 | 4.2.4.RELEASE
57 |
58 |
59 |
60 |
61 |
62 | org.jsoup
63 | jsoup
64 | 1.8.3
65 |
66 |
67 |
68 |
69 |
70 | com.alibaba
71 | fastjson
72 | 1.2.7
73 |
74 |
75 |
76 |
77 |
78 | com.fasterxml.jackson.core
79 | jackson-core
80 | 2.6.5
81 |
82 |
83 | com.fasterxml.jackson.core
84 | jackson-databind
85 | 2.6.5
86 |
87 |
88 |
89 |
90 | 5sing
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/controller/MusicianController.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.controller;
2 |
3 | import net.zfeng.sing.api.service.IMusicianService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.model.Musician;
6 | import net.zfeng.sing.model.MusicianList;
7 | import net.zfeng.sing.model.ResModel;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | import javax.annotation.Resource;
11 | import javax.servlet.http.HttpServletResponse;
12 |
13 | /**
14 | * Created by zhaofeng on 16/2/8.
15 | */
16 | @RestController
17 | @RequestMapping("/musicians")
18 | public class MusicianController {
19 | @Resource
20 | private IMusicianService musicianService;
21 |
22 | @RequestMapping(method = RequestMethod.GET)
23 | public ResModel getSongs(@RequestParam(defaultValue = "1")Integer page, HttpServletResponse response) {
24 | String code = "200";
25 | String message = "";
26 | MusicianList musicianList = null;
27 |
28 | try {
29 | musicianList = musicianService.getMusicians(page);
30 | } catch (SingDataException e) {
31 | code = "400";
32 | message = e.getMessage();
33 | response.setStatus(Integer.parseInt(code));
34 | }
35 |
36 | return new ResModel(code, message, musicianList);
37 | }
38 |
39 | @RequestMapping(method = RequestMethod.GET, value = "/space/{userId:\\d+}")
40 | public ResModel getFuns(
41 | @PathVariable String userId,
42 | @RequestParam(defaultValue = "1") Integer page,
43 | HttpServletResponse response
44 | ) {
45 | String code = "200";
46 | String message = "";
47 | MusicianList musicianList = null;
48 |
49 | try {
50 | musicianList = musicianService.getFuns(userId, page);
51 | } catch (SingDataException e) {
52 | code = "400";
53 | message = e.getMessage();
54 | response.setStatus(Integer.parseInt(code));
55 | }
56 |
57 | return new ResModel(code, message, musicianList);
58 | }
59 |
60 | @RequestMapping(method = RequestMethod.GET, value = "/space/{userId:\\d+}/info")
61 | public ResModel getInfo(@PathVariable String userId, HttpServletResponse response) {
62 | String code = "200";
63 | String message = "";
64 | Musician musician = null;
65 |
66 | try {
67 | musician = musicianService.getInfo(userId);
68 | } catch (SingDataException e) {
69 | code = "400";
70 | message = e.getMessage();
71 | response.setStatus(Integer.parseInt(code));
72 | }
73 |
74 | return new ResModel(code, message, musician);
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/controller/SearchController.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.controller;
2 |
3 | import net.zfeng.sing.api.service.ISearchService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.model.ResModel;
6 | import org.springframework.web.bind.annotation.*;
7 |
8 | import javax.annotation.Resource;
9 | import javax.servlet.http.HttpServletResponse;
10 |
11 | /**
12 | * Created by zhaofeng on 16/2/28.
13 | */
14 | @RestController
15 | @RequestMapping("/search")
16 | public class SearchController {
17 | @Resource
18 | private ISearchService searchService;
19 |
20 | @RequestMapping(method = RequestMethod.POST)
21 | public ResModel search(@RequestBody(required = true) SearchModel searchModel, HttpServletResponse response) {
22 | String code = "200";
23 | String message = "";
24 | Object results = null;
25 |
26 | try {
27 | results = searchService.search(searchModel.getType(), searchModel.getKey(), searchModel.getPage());
28 | } catch (SingDataException e) {
29 | code = "400";
30 | message = e.getMessage();
31 | response.setStatus(Integer.parseInt(code));
32 | }
33 |
34 | return new ResModel(code, message, results);
35 | }
36 | }
37 | /*
38 | * Search Model 不能作为内部类 否则和RequestBody 共同使用报415/400错误.
39 | */
40 | class SearchModel {
41 | private String type;
42 | private String key;
43 | private Integer page = 1;
44 |
45 | public String getType() {
46 | return type;
47 | }
48 |
49 | public void setType(String type) {
50 | this.type = type;
51 | }
52 |
53 | public String getKey() {
54 | return key;
55 | }
56 |
57 | public void setKey(String key) {
58 | this.key = key;
59 | }
60 |
61 | public Integer getPage() {
62 | return page;
63 | }
64 |
65 | public void setPage(Integer page) {
66 | this.page = page;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/controller/SongController.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.controller;
2 |
3 | import net.zfeng.sing.api.service.ISongService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.model.ResModel;
6 | import net.zfeng.sing.model.Song;
7 | import net.zfeng.sing.model.SongList;
8 | import net.zfeng.sing.utils.Conversion;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.annotation.Resource;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 |
15 | /**
16 | * Created by zhaofeng on 16/2/5.
17 | */
18 | @RestController
19 | @RequestMapping("/songs")
20 | public class SongController {
21 | @Resource
22 | private ISongService singService;
23 |
24 | @RequestMapping(method = RequestMethod.GET)
25 | public ResModel getSongs(
26 | @RequestParam(defaultValue = "1") Integer page,
27 | @RequestParam(required = true) String type,
28 | @RequestParam(required = true) String category,
29 | HttpServletResponse response
30 | ) {
31 | String code = "200";
32 | String message = "";
33 | SongList songs = null;
34 |
35 | try {
36 | songs = singService.getSongs(Conversion.convertSingType(type), Conversion.convertSingCategory(category), page);
37 | } catch (SingDataException e) {
38 | code = "400";
39 | message = e.getMessage();
40 | response.setStatus(Integer.parseInt(code));
41 | }
42 |
43 | return new ResModel(code, message, songs);
44 | }
45 |
46 | @RequestMapping(method = RequestMethod.GET, value = "/{songId:\\d+}")
47 | public ResModel getSong(
48 | @RequestParam(required = true) String type,
49 | @PathVariable String songId,
50 | @RequestParam(defaultValue = "1") Integer page,
51 | HttpServletResponse response
52 | ) {
53 | String code = "200";
54 | String message = "";
55 | Song song = null;
56 |
57 | try {
58 | song = singService.getSong(Conversion.convertSingType(type), songId, page);
59 | } catch (SingDataException e) {
60 | code = "400";
61 | message = e.getMessage();
62 | response.setStatus(Integer.parseInt(code));
63 | }
64 |
65 | return new ResModel(code, message, song);
66 | }
67 |
68 | @RequestMapping(method = RequestMethod.GET, value = "/space/{userId:\\d+}")
69 | public ResModel getPersonalSongs(
70 | @RequestParam(required = true) String type,
71 | @PathVariable String userId,
72 | @RequestParam(defaultValue = "1") Integer page,
73 | HttpServletResponse response
74 | ) {
75 | String code = "200";
76 | String message = "";
77 | SongList songs = null;
78 |
79 | try {
80 | songs = singService.getPersonalSongs(userId, Conversion.convertSingType(type), page);
81 | } catch (SingDataException e) {
82 | code = "400";
83 | message = e.getMessage();
84 | response.setStatus(Integer.parseInt(code));
85 | }
86 |
87 | return new ResModel(code, message, songs);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/IMusicianService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Musician;
5 | import net.zfeng.sing.model.MusicianList;
6 |
7 | /**
8 | * Created by zhaofeng on 16/2/8.
9 | */
10 | public interface IMusicianService {
11 |
12 | MusicianList getMusicians(int page) throws SingDataException;
13 |
14 | MusicianList getFuns(String userId, int page) throws SingDataException;
15 |
16 | Musician getInfo(String userId) throws SingDataException;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/ISearchService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.SongList;
5 |
6 | /**
7 | * Created by zhaofeng on 16/2/28.
8 | */
9 | public interface ISearchService {
10 | Object search(String type, String key, int page) throws SingDataException;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/ISongService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.MusicianList;
5 | import net.zfeng.sing.model.Song;
6 | import net.zfeng.sing.model.SongList;
7 | import net.zfeng.sing.parser.config.SingCategory;
8 | import net.zfeng.sing.parser.config.SingType;
9 | import org.springframework.stereotype.Service;
10 |
11 | /**
12 | * Created by zhaofeng on 16/2/5.
13 | */
14 | public interface ISongService {
15 |
16 | SongList getSongs(SingType type, SingCategory category, int page) throws SingDataException;
17 |
18 | Song getSong(SingType type, String songId, int page) throws SingDataException;
19 |
20 | SongList getPersonalSongs(String userId, SingType type, int page) throws SingDataException;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/impl/MusicianService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service.impl;
2 |
3 | import net.zfeng.sing.api.service.IMusicianService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.model.Musician;
6 | import net.zfeng.sing.model.MusicianList;
7 | import net.zfeng.sing.parser.IMusicianParser;
8 | import net.zfeng.sing.parser.impl.MusicianParserImpl;
9 | import org.springframework.stereotype.Service;
10 |
11 | /**
12 | * Created by zhaofeng on 16/2/8.
13 | */
14 | @Service("musicianService")
15 | public class MusicianService implements IMusicianService {
16 | private IMusicianParser parser;
17 |
18 | public MusicianService() {
19 | parser = new MusicianParserImpl();
20 | }
21 |
22 | public MusicianList getMusicians(int page) throws SingDataException {
23 | return parser.getMusicians(page);
24 | }
25 |
26 | public MusicianList getFuns(String userId, int page) throws SingDataException {
27 | return parser.getFuns(userId, page);
28 | }
29 |
30 | public Musician getInfo(String userId) throws SingDataException {
31 | return parser.getUserInfo(userId);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/impl/SearchService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service.impl;
2 |
3 | import net.zfeng.sing.api.service.ISearchService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.parser.ISearchParser;
6 | import net.zfeng.sing.parser.impl.SearchParserImpl;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | * Created by zhaofeng on 16/2/28.
11 | */
12 | @Service("searchService")
13 | public class SearchService implements ISearchService {
14 | private ISearchParser parser;
15 |
16 | public SearchService() {
17 | parser = new SearchParserImpl();
18 | }
19 |
20 | public Object search(String type, String key, int page) throws SingDataException {
21 | if (type.equals("user")) {
22 | return parser.searchUsers(key, page);
23 | }
24 | return parser.searchSongs(type, key, page);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/api/service/impl/SongService.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.api.service.impl;
2 |
3 | import net.zfeng.sing.api.service.ISongService;
4 | import net.zfeng.sing.exception.SingDataException;
5 | import net.zfeng.sing.model.Song;
6 | import net.zfeng.sing.model.SongList;
7 | import net.zfeng.sing.parser.ISongParser;
8 | import net.zfeng.sing.parser.config.SingCategory;
9 | import net.zfeng.sing.parser.config.SingType;
10 | import net.zfeng.sing.parser.impl.SongParserImpl;
11 | import org.springframework.stereotype.Service;
12 |
13 | /**
14 | * Created by zhaofeng on 16/2/5.
15 | */
16 | @Service("songService")
17 | public class SongService implements ISongService {
18 | private ISongParser parser;
19 |
20 | public SongService() {
21 | parser = new SongParserImpl();
22 | }
23 |
24 | public SongList getSongs(SingType type, SingCategory category, int page) throws SingDataException {
25 | return parser.getSongs(type, category, page);
26 | }
27 |
28 | public Song getSong(SingType type, String songId, int page) throws SingDataException {
29 | return parser.getSong(type, page, songId);
30 | }
31 |
32 | public SongList getPersonalSongs(String userId, SingType type, int page) throws SingDataException {
33 | return parser.getPersonalSongs(userId, type, page);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/exception/SingDataException.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.exception;
2 |
3 | /**
4 | * Created by zhaofeng on 16/2/5.
5 | */
6 | public class SingDataException extends Exception {
7 |
8 | public SingDataException(String msg) {
9 | super(msg);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/filter/OriginFilter.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.filter;
2 |
3 | import javax.servlet.*;
4 | import javax.servlet.http.HttpServletResponse;
5 | import java.io.IOException;
6 |
7 | /**
8 | * Created by zhaofeng on 16/2/28.
9 | */
10 | public class OriginFilter implements Filter {
11 | public void init(FilterConfig filterConfig) throws ServletException {
12 |
13 | }
14 |
15 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
16 | HttpServletResponse response = (HttpServletResponse) servletResponse;
17 | response.setHeader("Access-Control-Allow-Origin", "*");
18 | response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
19 |
20 | filterChain.doFilter(servletRequest, servletResponse);
21 | }
22 |
23 | public void destroy() {
24 |
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/model/Musician.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.model;
2 |
3 | /**
4 | * Created by zhaofeng on 16/2/8.
5 | */
6 | public class Musician {
7 | private String imgAddress = "";
8 | private String name = "";
9 | private String id = "";
10 | private String introduction = "";
11 |
12 | public String getIntroduction() {
13 | return introduction;
14 | }
15 |
16 | public void setIntroduction(String introduction) {
17 | this.introduction = introduction;
18 | }
19 |
20 | public String getImgAddress() {
21 | return imgAddress;
22 | }
23 |
24 | public void setImgAddress(String imgAddress) {
25 | this.imgAddress = imgAddress;
26 | }
27 |
28 | public String getName() {
29 | return name;
30 | }
31 |
32 | public void setName(String name) {
33 | this.name = name;
34 | }
35 |
36 | public String getId() {
37 | return id;
38 | }
39 |
40 | public void setId(String id) {
41 | this.id = id;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/model/MusicianList.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.model;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by zhaofeng on 16/2/8.
7 | */
8 | public class MusicianList {
9 | private int page;
10 | private List list;
11 |
12 | public int getPage() {
13 | return page;
14 | }
15 |
16 | public void setPage(int page) {
17 | this.page = page;
18 | }
19 |
20 | public List getList() {
21 | return list;
22 | }
23 |
24 | public void setList(List list) {
25 | this.list = list;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/model/ResModel.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.model;
2 |
3 | /**
4 | * Created by zhaofeng on 16/2/5.
5 | */
6 | public class ResModel {
7 | private String code = "200";
8 | private String message;
9 | private Object data;
10 |
11 | public ResModel() {
12 |
13 | }
14 |
15 | public ResModel(Object data) {
16 | this.data = data;
17 | }
18 |
19 | public ResModel(String code, String message, Object data) {
20 | this.code = code;
21 | this.message = message;
22 | this.data = data;
23 | }
24 |
25 | public String getCode() {
26 | return code;
27 | }
28 |
29 | public void setCode(String code) {
30 | this.code = code;
31 | }
32 |
33 | public String getMessage() {
34 | return message;
35 | }
36 |
37 | public void setMessage(String message) {
38 | this.message = message;
39 | }
40 |
41 | public Object getData() {
42 | return data;
43 | }
44 |
45 | public void setData(Object data) {
46 | this.data = data;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/model/Song.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.model;
2 |
3 | /**
4 | * Created by zhaofeng on 16/2/4.
5 | */
6 | public class Song {
7 | private String id = "";
8 | private String name = "";
9 | private String author = "";
10 | private String authorImg = "";
11 | private String style = "";
12 | private int clickNumber;
13 | private int likeNumber;
14 | private int downNumber;
15 | private String lrcs = "";
16 | private String introduction = "";
17 | private String address = "";
18 | private String uploadTime = "";
19 |
20 | public String getUploadTime() {
21 | return uploadTime;
22 | }
23 |
24 | public void setUploadTime(String uploadTime) {
25 | this.uploadTime = uploadTime;
26 | }
27 |
28 | public String getAuthorImg() {
29 | return authorImg;
30 | }
31 |
32 | public void setAuthorImg(String authorImg) {
33 | this.authorImg = authorImg;
34 | }
35 |
36 | public String getAddress() {
37 | return address;
38 | }
39 |
40 | public void setAddress(String address) {
41 | this.address = address;
42 | }
43 |
44 | public String getId() {
45 | return id;
46 | }
47 |
48 | public void setId(String id) {
49 | this.id = id;
50 | }
51 |
52 | public String getName() {
53 | return name;
54 | }
55 |
56 | public void setName(String name) {
57 | this.name = name;
58 | }
59 |
60 | public String getAuthor() {
61 | return author;
62 | }
63 |
64 | public void setAuthor(String author) {
65 | this.author = author;
66 | }
67 |
68 | public int getClickNumber() {
69 | return clickNumber;
70 | }
71 |
72 | public void setClickNumber(int clickNumber) {
73 | this.clickNumber = clickNumber;
74 | }
75 |
76 | public int getLikeNumber() {
77 | return likeNumber;
78 | }
79 |
80 | public void setLikeNumber(int likeNumber) {
81 | this.likeNumber = likeNumber;
82 | }
83 |
84 | public int getDownNumber() {
85 | return downNumber;
86 | }
87 |
88 | public void setDownNumber(int downNumber) {
89 | this.downNumber = downNumber;
90 | }
91 |
92 | public String getLrcs() {
93 | return lrcs;
94 | }
95 |
96 | public void setLrcs(String lrcs) {
97 | this.lrcs = lrcs;
98 | }
99 |
100 | public String getIntroduction() {
101 | return introduction;
102 | }
103 |
104 | public void setIntroduction(String introduction) {
105 | this.introduction = introduction;
106 | }
107 |
108 | public String getStyle() {
109 | return style;
110 | }
111 |
112 | public void setStyle(String style) {
113 | this.style = style;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/model/SongList.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.model;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by zhaofeng on 16/2/5.
7 | */
8 | public class SongList {
9 | private int page;
10 | private List list;
11 |
12 | public int getPage() {
13 | return page;
14 | }
15 |
16 | public void setPage(int page) {
17 | this.page = page;
18 | }
19 |
20 | public List getList() {
21 | return list;
22 | }
23 |
24 | public void setList(List list) {
25 | this.list = list;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/IMusicianParser.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Musician;
5 | import net.zfeng.sing.model.MusicianList;
6 |
7 | /**
8 | * Created by zhaofeng on 4/22/16.
9 | */
10 | public interface IMusicianParser extends IParser {
11 | MusicianList getMusicians(int page) throws SingDataException;
12 |
13 | MusicianList getFuns(String userId, int page) throws SingDataException;
14 |
15 | Musician getUserInfo(String userId) throws SingDataException;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/IParser.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Musician;
5 | import net.zfeng.sing.model.MusicianList;
6 | import net.zfeng.sing.model.Song;
7 | import net.zfeng.sing.model.SongList;
8 | import net.zfeng.sing.parser.config.SingCategory;
9 | import net.zfeng.sing.parser.config.SingType;
10 |
11 | /**
12 | * Created by zhaofeng on 16/2/4.
13 | */
14 | public interface IParser {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/ISearchParser.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.MusicianList;
5 | import net.zfeng.sing.model.SongList;
6 |
7 | /**
8 | * Created by zhaofeng on 4/22/16.
9 | */
10 | public interface ISearchParser extends IParser {
11 |
12 | SongList searchSongs(String type, String key, int page) throws SingDataException;
13 |
14 | MusicianList searchUsers(String key, int page) throws SingDataException;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/ISongParser.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Song;
5 | import net.zfeng.sing.model.SongList;
6 | import net.zfeng.sing.parser.config.SingCategory;
7 | import net.zfeng.sing.parser.config.SingType;
8 |
9 | /**
10 | * Created by zhaofeng on 4/22/16.
11 | */
12 | public interface ISongParser extends IParser {
13 | SongList getSongs(SingType type, SingCategory category, int page) throws SingDataException;
14 |
15 | Song getSong(SingType type, int page, String songId) throws SingDataException;
16 |
17 | SongList getPersonalSongs(String authorId, SingType type, int page) throws SingDataException;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/config/SingCategory.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.config;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by zhaofeng on 16/2/5.
8 | */
9 | public enum SingCategory {
10 | TUIJIAN("tj"),
11 | HOUXUAN("hx"),
12 | ZIJIAN("zj"),
13 | ZUIXIN("zx"),
14 | HOT("hot");
15 |
16 | private String text;
17 |
18 | SingCategory(String text) {
19 | this.text = text;
20 | }
21 |
22 | public String getText() {
23 | return this.text;
24 | }
25 |
26 | // Implementing a fromString method on an enum type
27 | private static final Map stringToEnum = new HashMap();
28 |
29 | static {
30 | // Initialize map from constant name to enum constant
31 | for (SingCategory category : values()) {
32 | stringToEnum.put(category.toString(), category);
33 | }
34 | }
35 |
36 | // Returns Blah for string, or null if string is invalid
37 | public static SingCategory fromString(String symbol) {
38 | return stringToEnum.get(symbol);
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return text;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/config/SingType.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.config;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by zhaofeng on 16/2/5.
8 | */
9 | public enum SingType {
10 | YUANCHUANG("yc"),
11 | FANCHANG("fc"),
12 | BANZOU("bz");
13 |
14 | private String text;
15 |
16 | SingType(String text) {
17 | this.text = text;
18 | }
19 |
20 | public String getText() {
21 | return this.text;
22 | }
23 |
24 | // Implementing a fromString method on an enum type
25 | private static final Map stringToEnum = new HashMap();
26 |
27 | static {
28 | // Initialize map from constant name to enum constant
29 | for (SingType type : values()) {
30 | stringToEnum.put(type.toString(), type);
31 | }
32 | }
33 |
34 | // Returns Blah for string, or null if string is invalid
35 | public static SingType fromString(String symbol) {
36 | return stringToEnum.get(symbol);
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return text;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/config/SingUrl.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.config;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * Created by zhaofeng on 16/2/5.
8 | */
9 | public enum SingUrl {
10 | SONG_LIST("http://5sing.kugou.com/m/list/{type}-{category}-{page}.html"),
11 | SONG_DETAIL("http://5sing.kugou.com/m/detail/{type}-{songId}-{page}.html"),
12 | MUSICIAN_HOT("http://5sing.kugou.com/m/list/musician-hot-{page}.html"),
13 | AUTHOR_SONG_LIST("http://5sing.kugou.com/m/space/mysongs/{authorId}-{type}-{page}.html"),
14 | AUTHOR_FUNS("http://5sing.kugou.com/m/space/fans/{authorId}-{page}.html"),
15 | AUTHOR_INFO("http://5sing.kugou.com/m/space/{authorId}.html"),
16 | SEARCH("http://5sing.kugou.com/m/search.html?type={type}&key={key}&p={page}");
17 |
18 | private String text;
19 |
20 | SingUrl(String text) {
21 | this.text = text;
22 | }
23 |
24 | public String getText() {
25 | return this.text;
26 | }
27 |
28 | // Implementing a fromString method on an enum type
29 | private static final Map stringToEnum = new HashMap();
30 |
31 | static {
32 | // Initialize map from constant name to enum constant
33 | for (SingUrl url : values()) {
34 | stringToEnum.put(url.toString(), url);
35 | }
36 | }
37 |
38 | // Returns Blah for string, or null if string is invalid
39 | public static SingUrl fromString(String symbol) {
40 | return stringToEnum.get(symbol);
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return text;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/impl/MusicianParserImpl.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.impl;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Musician;
5 | import net.zfeng.sing.model.MusicianList;
6 | import net.zfeng.sing.parser.IMusicianParser;
7 | import net.zfeng.sing.parser.config.SingUrl;
8 | import org.jsoup.nodes.Document;
9 | import org.jsoup.nodes.Element;
10 | import org.jsoup.select.Elements;
11 |
12 | import java.io.IOException;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 | import java.util.regex.Matcher;
16 | import java.util.regex.Pattern;
17 |
18 | /**
19 | * Created by zhaofeng on 4/22/16.
20 | */
21 | public class MusicianParserImpl extends ParserImpl implements IMusicianParser{
22 | /**
23 | * 获取热门歌手列表
24 | *
25 | * @param page
26 | * @return
27 | */
28 | public MusicianList getMusicians(int page) throws SingDataException {
29 | MusicianList musicianList = new MusicianList();
30 | List musicians = new ArrayList();
31 | Pattern userIdPattern = Pattern.compile(UserIdRE);
32 |
33 | try {
34 | Document doc = parserHTML(SingUrl.MUSICIAN_HOT.getText().replace("{page}", page + ""));
35 | Elements imgEls = doc.getElementById("photolist").getElementsByTag("a");
36 | int i = -1;
37 | while (i++ < imgEls.size() - 1) {
38 | Element imgEl = imgEls.get(i);
39 | Matcher userIdMatcher = userIdPattern.matcher(imgEl.attr("href"));
40 |
41 | Musician musician = new Musician();
42 |
43 | if (userIdMatcher.find() && userIdMatcher.group().length() > 1) {
44 | musician.setId(userIdMatcher.group(1));
45 | }
46 |
47 | musician.setName(imgEl.getElementsByTag("span").get(0).text());
48 | musician.setImgAddress(imgEl.getElementsByTag("img").get(0).attr("src"));
49 | musicians.add(musician);
50 | }
51 | } catch (IOException e) {
52 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
53 | }
54 |
55 | musicianList.setList(musicians);
56 | musicianList.setPage(page);
57 | return musicianList;
58 | }
59 |
60 | /**
61 | * 获取个人粉丝
62 | *
63 | * @param userId
64 | * @param page
65 | * @return
66 | * @throws SingDataException
67 | */
68 | public MusicianList getFuns(String userId, int page) throws SingDataException {
69 | MusicianList musicianList = new MusicianList();
70 | List musicians = new ArrayList();
71 | String url = SingUrl.AUTHOR_FUNS.getText().replace("{authorId}", userId).replace("{page}", page + "");
72 | Pattern userIdPattern = Pattern.compile(UserIdRE);
73 |
74 | try {
75 | Document doc = parserHTML(url);
76 | Elements funEls = doc.getElementsByClass("m_fans").get(0).getElementsByTag("li");
77 | int i = -1;
78 | while (i++ < funEls.size() - 1) {
79 | Element funEl = funEls.get(i);
80 | Musician musician = new Musician();
81 |
82 | String img = funEl.getElementsByTag("img").get(0).attr("src");
83 | String name = funEl.getElementsByTag("h6").get(0).ownText();
84 | String introduction = funEl.getElementsByTag("p").get(0).text();
85 | String hrefVal = funEl.getElementsByTag("a").get(0).attr("href");
86 | Matcher userIdMatcher = userIdPattern.matcher(hrefVal);
87 |
88 | if (userIdMatcher.find() && userIdMatcher.group().length() > 1) {
89 | musician.setId(userIdMatcher.group(1));
90 | }
91 | musician.setImgAddress(img);
92 | musician.setName(name);
93 | musician.setIntroduction(introduction);
94 |
95 | musicians.add(musician);
96 | }
97 |
98 | musicianList.setList(musicians);
99 | } catch (IOException e) {
100 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
101 | }
102 | return musicianList;
103 | }
104 |
105 | /**
106 | * 获取用户信息
107 | *
108 | * @param userId
109 | * @return
110 | * @throws SingDataException
111 | */
112 | public Musician getUserInfo(String userId) throws SingDataException {
113 | Musician musician = new Musician();
114 | String url = SingUrl.AUTHOR_INFO.getText().replace("{authorId}", userId);
115 |
116 | try {
117 | Document doc = parserHTML(url);
118 | Element element = doc.getElementsByClass("my_5sing").get(0);
119 | Element imgEl = element.getElementsByTag("img").get(0);
120 | Element introductionEl = element.getElementsByTag("ul").get(0).getElementsByTag("li").get(0);
121 | String name = doc.getElementsByTag("title").get(0).text().split("的")[0];
122 |
123 | musician.setName(name);
124 | musician.setId(userId);
125 | musician.setImgAddress(imgEl.attr("src"));
126 | musician.setIntroduction(introductionEl.text());
127 | } catch (IOException e) {
128 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
129 | }
130 | return musician;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/impl/ParserImpl.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.impl;
2 |
3 | import net.zfeng.sing.parser.IParser;
4 | import org.jsoup.Jsoup;
5 | import org.jsoup.nodes.Document;
6 |
7 | import java.io.IOException;
8 |
9 | /**
10 | * Created by zhaofeng on 16/2/4.
11 | */
12 | public class ParserImpl implements IParser {
13 | protected static String SingIdRE = "^/m/detail/\\w+-([0-9]+)-\\d+.html$";
14 | protected static String UserIdRE = "^/m/space/([0-9]+).html$";
15 |
16 | /**
17 | * 加载并解析指定url的html
18 | *
19 | * @param url
20 | * @return
21 | * @throws IOException
22 | */
23 | protected Document parserHTML(String url) throws IOException {
24 | return Jsoup.connect(url).get();
25 | }
26 |
27 | /**
28 | * 删除html中的其他字符
29 | *
30 | * @param str
31 | * @return
32 | */
33 | protected String deleteExtraChar(String str) {
34 | return str.replaceAll(" ", "").replaceAll(",", "").replaceAll("
", "").replaceAll(" ", "");
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/impl/SearchParserImpl.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.impl;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Musician;
5 | import net.zfeng.sing.model.MusicianList;
6 | import net.zfeng.sing.model.Song;
7 | import net.zfeng.sing.model.SongList;
8 | import net.zfeng.sing.parser.ISearchParser;
9 | import net.zfeng.sing.parser.config.SingUrl;
10 | import org.jsoup.nodes.Document;
11 | import org.jsoup.nodes.Element;
12 | import org.jsoup.select.Elements;
13 |
14 | import java.io.IOException;
15 | import java.io.UnsupportedEncodingException;
16 | import java.net.URLEncoder;
17 | import java.util.ArrayList;
18 | import java.util.List;
19 | import java.util.regex.Matcher;
20 | import java.util.regex.Pattern;
21 |
22 | /**
23 | * Created by zhaofeng on 4/22/16.
24 | */
25 | public class SearchParserImpl extends ParserImpl implements ISearchParser{
26 | /**
27 | * 搜索
28 | *
29 | * @param type
30 | * @param key
31 | * @param page
32 | * @return
33 | * @throws SingDataException
34 | */
35 | public SongList searchSongs(String type, String key, int page) throws SingDataException {
36 | List songs = new ArrayList();
37 | SongList songList = new SongList();
38 | String url = "";
39 | try {
40 | url = SingUrl.SEARCH.getText().replace("{type}", type).replace("{key}", URLEncoder.encode(key, "UTF-8")).replace("{page}", page + "");
41 | } catch (UnsupportedEncodingException e) {
42 | throw new SingDataException("encode error \n" + e.getMessage());
43 | }
44 | Pattern pattern = Pattern.compile(SingIdRE);
45 |
46 | try {
47 | Document doc = parserHTML(url);
48 | Element songListEl = doc.getElementsByClass("list_items").get(0);
49 | Elements songEls = songListEl.getElementsByTag("li");
50 | int i = -1;
51 |
52 | while (i++ < songEls.size() - 1) {
53 | Element songEl = songEls.get(i);
54 | String href = songEl.getElementsByTag("a").get(0).attr("href");
55 | String name = songEl.getElementsByTag("h4").get(0).ownText();
56 | String author = songEl.getElementsByTag("strong").get(0).text();
57 | Matcher matcher = pattern.matcher(href);
58 |
59 | Song song = new Song();
60 | song.setName(name);
61 | song.setAuthor(author);
62 |
63 | if (matcher.find() && matcher.group().length() > 1) {
64 | song.setId(matcher.group(1));
65 | }
66 |
67 | songs.add(song);
68 | }
69 | } catch (IOException e) {
70 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
71 | }
72 |
73 | songList.setPage(page);
74 | songList.setList(songs);
75 | return songList;
76 | }
77 |
78 | public MusicianList searchUsers(String key, int page) throws SingDataException {
79 | MusicianList musicianList = new MusicianList();
80 | List musicians = new ArrayList();
81 | String url = "";
82 | try {
83 | url = SingUrl.SEARCH.getText().replace("{type}", "user").replace("{key}", URLEncoder.encode(key, "UTF-8")).replace("{page}", page + "");
84 | } catch (UnsupportedEncodingException e) {
85 | throw new SingDataException("encode error \n" + e.getMessage());
86 | }
87 | Pattern userIdPattern = Pattern.compile(UserIdRE);
88 |
89 | try {
90 | Document doc = parserHTML(url);
91 | Element userListEl = doc.getElementsByClass("m_fans").get(0);
92 | Elements userEls = userListEl.getElementsByTag("li");
93 | int i = -1;
94 |
95 | while (i++ < userEls.size() - 1) {
96 | Element user = userEls.get(i);
97 | String href = user.getElementsByTag("a").get(0).attr("href");
98 | String name = user.getElementsByTag("h6").get(0).text();
99 | String introduction = user.getElementsByTag("p").get(0).text();
100 | Matcher userIdMatcher = userIdPattern.matcher(href);
101 |
102 | Musician musician = new Musician();
103 |
104 | musician.setName(name);
105 | musician.setIntroduction(introduction);
106 |
107 | if (userIdMatcher.find() && userIdMatcher.group().length() > 1) {
108 | musician.setId(userIdMatcher.group(1));
109 | }
110 |
111 | musicians.add(musician);
112 | }
113 | } catch (IOException e) {
114 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
115 | }
116 |
117 | musicianList.setPage(page);
118 | musicianList.setList(musicians);
119 | return musicianList;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/parser/impl/SongParserImpl.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.parser.impl;
2 |
3 | import net.zfeng.sing.exception.SingDataException;
4 | import net.zfeng.sing.model.Song;
5 | import net.zfeng.sing.model.SongList;
6 | import net.zfeng.sing.parser.ISongParser;
7 | import net.zfeng.sing.parser.config.SingCategory;
8 | import net.zfeng.sing.parser.config.SingType;
9 | import net.zfeng.sing.parser.config.SingUrl;
10 | import org.jsoup.nodes.Document;
11 | import org.jsoup.nodes.Element;
12 | import org.jsoup.select.Elements;
13 |
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | /**
21 | * Created by zhaofeng on 4/22/16.
22 | */
23 | public class SongParserImpl extends ParserImpl implements ISongParser {
24 | /**
25 | * 获取5sing歌曲列表
26 | *
27 | * @param page
28 | * @param type
29 | * @param category
30 | * @return
31 | */
32 | public SongList getSongs(SingType type, SingCategory category, int page) throws SingDataException {
33 | List songs = new ArrayList();
34 | SongList songList = new SongList();
35 | Pattern pattern = Pattern.compile(SingIdRE);
36 |
37 | String url = SingUrl.SONG_LIST.getText()
38 | .replace("{type}", type.getText())
39 | .replace("{category}", category.getText())
40 | .replace("{page}", page + "");
41 |
42 | try {
43 | Document doc = parserHTML(url);
44 | Elements songListEl = doc.getElementById("yc_list_tj").getElementsByTag("li");
45 | int i = -1;
46 | while (i++ < songListEl.size() - 1) {
47 | Element songEl = songListEl.get(i);
48 | Element nameEl = songEl.getElementsByTag("h4").get(0);
49 | Element authorEl = nameEl.getElementsByTag("strong").size() > 0 ? nameEl.getElementsByTag("strong").get(0) : null;
50 | Elements otherEls = songEl.getElementsByTag("span");
51 | String hrefVal = songEl.getElementsByTag("a").get(1).attr("href");
52 |
53 | Matcher matcher = pattern.matcher(hrefVal);
54 |
55 | Song song = new Song();
56 |
57 | if (authorEl != null) {
58 | song.setAuthor(authorEl.text());
59 |
60 | //删除歌曲名字中的作者信息
61 | authorEl.remove();
62 | }
63 |
64 | if (matcher.find() && matcher.group().length() > 1) {
65 | song.setId(matcher.group(1));
66 | }
67 |
68 | song.setName(nameEl.text());
69 |
70 | if (otherEls.size() > 1) {
71 | int clickNumber = Integer.parseInt(deleteExtraChar(otherEls.get(0).text()).split(":")[1]);
72 | int likeNumber = Integer.parseInt(deleteExtraChar(otherEls.get(1).text()).split(":")[1]);
73 | song.setClickNumber(clickNumber);
74 | song.setLikeNumber(likeNumber);
75 | }
76 |
77 | songs.add(song);
78 | }
79 | } catch (IOException e) {
80 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
81 | }
82 | songList.setList(songs);
83 | songList.setPage(page);
84 | return songList;
85 | }
86 |
87 | /**
88 | * 获取歌曲详情
89 | *
90 | * @param type
91 | * @param page
92 | * @param songId
93 | * @return
94 | */
95 | public Song getSong(SingType type, int page, String songId) throws SingDataException {
96 | Song song = new Song();
97 |
98 | String url = SingUrl.SONG_DETAIL.getText()
99 | .replace("{type}", type.getText())
100 | .replace("{songId}", songId)
101 | .replace("{page}", page + "");
102 |
103 | try {
104 | Document doc = parserHTML(url);
105 | System.out.print(doc);
106 | Element headEl = doc.getElementsByClass("cd-wrap").get(0).getElementsByTag("img").get(0);
107 | Elements infoEls = doc.getElementsByClass("info-wrap").get(0).getElementsByTag("p");
108 | Element mp3El = doc.getElementsByClass("play").get(0);
109 | Element lrcEl = doc.getElementsByClass("lrc-wrap").get(0);
110 |
111 | song.setId(songId);
112 | song.setName(infoEls.get(0).text());
113 | song.setAddress(mp3El.attr("data-songinfo").split(",")[0]);
114 | song.setLrcs(lrcEl.text());
115 |
116 | String author = deleteExtraChar(infoEls.get(1).text());
117 | song.setAuthorImg(headEl.attr("src"));
118 | song.setAuthor(author);
119 | } catch (IOException e) {
120 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
121 | }
122 |
123 | return song;
124 | }
125 |
126 | /**
127 | * 获取个人歌曲列表
128 | *
129 | * @param authorId
130 | * @param type
131 | * @param page
132 | * @return
133 | * @throws SingDataException
134 | */
135 | public SongList getPersonalSongs(String authorId, SingType type, int page) throws SingDataException {
136 | List songs = new ArrayList();
137 | SongList songList = new SongList();
138 | Pattern pattern = Pattern.compile(SingIdRE);
139 |
140 | String url = SingUrl.AUTHOR_SONG_LIST.getText()
141 | .replace("{authorId}", authorId)
142 | .replace("{type}", type.getText())
143 | .replace("{page}", page + "");
144 |
145 | try {
146 | Document doc = parserHTML(url);
147 | Elements songsEl = doc.getElementsByClass("list_items").get(0).getElementsByTag("li");
148 | int i = -1;
149 | while (i++ < songsEl.size() - 1) {
150 | Element songEl = songsEl.get(i);
151 |
152 | if (songEl.getElementsByTag("strong").size() == 0)
153 | throw new SingDataException("该音乐人未进行实名认证, 无法获取数据.");
154 |
155 | Song song = new Song();
156 |
157 | Element infoEl = songEl.getElementsByTag("strong").get(0);
158 | String hrefVal = songEl.getElementsByTag("a").get(0).attr("href");
159 | String infos = infoEl.text();
160 |
161 | String name = songEl.getElementsByTag("h4").get(0).ownText();
162 |
163 | Matcher matcher = pattern.matcher(hrefVal);
164 |
165 | if (matcher.find() && matcher.group().length() > 1) {
166 | song.setId(matcher.group(1));
167 | }
168 |
169 | song.setName(name);
170 | song.setClickNumber(Integer.parseInt(infos.split(" ")[0].split(":")[1]));
171 | song.setUploadTime(infos.split(" ")[1].split(":")[1]);
172 |
173 | songs.add(song);
174 | }
175 | songList.setList(songs);
176 | } catch (IOException e) {
177 | throw new SingDataException("从五婶获取数据失败\n" + e.getMessage());
178 | }
179 | return songList;
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/src/main/java/net/zfeng/sing/utils/Conversion.java:
--------------------------------------------------------------------------------
1 | package net.zfeng.sing.utils;
2 |
3 | import net.zfeng.sing.parser.config.SingCategory;
4 | import net.zfeng.sing.parser.config.SingType;
5 |
6 | /**
7 | * Created by zhaofeng on 16/2/5.
8 | */
9 | public class Conversion {
10 | public static SingType convertSingType(String type) {
11 | SingType mType = SingType.YUANCHUANG;
12 |
13 | if (type.equals("yc")) {
14 | mType = SingType.YUANCHUANG;
15 | } else if (type.equals("fc")) {
16 | mType = SingType.FANCHANG;
17 | } else if (type.equals("bz")) {
18 | mType = SingType.BANZOU;
19 | }
20 |
21 | return mType;
22 | }
23 |
24 | public static SingCategory convertSingCategory(String category) {
25 | SingCategory mCategory = SingCategory.TUIJIAN;
26 |
27 | if (category.equals("tj")) {
28 | mCategory = SingCategory.TUIJIAN;
29 | } else if (category.equals("hx")) {
30 | mCategory = SingCategory.HOUXUAN;
31 | } else if (category.equals("zj")) {
32 | mCategory = SingCategory.ZIJIAN;
33 | } else if (category.equals("hot")) {
34 | mCategory = SingCategory.HOT;
35 | }
36 |
37 | return mCategory;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/resources/config.properties:
--------------------------------------------------------------------------------
1 | hibernate.dialect=org.hibernate.dialect.OracleDialect
2 | driverClassName=oracle.jdbc.driver.OracleDriver
3 | validationQuery=SELECT 1 FROM DUAL
4 | jdbc_url=jdbc:oracle:thin:@localhost:1521:orcl
5 | jdbc_username=feng
6 | jdbc_password=zhaofeng
--------------------------------------------------------------------------------
/src/main/resources/spring-mvc.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/main/resources/spring-mybatis.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/main/resources/spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
9 | contextConfigLocation
10 | classpath:spring.xml,classpath:spring-mybatis.xml
11 |
12 |
13 |
14 | encodingFilter
15 | org.springframework.web.filter.CharacterEncodingFilter
16 |
17 | encoding
18 | UTF-8
19 |
20 |
21 |
22 | encodingFilter
23 | /*
24 |
25 |
26 |
27 | OriginFilter
28 | net.zfeng.sing.filter.OriginFilter
29 |
30 |
31 |
32 |
33 | OriginFilter
34 |
35 | /*
36 |
37 |
38 |
39 | spring listener
40 | org.springframework.web.context.ContextLoaderListener
41 |
42 |
43 |
44 | spring mvc servlet
45 | springmvc
46 | org.springframework.web.servlet.DispatcherServlet
47 |
48 | springmvc config
49 | contextConfigLocation
50 | classpath:spring-mvc.xml
51 |
52 | 1
53 |
54 |
55 | springmvc
56 | /api/*
57 |
58 |
59 |
60 | index.html
61 | index.htm
62 | index.jsp
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@page pageEncoding="utf-8" %>
2 |
3 |
4 |
5 |
6 |
7 | 中国原创音乐基地5SING第三方API
8 |
9 |