httpclient的使用和htmlcleaner快速使用

今天说:httpclient,他是apache下的, 目前用它采集同步网站,

那么首先看这个代码之前,一定要先对request response 有所了解,这样可以更好懂一些,httpclient是对网络编程 也就是net包下的封装,因为URLConnection类 ,虽然也可以采集到东西,但是毕竟是原生的, 我先把异常抛出到main上 ,这样代码少一些

一会什么简介啦,ppt和我们老师上的视频都有的

一会我把所需要的jar包,放到百度网盘中 ,当然 可以添加maven依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

//@Test
    public void fun() throws Exception{
        CloseableHttpClient httpClient = HttpClients.createDefault(); //创建实例对象
        HttpGet httpGet = new HttpGet("https://www.tinaya.com/"); //这里面放需要链接的地址即可
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36"); //为什么这里要设置请求头?

因为某些网站,是有反爬虫措施的, 这么设置,只是为了模拟人的操作而已,不然有可能封你的ip地址

/*
         得到response之后,我们就需要对response进行解析了
         */
        CloseableHttpResponse response = httpClient.execute(httpGet); ///执行http协议的get请求
        HttpEntity entity = response.getEntity(); //得到实体
        System.out.println("网页源码如下:");
        String src = EntityUtils.toString(entity, "utf-8"); //以什么形式看源码?? 一般的网页在meta标签中都有一个content-type请求头,与那个对应即可
        System.out.println(src);
        //关流
        response.close();
        httpClient.close();
    }

/*
     为什么要得到content-type?
    
     根据具体的MIME类型 ,来过滤
    
     为什么要得到状态码?
     因为200代表 成功, 404代表找不到,
     如果不是200,那么下面的爬虫代码就不需要执行了
     */

//得到此页面的MIME类型
        String value = entity.getContentType().getValue();
        System.out.println(value); //输出content-type的值
        
        //得到此页面的状态码
        StatusLine line = response.getStatusLine();
        System.out.println(line);//HTTP/1.1 200 OK 这个是把那一条信息都返回回来了
        //但是我们一般只需要状态码,用它判断即可
        int code = line.getStatusCode();
        System.out.println(code);

2  HttpClient 抓取图片:

public void fun() throws Exception{
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://xxxx/gg/sxt2.gif"); //只不过改为了图片地址而已
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if(entity!=null){
            System.out.println(entity.getContentType().getValue());
            InputStream input = entity.getContent();//以流的形式(因为照片是字节,当然以流的形式传输和写入)
            FileUtils.copyInputStreamToFile(input, new File("C:\\sxt.gif"));//这时你看,我保存的时候怎么知道文件是什么后缀,我可以上面写一个String imageHref  变量, 因为我知道我传入的图片路径 而路径中有名字,截取一下即可

这个方法是Commons.io包中的一个方法而已
      
        }

设置代理ip

在爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采集屏蔽IP措施。

这时候,代理IP就派上用场了。

关于代理IP的话 也分几种 透明代理、匿名代理、混淆代理、高匿代理

透明代理:虽然透明代理可以直接“隐藏”你的IP地址,但是还是可以查到你是谁

匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。

混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真:

高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。我们使用的是高匿代理,

代理IP 从哪里搞呢 很简单  百度一下,你就知道 一大堆代理IP站点。  一般都会给出一些免费的,

     CloseableHttpClient httpClient=HttpClients.createDefault(); // 创建httpClient实例

        HttpGet httpGet=new HttpGet("https://www.taobao.com/"); // 创建httpget实例

        HttpHost proxy=new HttpHost("116.226.217.54", 9999); //用来设置代理ip

/*

       这个类位于 org.apache.http.client.config包下,主要用于获取和配置一些外部的网络环境,它下面有一个嵌套类 RequestConfig.Builder

使用方法是:先用 RequestConfig类的静态方法custom()获取requestConfig.Builder“配置器”,然后再用其下各种方法配置网络环境;

*/

        RequestConfig requestConfig=RequestConfig.custom().setProxy(proxy).build();

        httpGet.setConfig(requestConfig);

        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");

        CloseableHttpResponse response=httpClient.execute(httpGet); // 执行http get请求

        HttpEntity entity=response.getEntity(); // 获取返回实体

        System.out.println("网页内容:"+EntityUtils.toString(entity, "utf-8")); // 获取网页内容

        response.close(); // response关闭

        httpClient.close(); // httpClient关闭

  一般如果是你如果采集网站遇到403 ,那么可能就是被屏蔽了,这时你就应该换一个代理ip了
     思路:
     先做一个小爬虫,专门去 这些免费代理ip网站,得到 这ip和端口这两个数据
     把代理ip和 端口 放到一个map中(队列中) 也可以
     加一个判断,如果是403,取出下一个map的键值对并且移除掉这个ip
     然后那么就会一直取,一直移除,再加一个判断,如果ip不够的时候,继续运作爬虫,爬取ip

httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间;

所谓连接的时候 是HttpClient发送请求的地方开始到连接上目标url主机地址的时间,

线路越通畅越快,但是由于路由复杂交错,往往连接上的时间都不固定,运气不好连不上,HttpClient的默认连接时间,

默认是1分钟,假如超过1分钟 过一会继续尝试连接,这样会有一个问题 假如遇到一个url老是连不上,会影响其他线程的线程进去,所以我们有必要进行特殊设置,比如设置10秒钟 假如10秒钟没有连接上 我们就报错,这样我们就可以进行业务上的处理,

比如我们业务上控制 过会再连接试试看。并且这个特殊url写到log4j日志里去。方便管理员查看。

ttpClient读取时间

所谓读取的时间 是HttpClient已经连接到了目标服务器,然后进行内容数据的获取,一般情况 读取数据都是很快速的,

但是假如读取的数据量大,或者是目标服务器本身的问题(比如读取数据库速度慢,并发量大等等..)也会影响读取时间。

同上,我们还是需要来特殊设置下,比如设置10秒钟 假如10秒钟还没读取完,就报错,同上,我们可以业务上处理。

   如果连接超时 ,报的是connect  timed out
   如果读取超时 ,报的是read timed out

CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("https://www.tuicool.com/");
        
        
        RequestConfig config = RequestConfig.custom()
                            .setConnectTimeout(10000)//设置连接超时时间
                            .setSocketTimeout(10000)//设置读取超时时间
                            .build();
        httpGet.setConfig(config);
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        System.out.println("网页源码如下:");
        String src = EntityUtils.toString(entity, "utf-8");
        System.out.println(src);
        //关流
        response.close();
        httpClient.close();

/=====================================================

其实httpclient能做很多的事情,但是我们目前用它做这么多就可以,做别的哟也有别的比他做得更好,

以后你们会知道的

当解析到源码之后呢? 我们是不是就可以解析其中的内容了呢? 当然可以

但是你考虑过吗? 某些网站的前台人员代码写的不好,那么就有可能会出现,标签不能成对出现或者短标签的情况

这是htmlcleaner 或者htmlparser 登场了

个人推荐用htmlcleaner,更好用一点

HtmlCleaner clean = new HtmlCleaner();
        TagNode tagNode = clean.clean(src); //就是这么用

他其中支持xpath ,我们可以用他解析内容

//标题
           Object[] titles = tagNode.evaluateXPath("xpath表达式");

然后获取就行了

htmlcleaner还可以将源码转换成dom树 我们就可以用dom4j  来解析了,但是还是有点麻烦呀,因为它自带xpath了,何必再new一个xpathFacotry呢?
---------------------
 

猜你喜欢

转载自blog.csdn.net/qq_40077806/article/details/83591911