java铃声类_java多线程抓取铃声多多官网的铃声数据

一直想练习下java多线程抓取数据。

有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据。

通过观察他们前端获取铃声数据的ajax

431c9f7319ae0a0860e6dfbc055319a8.png

http://www.shoujiduoduo.com/ringweb/ringweb.php?type=getlist&listid={类别ID}&page={分页页码}

很容易就能发现通过改变 listId和page就能从服务器获取铃声的json数据, 通过解析json数据,

可以看到都带有{"hasmore":1,"curpage":1}这样子的指示,通过判断hasmore的值,决定是否进行下一页的抓取。

但是通过上面这个链接返回的json中不带有铃声的下载地址

很快就可以发现,点击页面的“下载”会看到

通过下面的请求,就可以获取铃声的下载地址了

http://www.shoujiduoduo.com/ringweb/ringweb.php?type=geturl&act=down&rid={铃声ID}

431c9f7319ae0a0860e6dfbc055319a8.png

所以,他们的数据是很容易被偷的。于是我就开始...

github:https://github.com/yongbo000/DuoduoAudioRobot

上代码:

package me.yongbo.DuoduoRingRobot;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.URL;

import java.net.URLConnection;

import java.util.Iterator;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import com.google.gson.Gson;

import com.google.gson.JsonArray;

import com.google.gson.JsonElement;

import com.google.gson.JsonParser;

/* * @author yongbo_ * @created 2013/4/16 * * */

public class DuoduoRingRobotClient implements Runnable {

public static String GET_RINGINFO_URL = "http://www.shoujiduoduo.com/ringweb/ringweb.php?type=getlist&listid=%1$d&page=%2$d";

public static String GET_DOWN_URL = "http://www.shoujiduoduo.com/ringweb/ringweb.php?type=geturl&act=down&rid=%1$d";

public static String ERROR_MSG = "listId为 %1$d 的Robot发生错误,已自动停止。当前page为 %2$d";public static String STATUS_MSG = "开始抓取数据,当前listId: %1$d,当前page: %2$d";

public static String FILE_DIR = "E:/RingData/";public static String FILE_NAME = "listId=%1$d.txt";private boolean errorFlag = false;private int listId;private int page;

private int endPage = -1;private int hasMore = 1;

private DbHelper dbHelper;

/** * 构造函数 * @param listId 菜单ID * @param page 开始页码 * @param endPage 结束页码 * */

public DuoduoRingRobotClient(int listId, int beginPage, int endPage)

{this.listId = listId;this.page = beginPage;this.endPage = endPage;this.dbHelper = new DbHelper();}

/** * 构造函数 * @param listId 菜单ID * @param page 开始页码 * */

public DuoduoRingRobotClient(int listId, int page) {this(listId, page, -1);}

/** * 获取铃声 * */public void getRings() {String url = String.format(GET_RINGINFO_URL, listId, page);String responseStr = httpGet(url);hasMore = getHasmore(responseStr);

page = getNextPage(responseStr);

ringParse(responseStr.replaceAll("\\{\"hasmore\":[0-9]*,\"curpage\":[0-9]*\\},", "").replaceAll(",]", "]"));}/** * 发起http请求 * @param webUrl 请求连接地址 * */public String httpGet(String webUrl){URL url;URLConnection conn;StringBuilder sb = new StringBuilder();String resultStr = "";try {url = new URL(webUrl);conn = url.openConnection();conn.connect();InputStream is = conn.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader bufReader = new BufferedReader(isr);String lineText;while ((lineText = bufReader.readLine()) != null) {sb.append(lineText);}resultStr = sb.toString();} catch (Exception e) {errorFlag = true;//将错误写入txtwriteToFile(String.format(ERROR_MSG, listId, page));}return resultStr;}/** * 将json字符串转化成Ring对象,并存入txt中 * @param json Json字符串 * */public void ringParse(String json) {Ring ring = null;JsonElement element = new JsonParser().parse(json);JsonArray array = element.getAsJsonArray();// 遍历数组Iterator it = array.iterator();

Gson gson = new Gson();while (it.hasNext() && !errorFlag) {JsonElement e = it.next();// JsonElement转换为JavaBean对象ring = gson.fromJson(e, Ring.class);ring.setDownUrl(getRingDownUrl(ring.getId()));if(isAvailableRing(ring)) {System.out.println(ring.toString());

//可选择写入数据库还是写入文本//writeToFile(ring.toString());writeToDatabase(ring);}}}

/** * 写入txt * @param data 字符串 * */public void writeToFile(String data)

{String path = FILE_DIR + String.format(FILE_NAME, listId);File dir = new File(FILE_DIR);File file = new File(path);FileWriter fw = null;if(!dir.exists()){dir.mkdirs();

}try {if(!file.exists()){file.createNewFile();}fw = new FileWriter(file, true);

fw.write(data);fw.write("\r\n");fw.flush();} catch (IOException e) {

// TODO Auto-generated catch blocke.printStackTrace();

}finally {try {if(fw != null){fw.close();}} catch (IOException e) {

// TODO Auto-generated catch blocke.printStackTrace();}}}/** * 写入数据库 * @param ring 一个Ring的实例 * */

public void writeToDatabase(Ring ring) {dbHelper.execute("addRing", ring);}

@Overridepublic void run() {while(hasMore == 1 && !errorFlag){if(endPage != -1){if(page > endPage) { break; }}System.out.println(String.format(STATUS_MSG, listId, page));

getRings();System.out.println(String.format("该页数据写入完成"));}System.out.println("ending...");}

private int getHasmore(String resultStr){Pattern p = Pattern.compile("\"hasmore\":([0-9]*),\"curpage\":([0-9]*)");

Matcher match = p.matcher(resultStr);

if (match.find()) { return Integer.parseInt(match.group(1));

} return 0;

}

private int getNextPage(String resultStr){Pattern p = Pattern.compile("\"hasmore\":([0-9]*),\"curpage\":([0-9]*)");Matcher match = p.matcher(resultStr);if (match.find()) {return Integer.parseInt(match.group(2));}return 0;}

/** * 判断当前Ring是否满足条件。当Ring的name大于50个字符或是duration为小数则不符合条件,将被剔除。 * @param ring 当前Ring对象实例 * */private boolean isAvailableRing(Ring ring){Pattern p = Pattern.compile("^[1-9][0-9]*$");

Matcher match = p.matcher(ring.getDuration());

if(!match.find()){return false;}if(ring.getName().length() > 50 || ring.getArtist().length() > 50 || ring.getDownUrl().length() == 0){return false;}return true;}

/** * 获取铃声的下载地址 * @param rid 铃声的id * */

public String getRingDownUrl(String rid){String url = String.format(GET_DOWN_URL, rid);

String responseStr = httpGet(url);return responseStr;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark精华问答 | RDD的核心概念是什么?

Hadoop再火,火得过Spark吗?今天我们继续关于Spark的精华问答吧。1Q:RDD的核心概念是什么?A:Client:客户端进程,负责提交作业到Master。Master:Standalone模式中主控节点,负责接收Cli…

Git 删除命令

文章目录一、Git 分支操作二、Git删除操作一、Git 分支操作 命令说明git branch查看本地分支git branch查看远程分支git branch dev创建dev 分支git checkout -b dev创建dev分支,并切换到新建的dev分支上git checkout master切换到master分支上git merge dev把dev分…

用科技讲好中国历史故事,腾讯携手秦陵“玩儿转”数字化!

戳蓝字“CSDN云计算”关注我们哦!众所周知,秦始皇陵及兵马俑坑一早就被联合国教科文组织批准列入《世界遗产名录》,并同时被誉为“世界第八大奇迹”,逐渐成长为中国古代辉煌文明的一张金字名片。与此同时,近年来秦陵博…

Tomcat10 开机启动 Linux环境

文章目录1. 切换用户2. 编辑3. 赋予权限4. 重启服务器5. 验证1. 切换用户 请切换到root用户执行,普通用户自启动无权限 su - root2. 编辑 vim /etc/rc.d/rc.local# 添加内容 source /etc/profile touch /var/lock/subsys/local /app/apache-tomcat-10.0.10/bin/s…

猫眼java开发暑期实习_校招|猫眼 Android日常实习一面面经

作者:Wwww_来源:牛客网问简历上项目,看我用了GreenDao开源库,问为什么使用这个数据库Java:1. 抽象类和接口,问的很细而且比较灵活。还记得的有:接口中能不能有protected修饰的方法;能…

开源“大地震”下,华为如何复制 Google 模式?

戳蓝字“CSDN云计算”关注我们哦!作者 | 郭芮出品 | CSDN(ID:CSDNnews)回首刚刚过去的五月,注定会给很多技术人留下浓墨重彩的一笔。2018 年 4 月,曾经占据智能手机全球份额第九、美国第四大智能手机供应商…

java 实体类 代码重复_java – JPA两个单向@OneToMany关系到同一个实体导致重复输入...

我目前正在开展一个学校项目,我们必须创建自己的“Twitter”应用程序,并且我在域对象的持久性方面遇到了一些麻烦.我的帐户类(为便于阅读而简化):Entitypublic class Account implements Serializable {IdGeneratedValue(strategy GenerationType.SEQUENCE)private…

Spring精华问答 | 什么是YAML?

Spring框架是一个开源的Java平台,它提供了非常容易,非常迅速地开发健壮的Java应用程序的全面的基础设施支持。今天就让我们一起来看看关于Spring的精华问答吧。1Q:如何在自定义端口上运行Spring Boot应用程序?A:为了在自定义端口上运行Spring…

Sublime Test3 添加一键格式化XML文件插件

文章目录1. 下载地址:2. 快捷键:3. 在线格式化xml json插件1. 下载地址: 下载链接提取码https://pan.baidu.com/s/1zovLp4BCJmreAYe83EionAq0vq 2. 快捷键: 快捷键说明CtrlL选择整行(按住-继续选择下行)C…

java获得jsp的name注解_记录Java注解在JavaWeb中的一个应用实例

概述在学习注解的时候,学了个懵懵懂懂。学了JavaWeb之后,在做Demo项目的过程中,借助注解和反射实现了对页面按钮的权限控制,对于注解才算咂摸出了点味儿来。需求以"角色列表"页面为例,该页面包含"新建&…

企业实战_03_MyCat下载、安装、启动

接上一篇:企业实战_02_MyCat基本元素 https://gblfy.blog.csdn.net/article/details/118770154 Mycat是一个广受好评的数据库中间件,主要应用场景:主从复制、读写分离、垂直拆分、水平扩展、热备、分表分库等。 前言: MyCat基于jd…

微服务的历史与陷阱

戳蓝字“CSDN云计算”关注我们哦!作者 | 李运华出品 | 技术琐话微服务是近几年非常火热的架构设计理念,大部分人认为是MartinFlower提出了微服务概念,但事实上微服务概念的历史要早得多,也不是Martin Flower创造出来的&#xff0c…

mysqldump备份报Binlogging on server not active的解决

文章目录1. 问题现象2. 解决方案1. 问题现象 Redhat 6.5 X64 Mysql 5.7执行备份: [rootmaster 3306]# mysqldump -u root -p --master-data2 --single-transaction -R --triggers -A > all.sql Enter password: mysqldump: Error: Binlogging on server not active2. 解决…

java加锁多线程改为单线程_GUI为什么不设计为多线程(用户事件和底层事件的流程是相反的,每层都加锁效率太低,共用一把锁那就是单线程)...

在我们这批新人转正评审的时候,我师父问了我的小伙伴一个问题:为什么一些更新界面的方法只能在主线程中调用?师父没有问我这个问题,让知其然但不知其所以然的我有种侥幸逃过一难的心情。我想如果回答那是因为Android GUI库是单线程…

行啊,人工智能玩大了!

戳蓝字“CSDN云计算”关注我们哦!是的 ,你没猜错!就是人工智能!AI的炽手可热程度和重要性无需多提。最近,笔者在网上发现了一个报告,报告名字:《BAT人工智能领域人才发展报告》,发现…

Slave is not configured or failed to initialize properly. You must at least set --server-id

一、如果版本不一样请执行以下操作: MySQL 跨版本主从复制时报错:ERROR 1794 (HY000): Slave is not configured or failed to initialize properly. 背景: zabbix 数据库迁移,搭建主从,主是5.6.25,从是5.…

java xml注入bean_Spring实战之通过XML装配bean

尽管Spring长期以来确实与XML有着关联,但现在需要明确的是,XML不再是配置Spring的唯一可选方案。Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了。不过,鉴于已经存在那么多基于XML的Spring配置&…

Docker 存储选型,这些年我们遇到的坑

戳蓝字“CSDN云计算”关注我们哦!技术头条:干货、简洁、多维全面。更多云计算精华知识尽在眼前,get要点、solve难题,统统不在话下!随着Docker 容器技术的不断发展和业内对Docker 的使用不断深入,大家已经不…

mysql主从复制之异常解决--- Slave_IO_Running: NO

关于 Slave_IO_Running: NO 的错误其实有很多原因, 文章目录1. 解决问题的思路2. 异常信息3. 问题定位:由于uuid相同,而导致触发此异常4. 解决方案5. 服务器背景6. 具体解决方案7. 重新启动mysql8. 登录mysql,重启slave&#xff0…

企业实战_11_MyCat垂直拆分相关配置

接上一篇:企业实战_10_MyCat Mysql 主复制总结 https://gblfy.blog.csdn.net/article/details/118652742 文章目录一、准备工作1. 实现思路2. 配置MyCat垂直分库3. 环境配置4. 在master节点创建mycat用户5. 赋予操作数据库权限二、schema.xml文件配置2.1. 基础模板 …