解析与使用 Apache HttpClient 进行网络请求和数据抓取

目录

[1. 什么是 HttpClient?](#1. 什么是 HttpClient?)

[2. 基本使用](#2. 基本使用)

[3. 使用 HttpClient 爬取腾讯天气的数据](#3. 使用 HttpClient 爬取腾讯天气的数据)

[4. 爬取拉勾招聘网站的职位信息](#4. 爬取拉勾招聘网站的职位信息)

[5. 总结](#5. 总结)


前言

Apache HttpClient 是 Apache 提供的一个用于处理 HTTP 请求和响应的工具类库。它提供了一种便捷、功能强大的方式来发送 HTTP 请求,并解析 HTTP 响应。HttpClient 适用于多种网络请求场景,能够帮助我们高效地与 Web 服务进行交互。

1. 什么是 HttpClient?

HttpClient 是在 JDK 的基础类库基础上进行封装和增强的一个 HTTP 请求工具库。它提供了更强大、更灵活的功能,比如支持连接池、认证机制、重定向、请求重试等,帮助我们提高开发效率和代码质量。

HttpClient 的核心功能包括:

  • 连接池管理:提高性能,减少资源消耗,复用 TCP 连接。
  • 自动化处理 HTTP 头、请求和响应数据
  • 支持多种认证方式,如 Basic 认证、Digest 认证等。
  • 重定向处理:自动处理 HTTP 重定向。
  • 支持 Cookie 管理
  • 支持并发请求

2. 基本使用

2.1 引入依赖

首先,你需要在项目中引入 HttpClient 的 Maven 依赖。以下是 Apache HttpClient 的 Maven 依赖配置:

XML 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version> <!-- 请使用最新版本 -->
</dependency>

2.2 发送 HTTP GET 请求

下面是一个简单的使用示例,展示如何通过 HttpClient 发送一个 HTTP GET 请求:

java 复制代码
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;

public class HttpClientExample {
    public static void main(String[] args) throws IOException {
        // 创建一个 HttpClient 实例
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建一个 HttpGet 请求对象
            HttpGet request = new HttpGet("https://www.baidu.com/");
            
            // 执行请求并获取响应
            HttpResponse response = httpClient.execute(request);
            
            // 如果请求成功,返回 200 状态码
            if (response.getStatusLine().getStatusCode() == 200) {
                // 将响应实体转换为字符串
                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                // 输出响应内容
                System.out.println(responseBody);
            }
        }
    }
}

在上面的代码中,我们使用 HttpClients.createDefault() 创建了一个默认的 HttpClient 实例,然后通过 HttpGet 对象发送了一个请求,并打印了百度主页的 HTML 源码。

可以看到请求的结果为百度源代码

3. 使用 HttpClient 爬取腾讯天气的数据

接下来,展示如何使用 HttpClient 来爬取 JSON 格式的天气数据。我们通过发送 HTTP GET 请求,获取腾讯天气 API 返回的 JSON 数据,并进行解析。

3.1 查询天气的json格式数据

我们构造一个 HTTP GET 请求,访问腾讯的天气 API:

java 复制代码
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class WeatherDemo {
    public static void main(String[] args) {
        // 创建 HttpClient 实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            // 设置请求 URL,查询河北省保定市的天气信息
            HttpGet httpGet = new HttpGet("https://wis.qq.com/weather/common?source=pc&weather_type=observe|forecast_1h|forecast_24h&province=%E6%B2%B3%E5%8C%97%E7%9C%81&city=%E4%BF%9D%E5%AE%9A%E5%B8%82&county=");
            
            // 设置请求头
            httpGet.setHeader("Accept", "*/*");
            httpGet.setHeader("User-Agent", "Mozilla/5.0");
            
            // 执行请求,获取响应
            CloseableHttpResponse response = httpClient.execute(httpGet);
            
            // 获取响应的字符串内容
            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
            
            // 解析 JSON 数据
            String jsonString = responseBody.substring(42, responseBody.length() - 1);
            JSONObject json = JSON.parseObject(jsonString);
            JSONObject data = json.getJSONObject("data");
            JSONObject forecast = data.getJSONObject("forecast_24h");
            JSONObject day0 = forecast.getJSONObject("0");

            // 输出天气信息
            System.out.println("夜间风向: " + day0.get("night_wind_direction"));
            
            // 关闭响应对象
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭 HttpClient
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在这个示例中,我们通过解析返回的 JSON 数据,提取了天气信息,并输出了夜间风向。

3.2 JSON 解析

通过使用 fastjson 库,我们能够方便地解析 JSON 数据。JSONObject 类提供了 get()getJSONObject()getJSONArray() 方法,方便我们提取对应的值:

  • get():获取某个键对应的值,返回 Object 类型。
  • getJSONObject():获取某个键对应的 JSON 对象,返回 JSONObject 类型。
  • getJSONArray():获取某个键对应的 JSON 数组,返回 JSONArray 类型。

整体代码:

java 复制代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;

public class XXDemo {
    public static void main(String[] args) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet httpGet = new HttpGet("https://wis.qq.com/weather/common?source=pc&weather_type=observe%7Cforecast_1h%7Cforecast_24h%7Cindex%7Calarm%7Climit%7Ctips%7Crise&province=%E6%B2%B3%E5%8C%97%E7%9C%81&city=%E4%BF%9D%E5%AE%9A%E5%B8%82&county=&callback=jQuery111307985983701500603_1730452291491&_=1730452291493");
            // 设置请求头
            httpGet.setHeader("Accept", "*/*");
            httpGet.setHeader("Accept-Encoding",  "gzip, deflate, br, zstd");
            httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.9");
            httpGet.setHeader("Cache-Control", "max-age=0");
            httpGet.setHeader("Connection", "keep-alive");
            httpGet.setHeader("Cookie", "pgv_pvid=7587513344; RK=viMJj838H2; ptcz=410fc81f9ad1719db0b83d1ae0b767a81c43f89b4d79b4f22f0f04bf476c4e44; qq_domain_video_guid_verify=50ba34f244950f77; _qimei_uuid42=17c02140117100fd9f4a0a8f7ddb1d4eb0eef0fe2b; _qimei_q36=; _qimei_h38=2db835139f4a0a8f7ddb1d4e02000003017c02; tvfe_boss_uuid=9dd0f4ca6252467b; _qimei_fingerprint=a8fdf4f9656a2285f66b7f0bb5dbefc2; fqm_pvqid=bfdb0333-6586-490e-9451-7e4628f24f32; pgv_info=ssid=s390182559; pac_uid=0_sBk6e1R1P4Zpc");
            httpGet.setHeader("Host", "wis.qq.com");
            httpGet.setHeader("Upgrade-Insecure-Requests", "1");
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36");
            // 执行请求
            CloseableHttpResponse response = httpClient.execute(httpGet);
            // 获取响应实体
            String responseBody = EntityUtils.toString(response.getEntity(),"UTF-8");

            //获取中间json数据
            String subStringA = responseBody.substring(0,42);
            String str = responseBody.replace(subStringA,"");
            String newStr = str.substring(0, str.length()-1);


            //JSON解析----》JSONObject:处理json对象,根据可以值获取value值
            JSONObject json =  JSON.parseObject(newStr); //将字符串转换成json数组
            JSONObject data =  json.getJSONObject("data");
            JSONObject forecast_24h =  data.getJSONObject("forecast_24h");
            JSONObject data0 =  forecast_24h.getJSONObject("0");
            System.out.println(data0.get("night_wind_direction"));

            // 关闭响应对象
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
java 复制代码
public class HttpClient {
    public static void main(String[] args) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet("https://cdn.mdeer.com/data/yqstaticdata.js");
            CloseableHttpResponse response = httpClient.execute(request);  //发送请求,获取响应
            if (response.getStatusLine().getStatusCode() == 200) {
                String responseBody = EntityUtils.toString(response.getEntity(),"utf-8");

                //获取中间json数据
                String subStringA = responseBody.substring(0, 19);
                String str = responseBody.replace(subStringA, "");
                String newStr = str.substring(0, str.length() - 1);
                //System.out.println(newStr);

                JSONObject json = JSON.parseObject(newStr); //将字符串转换成json数据
                JSONArray cityLists = json.getJSONArray("cityLists");
                for (int i = 0;i<cityLists.size();i++){
                    JSONObject jsonObject = cityLists.getJSONObject(i);
                    if(!jsonObject.getString("city").equals("待确认地区")){
                        System.out.println("城市:"+jsonObject.getString("city")+" 当前确认:"+jsonObject.getString("currentConfirm"));
                    }
                }
            }
        }
    }
}

4. 爬取拉勾招聘网站的职位信息

除了获取天气数据,我们还可以利用 HttpClient 抓取其他网站的数据。例如,我们可以爬取拉钩招聘网站的职位信息。以下是一个爬取拉钩招聘职位的简单示例:

java 复制代码
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ParseUtils {
    public static final String url = "https://www.lagou.com/wn/zhaopin?kd=Java&city=%E5%8C%97%E4%BA%AC";

    private static List<Job> jobs = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        // 使用 Jsoup 连接拉钩招聘网站
        Document scriptHtml = Jsoup.connect(url)
                .header("User-Agent", "Mozilla/5.0")
                .timeout(50000)
                .get();
        
        // 获取职位列表
        Elements list = scriptHtml.getElementsByClass("item__10RTO");
        for (Element element : list) {
            String jobName = element.getElementById("openWinPostion").text();
            String experience = element.getElementsByClass("p-bom__JlNur").text();
            String salary = element.getElementsByClass("money__3Lkgq").text();
            String company = element.getElementsByClass("company-name__2-SjF").text();

            // 将职位信息添加到列表中
            Job job = new Job(jobName, experience, salary, company);
            jobs.add(job);
        }

        // 输出所有职位信息
        for (Job job : jobs) {
            System.out.println(job);
        }
    }
}

4.1 数据清洗

爬取到的数据往往需要进行清洗处理,以符合我们需要的格式。例如,在拉钩招聘爬虫中,我们提取了职位名称、经验要求、薪资信息等,并进行清洗和格式化。

java 复制代码
public static void cleanData(Job job) {
    // 薪资清洗
    String salary = job.getSalary().substring(0, job.getSalary().indexOf("-"));
    job.setSalary(salary);

    // 清洗经验要求
    String experience = job.getExperience().substring(job.getExperience().indexOf("经验"), job.getExperience().indexOf(" "));
    job.setExperience(experience);

    jobs.add(job);
}

5. 总结

HttpClient 是一个强大的工具,适用于多种网络请求场景,特别是爬虫和数据抓取。通过它,我们可以轻松发送 HTTP 请求,解析返回的 JSON 或 HTML 数据,并提取出有用的信息。对于复杂的网络请求场景,HttpClient 还提供了丰富的功能,如连接池、认证、请求重试等,帮助我们提高效率和性能。

通过本文的介绍,你已经掌握了如何使用 HttpClient 发送 HTTP 请求,如何解析 JSON 数据,并能在实践中抓取和清洗网页数据。

相关推荐
一一Null26 分钟前
关于手机取证中逻辑采集与系统备份的差异
服务器·网络·智能手机
码农新猿类29 分钟前
服务器本地搭建
linux·网络·c++
SlientICE2 小时前
TCP是什么?不需要!使用ESP32网络层直接通信!
网络·单片机·网络协议·tcp/ip
小李超勇的..4 小时前
SOME/IP
网络·网络协议·tcp/ip
EasyDSS4 小时前
WebRTC实时通话EasyRTC嵌入式音视频通信SDK,构建智慧医疗远程会诊高效方案
大数据·网络·网络协议·音视频
左灯右行的爱情4 小时前
计算机网络-传输层基础概念
网络·计算机网络·php
群联云防护小杜4 小时前
隐藏源站IP与SD-WAN回源优化:高防架构的核心实践
网络·分布式·网络协议·tcp/ip·安全·架构·ddos
老马啸西风5 小时前
Neo4j GDS-09-neo4j GDS 库中路径搜索算法实现
网络·数据库·算法·云原生·中间件·neo4j·图数据库
Go高并发架构_王工6 小时前
基于 GoFrame 框架的电子邮件发送实践:优势、特色与经验分享
网络·经验分享·golang
SlientICE6 小时前
预防WIFI攻击,保证网络安全
网络·安全·php