HttpClient爬虫入门

文章目录

  • 一、maven引入jar包
  • 二、HttpClient使用
    • 1.步骤
    • 2.向网页发送GET请求
    • 3.向网页发送POST请求
    • 4.使用连接池管理请求
  • 三、Jsoup使用
    • 1.使用jsoup解析url
    • 2.使用jsoup解析字符串
    • 3.使用jsoup解析.html文件


  • 什么是HttpClient?

顾名思义,httpclient就是http客户端的意思;在项目中前后台交互是通过HTTP/HTTPS请求、响应来进行的,而HTTP请求是由浏览器生成并发送给后台服务器的,服务器接收request请求处理过后返回前台response响应。HttpClient就是代替并模拟浏览器,由代码生成HTTPrequest请求;请求发送给各个大型网站的服务器,获取其网页内容可以实现网络爬虫的功能。

一、maven引入jar包

<dependency>
	<groupId>org.apache.httpcomponentsgroupId>
	<artifactId>httpclientartifactId>
	<version>4.5.13version>
dependency>

二、HttpClient使用

1.步骤

浏览器发送HTTP请求步骤:

  1. 打开个人PC客户端浏览器
  2. 输入网址
  3. 按下Enter发送GET请求
  4. 收到服务器返回的请求

使用HttpClient向网页发送请求本质就是用代码的方式实现了上面“浏览器发送HTTP请求步骤”,即代码代替手工(方便理解)。

2.向网页发送GET请求

查看HttpGet的源码可以发现HttpGet方法有三个构造函数,可以接受URI对象和String字符串。
HttpClient爬虫入门_第1张图片

代码如下(示例):

/**
 * 使用httpclient发送get请求
 * 并且通过URIBuilder设置带参数的请求(可以不设置,直接发送GET请求)
 * @throws Exception
 */
@Test
public void test2() throws Exception{
     /**
      * CloseableHttpClient:
      * 可以关闭的httpclient客户端,相当于打开一个浏览器
      * 据说是在老版本中httpClient不能及时关闭,造成了资源的浪费,所以有了CloseableHttpClient类。
      */
    CloseableHttpClient closeableHttpClient = HttpClients.createDefault();
    String urlStr = "https://www.huawei.com/cn/searchresult";
    /**
     * 通过URIBuilder设置带参数的get请求
     * 如果有多个参数可以采用链式编程的方法设置多个键值对参数。
     */
    URIBuilder uriBuilder = new URIBuilder(urlStr);
    /**
     * 最终成型样式打印:
     * "GET /cn/searchresult?keywords=p50 HTTP/1.1[\r][\n]"
     */
    uriBuilder.setParameter("keywords","p50");
    /**
     * 构造httpGet请求对象
     * 打印httpGet:GET https://www.huawei.com/ HTTP/1.1
     * 其构造方法可以接受字符串或者是URI实例对象;
     * 即:如果是HttpGet httpGet = new HttpGet(urlStr);
     * 的话是不带参数发送GET请求
     */
    HttpGet httpGet = new HttpGet(uriBuilder.build());
   
    /**
     * 设置请求头,防止多次请求后被网页服务器认定为破坏者给封了
     */
    httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36");

    //  可以关闭的httpClient客户端的响应
    CloseableHttpResponse closeableHttpResponse = null;
    //相当于按下Enter发送请求,然后用closeableHttpResponse 接收返回的响应。
    closeableHttpResponse = closeableHttpClient.execute(httpGet);
    /**
     *  获取status:HTTP/1.1 200 OK  获取状态码:
     *  代码实现:closeableHttpResponse.getStatusLine().getStatusCode();
     */
    /**
     * HttpEntity:
     * 发送请求后获取响应的结果,即获取返回的结果!!!
     * HttpEntity不仅可以作为结果,也可以作为请求的实体参数,他有很多实现。
     * 输出entity:org.apache.http.client.entity.DecompressingEntity@dd3b207
     *  HttpEntity表示http的request和resposne实体,它由消息头和消息体组成。
     *  从HttpEntity中可以获取http请求头和回应头,也可以获取http请求体和回应体信息。
     */
    HttpEntity entity = closeableHttpResponse.getEntity();
    /**
     * EntityUtils是对HttpEntity操作的工具类
     * responseResult就是完整的响应
     */
    String responseResult = EntityUtils.toString(entity,StandardCharsets.UTF_8);
    //System.out.print("测试输出请求的内容:"+entity.getContentType().getValue());
    System.out.print(responseResult);
    //关闭流水
    EntityUtils.consume(entity);
    if(closeableHttpClient != null){
        closeableHttpClient.close();
    }
    if(closeableHttpResponse != null){
        closeableHttpResponse.close();
    }
}

对网页手动发出带参数的请求右击查看网页源代码,和下面的对比发现一样。
HttpClient爬虫入门_第2张图片
执行代码,发出请求,打印结果HttpClient爬虫入门_第3张图片
补充:请求主体的设置

//请求主体的设置,可加在代码中也可不加,记录一下使用方法。
//通过RequestConfig设置,通过httpGet.setConfig将设置添加到http请求中去
HttpGet httpGet = new HttpGet(urlStr);
RequestConfig requestConfig = RequestConfig
     .custom()
     .setConnectTimeout(10000)           //设置链接超时时间为10秒钟,单位是毫秒
     .setConnectionRequestTimeout(1000)  //设置获取连接的最长时间
     .setSocketTimeout(10000)            //设置读取超时时间为十秒钟
     .build();
httpGet.setConfig(requestConfig);


3.向网页发送POST请求

可以设置带参数也可以不带参数,这里直接设置的带参数的post请求,去掉设置请求参数的代码就是不带参数的post请求了;同样可以请求成功。

/**
 * 实现:发送Post请求
 * 步骤:
 * 1.开启客户端
 * 2.找到网址
 * 3.发送GET/POST请求
 * 4.收到response响应
 * 5.处理响应
 * 6.关闭网页,释放资源
 */
@Test
public void testPost() throws  Exception{
    CloseableHttpClient httpClient = HttpClients.createDefault();
    //创建httpPost对象,设置url访问地址
    HttpPost httpPost = new HttpPost("https://www.huawei.com/cn/searchresult");
    //封装表单中的额数据--->声明list集合
    List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
    //设置请求地址是:https://www.huawei.com/cn/searchresult?keywords=p50,是post请求!
    paramsList.add(new BasicNameValuePair("keywords","p50"));
    //创建表单的Entitty的对象
    UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(paramsList,StandardCharsets.UTF_8);
    //将表单对象加入到post请求中
    httpPost.setEntity(urlEncodedFormEntity);
    CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpPost);
    //判断是否请求成功,状态码是200说明得到了正确的响应
    if(closeableHttpResponse.getStatusLine().getStatusCode() == 200){
        HttpEntity entity = closeableHttpResponse.getEntity();
        String s = EntityUtils.toString(entity);
        System.out.print(s);
    }
    httpClient.close();
    closeableHttpResponse.close();
}

4.使用连接池管理请求

/**
 * 功能:测试连接池
 * 问:为什么使用连接池?
 * 答:每次使用HttpClient时,需要开启一个可关闭的httpclient客户端(实际是在内存中申请地址获取硬件资源),使用完后关闭时释放内存资源;
 *    单次使用未有大问题,但是频繁开启httpclient客户端会造成资源的利用不合理。使用连接池可以提前申请好资源,不用频繁开启关闭,使得硬件资源合理利用。
 *
 *  步骤:
 *  1.创建连接池管理器
 *  2.配置连接池
 *  3.使用连接池管理器发起请求
 *
 *  使用连接池和使用HttpClient发起请求的区别:
 *  1.使用连接池管理器创建http请求时不需要使用 HttpClients.createDefault()的方法创建请求
 *  2.请求发起并完成后逇链接不需要关闭,因为有连接池管理器在管理链接。
 */
@Test
public void connPoolMan() throws Exception{
    //1.创建连接池
    PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();
    //2.配置连接池
    pool.setMaxTotal(100);//设置最大连接
    pool.setDefaultMaxPerRoute(10);//设置每个主机的最大连接数
    //3.使用连接池发起请求
    conn(pool);
    conn(pool);
 }

public static void conn(PoolingHttpClientConnectionManager pool) throws Exception{
    CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(pool).build();
    /**
     * 可以看到两次的请求地址是不一样的:
     * HttpClient客户端地址:org.apache.http.impl.client.InternalHttpClient@19dc67c2
     * HttpClient客户端地址:org.apache.http.impl.client.InternalHttpClient@1e127982
     */
    System.out.println("HttpClient客户端地址:"+closeableHttpClient);
    HttpGet httpGet = new HttpGet("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=parser&fenlei=256&oq=Incompatible%2520types.%2520Found%253A%2520%2526%252339%253Bcom.minGe.SpringSecurityStudy.WeekDay%2526%252339%253B%252C%2520required&rsv_pq=89062b920009f034&rsv_t=c484X67GB9z1uE4WJcPgGer043fTPO5I83E1A7YpLoq%2Fw9NM4JZlWN94GOw&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&rsv_sug3=53&rsv_sug1=41&rsv_sug7=100&rsv_sug2=0&inputT=1201&rsv_sug4=2524");
    CloseableHttpResponse execute = closeableHttpClient.execute(httpGet);
    if(execute.getStatusLine().getStatusCode()==200){
        HttpEntity string = execute.getEntity();
        System.out.println("占用了多少字节:"+EntityUtils.toString(string).length());
    }
    /**
     * 注意:
     * closeableHttpClient.close()不需要,连接池管理资源,所以不需要再手动去关闭。
     */
    execute.close();
}

三、Jsoup使用

1.使用jsoup解析url

从下图看到Jsoup.parse的构造函数可以接收多种类型的数据,并且其返回的结果只有一种形式,均是Document类型的结果。
HttpClient爬虫入门_第4张图片

@Test
/**
 * 功能:使用jsoup解析url
 * 注意:
 *    从程序中可以看出使用jsoup可以代替HttpClient直接发起请求并且解析数据,而且简单,但是为何不用jsoup爬取数据?
 *    因为在实际开发中需要使用到多线程、连接池、代理等等方式;而jsoup对这些支持不是很好,所以我们吧jsoup仅仅作为html解析工具使用。
 */
public void parseURL() throws Exception{
    //直接解析url地址,返回的是一个Document对象
    Document document = Jsoup.parse(new URL("https://www.huawei.com/cn/searchresult"), 10000);
    //获取解析到的document对象中的第一个title标签下的文字内容
    String span = document.getElementsByTag("title").first().text();
    //打印结果:站内搜索 - 华为
    System.out.println(span);
}

执行结果:
HttpClient爬虫入门_第5张图片

2.使用jsoup解析字符串

//解析字符串
String content = FileUtils.readFileToString(new File("C://Users//minge//Desktop//这就是一段简单html内容.txt"));
Document docu = Jsoup.parse(content);
System.out.println(docu.getElementsByTag("title").text());

使用FileUtils工具类要导commons-io包:

<dependency>
	<groupId>commons-iogroupId>
	<artifactId>commons-ioartifactId>
	<version>2.4version>
dependency>

3.使用jsoup解析.html文件

//直接解析文件,是在Windows系统下解析的文件,Windows系统下的文件默认使用GB2312编码。
Document document = Jsoup.parse(new File("C://Users//minge//Desktop//这就是一段简单html内容.html"), "GB2312");
//打印结果对比:   

我嫩爹

我嫩爹
System.out.println(document.getElementsByClass("wonendie").html()); System.out.println(document.getElementsByClass("wonendie").text());

你可能感兴趣的:(SpringBoot,HttpClient,http,java,爬虫)