分享一个简单的java爬虫框架

反复给网站编写不同的爬虫逻辑太麻烦了,自己实现了一个小框架

可以自定义的部分有:

请求方式(默认为Getuser-agent为谷歌浏览器的设置),可以通过实现RequestSet接口来自定义请求方式

储存方式(默认储存在f盘的html文件夹下),可以通过SaveUtil接口来自定义保存方式

需要保存的资源(默认为整个html页面)

筛选方式(默认所有url都符合要求),通过实现ResourseChooser接口来自定义需要保存的url和资源页面

实现的部分有:

html页面的下载方式,通过HttpClient实现html页面的下载

html页面的解析部分,通过jsoup实现html页面的解析

HtmlDownloader类,用于根据一个url下载一个html页面

package DownloadPackage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/*
 * 根据一个url下载一个html页面
 */
public class HtmlDownloader {
	RequestSet requestset = null;
	public HtmlDownloader(RequestSet requestset){
		this.requestset = requestset;
	}
	public String downloadhtml(String url){
		String html = null;
		//创建一个客户端
		//创建一个读取流从entity读取html
		BufferedReader reader = null;
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpResponse response = null;
		try {
			response = httpclient.execute(requestset.getMethod(url));
			HttpEntity entity = response.getEntity();
			reader = new BufferedReader(new InputStreamReader(entity.getContent()));
			StringBuilder sb = new StringBuilder();
			while((html = reader.readLine()) != null){
				sb.append(html);
			}
			html = sb.toString();
			System.out.println("一个html页面获取成功");
		}
		catch (IOException e) {
			System.out.println(url+"连接失败");
		}
		finally{
			if(reader != null){
				try {
					reader.close();
					httpclient.close();
				}
				catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return html;
	}
}

UrlGet类,用于根据一个html页面获得所有的url连接

package DownloadPackage;
import java.util.LinkedList;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class UrlGet {
	public LinkedList<String> geturls(String html){
		LinkedList<String> urls = new LinkedList<String>();
		Document doc = Jsoup.parse(html);
		Elements links = doc.getElementsByTag("a");
		for (Element link:links){
			String url = link.attr("href");
			urls.add(url);
		}
		return urls;
	}
}

资源选择接口,需要实现三个方法,第一是isNeed方法,判断url是否为需要的,第二个是isResourse方法,判断url页面是不是需要的资源页面,第三个是process方法,

有时网页上的url是我们需要的但是格式不对,对url进行加工

package ChoosePackage;
public interface ResourseChooser {
	public Boolean isNeed(String url);
	public Boolean isResourse(String url);
	public String process(String url);
}

RequsetSet类,用于自定义请求方法的接口,实现getMethod方法获取请求方法

package DownloadPackage;
import org.apache.http.client.methods.HttpGet;
/*
 * 一个用于获得Request请求的接口
 * 实现getMethod方法获取Get方法
 */
public interface RequestSet {
	public HttpGet getMethod(String url);
}
Saveutil接口用于自定义保存方式,需要实现save方法
package SaveUtil;
/*
 * 数据储存的工具接口,必须实现保存方法
 */
public interface SaveUtil {
	public void save(String url,String html);
}

Spider类,有五中构造方法,可以实现多种自定义操作,其中实现了上述自定义接口的默认实现类

package Spider;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import ChoosePackage.MyResourseChooser;
import ChoosePackage.ResourseChooser;
import DownloadPackage.HtmlDownloader;
import DownloadPackage.RequestSet;
import DownloadPackage.UrlGet;
import SaveUtil.MySaveUtil;
import SaveUtil.SaveUtil;
/*
 * 用于爬取资源的类
 */
public class Spider{
	public static void main(String[] args) {
		new Spider("http://www.bilibili.net").spiderstart();
	}
	//种子url
	String seed = null;
	//用于保存数据的类,需要自己实现
	private SaveUtil saveutil = null;
	//html下载类
	private HtmlDownloader downloader = null;
	//url下载类
	private UrlGet urldownloader = null;
	//资源选择工具
	private ResourseChooser resoursechooser = null;
	//用于保存未下载的网页
	LinkedList<String> unvisited = new LinkedList<String>();
	//用于保存已下载的网页
	HashSet<String> visited = new HashSet<String>();
	//自定义储存方式,请求方式,资源筛选方式的构造方法
	public Spider(SaveUtil saveutil,RequestSet request,ResourseChooser resoursechooser,String seed){
		this.saveutil = saveutil;
		this.downloader = new HtmlDownloader(request);
		this.urldownloader = new UrlGet();
		this.resoursechooser = resoursechooser;
		this.seed = seed;
		unvisited.add(seed);
	}
	//自定义储存方式,资源筛选方式的构造方法
	public Spider(SaveUtil saveutil,ResourseChooser resoursechooser,String seed){
		this.resoursechooser = resoursechooser;
		this.downloader = new HtmlDownloader(new getRequest());
		this.saveutil = saveutil;
		this.urldownloader = new UrlGet();
		this.seed = seed;
		unvisited.add(seed);
	}
	//自定义储存方式,请求的构造方法
	public Spider(SaveUtil saveutil,RequestSet requestset,String seed){
		this.saveutil = saveutil;
		this.downloader = new HtmlDownloader(requestset);
		this.resoursechooser = new MyResourseChooser();
		this.urldownloader = new UrlGet();
		this.seed = seed;
		unvisited.add(seed);
	}
	//自定义储存方式的构造方法
	public Spider(SaveUtil saveutil,String seed){
		this.saveutil = saveutil;
		this.downloader = new HtmlDownloader(new getRequest());
		this.resoursechooser = (new MyResourseChooser());
		this.urldownloader = new UrlGet();
		this.seed = seed;
		unvisited.add(seed);
	}
	//默认的爬虫构造方法
	public Spider(String seed){
		this.saveutil = new MySaveUtil();
		this.downloader = new HtmlDownloader(new getRequest());
		this.resoursechooser = (new MyResourseChooser());
		this.urldownloader = new UrlGet();
		this.seed = seed;
		unvisited.add(seed);
	}
	//开始爬取的方法
	private void spiderstart(){
		String html = null;
		while(!unvisited.isEmpty()){
			String url = unvisited.poll();
			System.out.println("开始获取"+url);
			if(resoursechooser.isNeed(url)){
				try{
					html = downloader.downloadhtml(url);
				}
				catch(RuntimeException e){
					System.out.println(url+"连接获取失败");
					continue;
				}
				visited.add(url);
				LinkedList<String> urls = new LinkedList<String>();
				try{
					urls = urldownloader.geturls(html);
				}
				catch(RuntimeException e){
					System.out.println(url+"的html页面为空");
					continue;
				}
				Iterator<String> it = urls.iterator();
				while(it.hasNext()){
					String newurl = it.next();
					if(resoursechooser.isNeed(newurl)&&!visited.contains(newurl)&&!unvisited.contains(newurl)){
						newurl = resoursechooser.process(newurl);
						unvisited.add(newurl);
						System.out.println(newurl+"加入页面");
					}
				}
				System.out.println("获取了"+url+"上的所有url");
				if(resoursechooser.isResourse(url)){
					saveutil.save(url,html);
				}
			}
		}
	}
	//默认资源筛选类
	private class MyResourseChooser implements ResourseChooser{
		@Override
		public Boolean isNeed(String url) {
			// TODO Auto-generated method stub
			if(!url.startsWith("/")&&!url.startsWith("http")){
				return false;
			}
			return true;
		}
		@Override
		public Boolean isResourse(String url) {
			// TODO Auto-generated method stub
			return true;
		}
		@Override
		public String process(String url) {
			// TODO Auto-generated method stub
			if(!url.startsWith("http")){
				url = seed+url;
			}
			return url;
		}
	}
	public class getRequest implements RequestSet{
		public HttpGet getMethod(String url) {
			// TODO Auto-generated method stub
			//创建一个get请求方法
			HttpGet getmethod = new HttpGet(url);
			//HttpHost proxy = new HttpHost("124.88.67.81",80);这里不设置代理IP
			//设置请求超时时间等
			RequestConfig responseconfig = RequestConfig.custom().setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(10000).build();
			//设置请求头,主要是user-agent
			getmethod.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
			//设置请求参数
			getmethod.setConfig(responseconfig);
			return getmethod;
		}
	}
	//默认的存储类
	public class MySaveUtil implements SaveUtil{
		@Override
		public void save(String url, String html) {
			// TODO Auto-generated method stub
			String filename = getfilename(url);
			BufferedWriter writer = null;
			try{
				writer = new BufferedWriter(new FileWriter(filename));
				writer.write(html);
				writer.flush();
				System.out.println("文件写入成功");
			}
			catch(IOException e){
				System.out.println("文件写入失败");
			}
			finally{
				try {
					if(writer != null)
					writer.close();
				}
				catch (IOException e) {
					// TODO Auto-generated catch block
					System.out.println("流关闭失败");
				}
			}
		}
		private String getfilename(String url){
			String fileparentpath = "f://html";
			File file = new File(fileparentpath);
			if(!file.exists()){
				file.mkdir();
			}
			int last = url.lastIndexOf(".");
			int first = url.indexOf(".");
			url = url.substring(first,last);
			url = url.replaceAll("\\.", "");
			url = url.replaceAll("/", "");
			return fileparentpath+"/"+url+".txt";
		}
	}
}

总结

以上就是本文关于分享一个简单的java爬虫框架的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:Python爬虫实例爬取网站搞笑段子、Java线程之锁对象Lock-同步问题更完美的处理方式代码实例、Java编程几个循环实例代码分享等,有什么问题可以随时留言,小编会及时回复大家的。感谢朋友们对本站的支持!

时间: 2017-11-08

Java实现爬虫给App提供数据(Jsoup 网络爬虫)

一.需求 最近基于 Material Design 重构了自己的新闻 App,数据来源是个问题. 有前人分析了知乎日报.凤凰新闻等 API,根据相应的 URL 可以获取新闻的 JSON 数据.为了锻炼写代码能力,笔者打算爬虫新闻页面,自己获取数据构建 API. 二.效果图 下图是原网站的页面 爬虫获取了数据,展示到 APP 手机端 三.爬虫思路 关于App 的实现过程可以参看这几篇文章,本文主要讲解一下如何爬虫数据. Android下录制App操作生成Gif动态图的全过程 :http://www

详解Java豆瓣电影爬虫——小爬虫成长记(附源码)

以前也用过爬虫,比如使用nutch爬取指定种子,基于爬到的数据做搜索,还大致看过一些源码.当然,nutch对于爬虫考虑的是十分全面和细致的.每当看到屏幕上唰唰过去的爬取到的网页信息以及处理信息的时候,总感觉这很黑科技.正好这次借助梳理Spring MVC的机会,想自己弄个小爬虫,简单没关系,有些小bug也无所谓,我需要的只是一个能针对某个种子网站能爬取我想要的信息就可以了.有Exception就去解决,可能是一些API使用不当,也可能是遇到了http请求状态异常,又或是数据库读写有问题,就是在这

一个简易的Java多页面队列爬虫程序

之前写过很多单页面python爬虫,感觉python还是很好用的,这里用java总结一个多页面的爬虫,迭代爬取种子页面的所有链接的页面,全部保存在tmp路径下. 一. 序言 实现这个爬虫需要两个数据结构支持,unvisited队列(priorityqueue:可以适用pagerank等算法计算出url重要度)和visited表(hashset:可以快速查找url是否存在):队列用于实现宽度优先爬取,visited表用于记录爬取过的url,不再重复爬取,避免了环.java爬虫需要的工具包有http

java实现简单的爬虫之今日头条

前言 需要提前说下的是,由于今日头条的文章的特殊性,所以无法直接获取文章的地址,需要获取文章的id然后在拼接成url再访问.下面话不多说了,直接上代码. 示例代码如下 public class Demo2 { public static void main(String[] args) { // 需要爬的网页的文章列表 String url = "http://www.toutiao.com/news_finance/"; //文章详情页的前缀(由于今日头条的文章都是在group这个目

Java爬虫抓取视频网站下载链接

本篇文章抓取目标网站的链接的基础上,进一步提高难度,抓取目标页面上我们所需要的内容并保存在数据库中.这里的测试案例选用了一个我常用的电影下载网站(http://www.80s.la/).本来是想抓取网站上的所有电影的下载链接,后来感觉需要的时间太长,因此改成了抓取2015年电影的下载链接. 一 原理简介 其实原理都跟第一篇文章差不多,不同的是鉴于这个网站的分类列表实在太多,如果不对这些标签加以取舍的话,需要花费的时间难以想象. 分类链接和标签链接都不要,不通过这些链接去爬取其他页面,只通过页底的

Java爬虫实战抓取一个网站上的全部链接

前言:写这篇文章之前,主要是我看了几篇类似的爬虫写法,有的是用的队列来写,感觉不是很直观,还有的只有一个请求然后进行页面解析,根本就没有自动爬起来这也叫爬虫?因此我结合自己的思路写了一下简单的爬虫. 一 算法简介 程序在思路上采用了广度优先算法,对未遍历过的链接逐次发起GET请求,然后对返回来的页面用正则表达式进行解析,取出其中未被发现的新链接,加入集合中,待下一次循环时遍历. 具体实现上使用了Map<String, Boolean>,键值对分别是链接和是否被遍历标志.程序中使用了两个Map集

java 爬虫详解及简单实例

Java爬虫 一.代码 爬虫的实质就是打开网页源代码进行匹配查找,然后获取查找到的结果. 打开网页: URL url = new URL(http://www.cnblogs.com/Renyi-Fan/p/6896901.html); 读取网页内容: BufferedReader bufr = new BufferedReader(new InputStreamReader(url.openStream())); 正则表达式进行匹配: tring mail_regex = "\\w+@\\w+

Java爬虫Jsoup+httpclient获取动态生成的数据

Java爬虫Jsoup+httpclient获取动态生成的数据 前面我们详细讲了一下Jsoup发现这玩意其实也就那样,只要是可以访问到的静态资源页面都可以直接用他来获取你所需要的数据,详情情跳转-Jsoup爬虫详解,但是很多时候网站为了防止数据被恶意爬取做了很多遮掩,比如说加密啊动态加载啊,这无形中给我们写的爬虫程序造成了很大的困扰,那么我们如何来突破这个梗获取我们急需的数据呢, 下面我们来详细讲解一下如何获取 String startPage="https://item.jd.com/1147

详解java爬虫jsoup解析多空格class数据

在使用jsoup爬取其他网站数据的时候,发现class是带空格的多选择,如果直接使用doc.getElementsByClass("class的值"),这种方法获取不到想要的数据. 1.问题描述: 在使用jsoup爬取其他网站数据的时候,发现class是带空格的多选择,如果直接使用doc.getElementsByClass("class的值"),这种方法获取不到想要的数据. 爬取网站页面结构如下: 2.其中文章列表的div为:<div class="

通过抓取淘宝评论为例讲解Python爬取ajax动态生成的数据(经典)

在学习python的时候,一定会遇到网站内容是通过 ajax动态请求.异步刷新生成的json数据 的情况,并且通过python使用之前爬取静态网页内容的方式是不可以实现的,所以这篇文章将要讲述如果在python中爬取ajax动态生成的数据. 至于读取静态网页内容的方式,有兴趣的可以查看本文内容. 这里我们以爬取淘宝评论为例子讲解一下如何去做到的. 这里主要分为了四步: 一 获取淘宝评论时,ajax请求链接(url) 二 获取该ajax请求返回的json数据 三 使用python解析json数据

jQuery获取动态生成的元素示例

需求描述:页面上可以动态添加数据,比如table,点击按钮可以动态添加行.又或页面 加载时table数据是通过ajax从后台获取的.而这时我们想要获取其中的某个值,又该如何获取呢? 如果是要通过某个事件来获取的比如click,mouseover等等,则可以使用live()方法 复制代码 代码如下: $(".button").live("click",function(){ console.info($("#mytd").html()); }) 而

C#获取动态生成的CheckBox值

给你推荐两种方法,一种是向服务器容器控件里添加子控件(即向runat=server的控件的Controls里添加控件),第二种是就是你的这种拼接HTML的方法不过这种方法必须设置控件的name属性,然后在Request.Form["控件的name"]里获得控件的值,推荐使用第一种方法,更直观一些,第二种无法记录提交以后的状态,代码如下 第一种 后台 using System.Web.UI.HtmlControls; protected void Page_Load(object sen

Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

1.需求及配置 需求:爬取京东手机搜索页面的信息,记录各手机的名称,价格,评论数等,形成一个可用于实际分析的数据表格. 使用Maven项目,log4j记录日志,日志仅导出到控制台. Maven依赖如下(pom.xml) <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId>

Java 爬虫工具Jsoup详解

Java 爬虫工具Jsoup详解 Jsoup是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址.HTML 文本内容.它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据. jsoup 的主要功能如下: 1. 从一个 URL,文件或字符串中解析 HTML: 2. 使用 DOM 或 CSS 选择器来查找.取出数据: 3. 可操作 HTML 元素.属性.文本: jsoup 是基于 MIT 协议发布的,可放心使用于商业项目. js

关于动态生成dom绑定事件失效的原因及解决方法

之前做项目都是直接用jquery的bind绑定事件,不过当时都不是动态生成dom元素,而是已经页面中原本存在的dom元素进行事件绑定,最近在测试给动态生成的dom绑定事件的时候发现事件失效,于是就测试了一下: 1. 事件失效的原因: (1)bind事件绑定只对dom中存在的元素有效,对于我们后来动态增加的元素是监测不到,所以绑定不了 (2)同样,当你使用var aa = document.getElementsByTagName("动态生成的元素");来获取动态生成的元素的时候也是获取

AngularJS 获取ng-repeat动态生成的ng-model值实例详解

AngularJS 获取ng-repeat动态生成的ng-model值               最近做项目遇到了ng-model是ng-repeat动态生成的,ng-model="变量",什么变量,是未知的,所以你无法在$scope."变量"取到值,就算取到值也是其中一个值,这样的问题,经过百度一番查找找到解决方案,这里记录下,也行可以帮助到大家. 代码 html <div> <div class="modal-header"

java 动态生成SQL的实例讲解

代码如下: /** * 动态生成SQ及SQL参数L * @param ve 接收到的消息的CHGLIST * @param paramList MQ消息中的SQL参数 * @param t 泛型对象 * @param table 数据表 * @param list 可执行SQL语句集合 * @return */ public <T> String updateSqlAndParamList(Vector<String> ve,List<String> paramList