使用HttpClient和Jsoup实现一个简单爬虫

一直很想了解一下爬虫这个东西的,彻底是出于兴趣,其实刚开始是准备用python的,可是因为种种缘由选择了java,此处省略不少字... 总之,若是你想作一件事情的话就尽快去作吧,千万不要把战线拉得太长了,不然时间一长其实发现本身什么都没作... 拖延症就是这样慢慢造成了。html

在写一个爬虫之前须要了解一下HTTP协议的,一般的B/S程序都是客户端请求、服务端响应这种模式,经过一个URL就能从服务器上请求到一些信息。而爬虫就是用程序实现了这个过程,用程序发起一个HTTP请求,而后接收服务端的响应结果,而后就从这些响应中抽取出你想要的信息。这里介绍了使用HttpClient和Jsoup编写的一个网络爬虫,爬取了http://jandan.net/上的一些图片,而且把图片保存到本地。java

HttpClientnode

官网地址:http://hc.apache.org/httpclient-3.x/  这是apache上的一个项目,主要做用是发起一个Http请求,而且接收响应,而且能够设置超时时间,比传统Java中的API要方便不少。python

Jsoupgit

官网地址:https://jsoup.org/ 虽然这是官方地址,可是倒是英文的,推荐看这里http://www.open-open.com/jsoup/ 这里是中文的文档,看这里就足够使用这个工具了,主要用于解析响应的html,可是也可使用Jsoup发起一个http请求,可是功能没有HttpClient强大。全部通常是用HttpClient请求,Jsoup解析。github

包含的jar包:apache

jsoup-1.7.2.jar服务器

commons-logging-1.1.3.jar网络

httpclient-4.5.3.jaride

httpcore-4.4.6.jar

直接上代码吧:这基本上是一个通用的类了,给定一个URL返回一个请求响应的html,而且设置了请求超时的参数。

package spider.img.service;

import org.apache.http.client.config.RequestConfig;
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.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

/**
 * 2017-5-17 基础类,经过URL返回一个响应的html
 * 
 * @author tom
 */
public class AbstractSpider {

    public static String getResult(String url) throws Exception {
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();
                CloseableHttpResponse response = httpClient.execute(new HttpGetConfig(url))) {
            String result = EntityUtils.toString(response.getEntity());
            return result;
        } catch (Exception e) {
            System.out.println("获取失败");
            return "";
        }
    }
}

/**
 * 内部类,继承HttpGet,为了设置请求超时的参数
 * 
 * @author tom
 *
 */
class HttpGetConfig extends HttpGet {
    public HttpGetConfig(String url) {
        super(url);
        setDefaulConfig();
    }

    private void setDefaulConfig() {
        this.setConfig(RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(10000)
                .setSocketTimeout(10000).build());
        this.setHeader("User-Agent", "spider");
    }
}

这里用了try-with-resource语法,是Java7的新特性,在try()括号中的资源会在try语句块执行完以后自动释放,因此不须要再finally中释放资源。

 

爬取图片的类:经过上面类的静态方法返回的结果,获取到返回的响应结果,而后经过jsoup解析。

package spider.img.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * 2017-5-17 爬取指定URL的图片
 * 
 * @author tom
 *
 */
public class SpiderImgs {
    public SpiderImgs(String url) throws Exception {
        //获取工具类返回的html,并用Jsoup解析
        String result = AbstractSpider.getResult(url);
        Document document = Jsoup.parse(result);
        document.setBaseUri(url);
        //获取全部的img元素
        Elements elements = document.select("img");
        for (Element e : elements) {
            //获取每一个src的绝对路径
            String src = e.absUrl("src");
            URL urlSource = new URL(src);
            URLConnection urlConnection = urlSource.openConnection();
            String imageName = src.substring(src.lastIndexOf("/") + 1, src.length());
            System.out.println(e.absUrl("src"));
            //经过URLConnection获得一个流,将图片写到流中,而且新建文件保存
            InputStream in = urlConnection.getInputStream();
            OutputStream out = new FileOutputStream(new File("E:\\IDEA\\imgs\\", imageName));
            byte[] buf = new byte[1024];
            int l = 0;
            while ((l = in.read(buf)) != -1) {
                out.write(buf, 0, l);
            }
        }
    }
}

 

写一个单元测试试一下:

package spider.img.service.test;

import org.junit.Test;
import spider.img.service.SpiderImgs;

/**
 * 2017-5-17 单元测试
 * @author tom
 */
public class TestCase {
    @Test
    public void testGetResult() throws Exception{
        SpiderImgs spider=new SpiderImgs("http://jandan.net/ooxx/page-60#comments");
    }
}

控制台输出了一些东西,本地也保存了图片。

http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffolz6oon2j30rs15o428.jpg
http://wx2.sinaimg.cn/mw600/0063qhYBgy1ffoiucdw5yj30xc0m9gpt.jpg
http://wx2.sinaimg.cn/mw600/0063qhYBgy1ffoivfcfpwj30xc0m9jt3.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqgqqc0j30lc0w1402.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqg5kz2j30hs0qogo7.jpg
http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffoiqewsbej30go0l60wc.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqdglc7j30lc0voq5k.jpg
http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffoiqaz4dej30lc0w0gn6.jpg

 

github地址:https://github.com/silentyao/JavaImgSpider

相关文章
相关标签/搜索