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

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

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

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}

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

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;}}

java铃声类_java多线程抓取铃声多多官网的铃声数据相关推荐

  1. 学校铃声Java_java_java多线程抓取铃声多多官网的铃声数据,一直想练习下java多线程抓取数 - phpStudy...

    java多线程抓取铃声多多官网的铃声数据 一直想练习下java多线程抓取数据. 有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据. 通过观 ...

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

    一直想练习下java多线程抓取数据. 有天被我发现,铃声多多的官网(http://www.shoujiduoduo.com/main/)有大量的数据. 通过观察他们前端获取铃声数据的ajax http ...

  3. java thread类_Java多线程原理及Thread类详解

    多线程原理 代码如下: 自定义线程类: 测试类: 流程图: 程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建.随着调用mt的对象的start方法,另外一 ...

  4. Node 插件 爬取王者荣耀官网英雄信息,并生成数据库

    文章结构 打开官网看接口地址 打开官网 游戏资料里的英雄资料,并打开后台 接下来是英雄技能 技能结构路径方便抓取 jQ的获取元素这里不细说 重头戏 抓包到到数据库 全部代码 看数据库 总结 打开官网看 ...

  5. JAVA爬取虎嗅网截图_httpclient3+jsoup多线程抓取虎嗅网全部文章

    周六无事生非,一直觉得虎嗅网的文章质量很高,早上醒来突然有个念头想把它的文章都搞下来:花了半个钟头,写了个小程序,jdk6下采用httpclient3.1.线程池ThreadPoolExecutor. ...

  6. 基于Java的网络爬虫实现抓取网络小说(一)

    基于Java的网络爬虫实现抓取网络小说(一) 今天开始写点东西,一方面加深印象一方面再学习. 网络爬虫(Web crawler),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,它们被广泛用 ...

  7. python爬虫代理服务器_Python爬虫多线程抓取代理服务器

    Python作为一门功能强大的脚本语言来说,经常被用来写爬虫程序,下面是Python爬虫多线程抓取代理服务器 首先通过谷歌把包含代理服务器地址的网页查出来,我选择从 http://www.88181. ...

  8. Python 多线程抓取网页 牛人 use raw socket implement http request great

    Python 多线程抓取网页 - 糖拌咸鱼 - 博客园 Python 多线程抓取网页 最近,一直在做网络爬虫相关的东西. 看了一下开源C++写的larbin爬虫,仔细阅读了里面的设计思想和一些关键技术 ...

  9. Python requests 多线程抓取 出现HTTPConnectionPool Max retires exceeded异常

    Python requests 多线程抓取 出现HTTPConnectionPool Max retires exceeded异常 参考文章: (1)Python requests 多线程抓取 出现H ...

最新文章

  1. Java 程序员必备的 15 个框架,前 3 个地位无可动摇!
  2. System Center产品相关开发(1)-SCOM和SCVMM简介
  3. 我的总结SVN的使用
  4. 高级特性(2)- XML
  5. 2019\National _C_C++_B\1.求2019<X<Y ,使2019*2019,X*X,Y*Y组成等差数列且X+Y最小.
  6. MOCTF-Web-还是水题
  7. webpack4 es6转换
  8. 菊长说丨一文读懂MySQL4种事务隔离级别
  9. 基于MapWinGis开发探索(一)
  10. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_06 Properties集合_2_Properties集合中的方法store...
  11. PCIE设备与HOST之间的地址转换
  12. Scratch3.0中文版官方介绍
  13. Java面试 Java简历 Java简历模板
  14. asp.net mvc excel合并单元格_如何用Excel制作一份A4纸可直接打印的拼音田字格模版?...
  15. chloe.mysql 源码_[开源]无sql之旅-Chloe.ORM之增删查改
  16. 推荐几本适合初学者的Java书籍
  17. APP项目开发-需求分析
  18. 虚拟服务器 vmotion,不使用 vMotion 将 VMware 虚拟机从一台主机迁移至另一台主机...
  19. Android手动控制软键盘的开启和关闭,判断软键盘是否显示;
  20. 入门SpringBoot-关于那些静态资源(四)

热门文章

  1. sysAK(青囊)系统运维工具集:如何实现高效自动化运维?| 龙蜥技术
  2. 多中心容灾实践:如何实现真正的异地多活?
  3. 阿里云发布OAMKubernetes标准实现与核心依赖库
  4. 可用性SLA还不懂?看完这个故事就懂了
  5. 实战:基于 Spring 的应用配置如何迁移至阿里云应用配置管理 ACM
  6. 基于MaxCompute搭建社交好友推荐系统
  7. 阿里云MaxCompute印度开服,加速大数据产业升级
  8. Apache RocketMQ 深圳沙龙报名开启!
  9. 啥情况?为什么我的 Service 无法注入进来?
  10. “华为云-东吴杯”圆满成功,顶尖参赛者推动“智造”场景结构升级