Java实现网络爬虫[1+x大数据应用的实战]

 Hygge   2020-12-25 19:06   275 人阅读  1 条评论

    这几天打算考一个《1+x 大数据应用》,这个是蓝桥的,我和蓝桥挺有缘的高中就听过蓝桥杯,大一也如愿参加了现在又是蓝桥的这个证书。

    做了一下官方的模拟考试,发现考的并不是特别难,但是相应的技术都已经学过了,所以想利用这些知识来实战一下。

    技术点有:网络请求、mysql存储数据、JSON数据解析

爬取目标:

蓝桥杯大赛的所有大赛通知

32页数据 ,将每条的标题内容发布日期存储的数据库中

3目标.jpg

通过浏览器的开发者工具抓了下包,配合postman调试了一下

4 分析.jpg

得到以下的信息:

https://dasai.lanqiao.cn/api/action/http/get

请求方式:POST

请求体:

url:
http://10.251.196.135/API.php?m=list&id=20&p=1&s=10

其中 p 代表页码,s 代表每一页的数据条数。

理论上可以一个请求获取到所有的数据,在明确数据总条数的情况

但是本篇讲解是基于不断改变页码的方式来操作的,有兴趣可以自主尝试一下前者



第一步  先创建一个 Maven项目,直接下一步

1创建项目.jpg

第二步 配置pom.xml文件

<dependencies>
    <!-- 网络请求 所需要的包 -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.6</version>
    </dependency>
    <!-- 引入fastjson 解析json数据-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
    <!-- 含有转义与去除转义的功能 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-text</artifactId>
        <version>1.1</version>
    </dependency>
    <!-- MySql 8.0.18 Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
</dependencies>

2配置依赖.jpg


第三步:开始敲代码

    对于一个网络请求是分为两部分的,有请求,响应。

    对于post请求,还需要在请求体中携带参数

建好基本的代码结构

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.io.IOException;


/**
 * @author lsk
 * @description
 * @create 2020/12/25 20:10
 */
public class main {
    public static void main(String[] args) {
        //初始化网络请求的对象
        CloseableHttpClient client = HttpClients.createDefault();
        //定义网络响应对象
        CloseableHttpResponse response = null;
        //定义请求方式
        HttpPost httpPost = new HttpPost("https://dasai.lanqiao.cn/api/action/http/get");
        try {
            //client.execute()会导致IOException 异常,所以要捕捉一下
            //execute()需要一个实现HttpUriRequest接口的类作为参数,有HttpPost\HttpGet,详见该接口的源码
            response = client.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
//            防止响应为空
            if(response != null){
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
//            防止请求为空
            if(client != null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

下一步需要给post请求携带上参数

//通过该方法,需要一个实现了HttpEntity接口的类作为参数,这里使用StringEntity > UrlEncodeFormEntity
httpPost.setEntity();

参数设置.jpg

实例化该类需要一个 NameValuePair类型的集合,那我们就创建一个这样集合。

写单个参数.jpg

本次请求只需要一个 url 参数,所以声明一个该类型的对象又是一个接口,找子类实现,图中可以看出直接填写键值对。

……
//定义请求方式
HttpPost httpPost = new HttpPost("https://dasai.lanqiao.cn/api/action/http/get");
NameValuePair para = new BasicNameValuePair("url","http://10.251.196.135/API.php?m=list&id=20&p=1&s=10");
List<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(para);
try {
    StringEntity stringEntity = new UrlEncodedFormEntity(list);
    httpPost.setEntity(stringEntity);
    //client.execute()会导致IOException 异常,所以要捕捉一下
    //execute()需要一个实现HttpUriRequest接口的类作为参数,有HttpPost\HttpGet,详见该接口的源码
    response = client.execute(httpPost);
} catch (IOException e) {
    e.printStackTrace();
}
……

至此,网络请求已经完整,可以尝试接受响应了!

//execute 就是 执行,发送了请求
response = client.execute(httpPost);
// 对响应的状态码进行判断。
if(response.getStatusLine().getStatusCode() == 200){
    //获取响应的源代码
    HttpEntity entity = response.getEntity();
    String str = EntityUtils.toString(entity, "UTF-8");
    System.out.println(str);
}

运行查看结果:

接受到响应.jpg

控制台中可以看到打印的响应

下面要做两件事,

  1. 去除响应的转义,也就是 \" 等字符

  2. 去除开头和结尾的引号

  3. 应字符串解析为JSON数据

// StringEscapeUtils 来自于 依赖中的 commons-text
str = StringEscapeUtils.unescapeJava(str);
str = str.substring(1,str.length() - 1);
//打印一下 发现去除转义、开头结尾的引号的效果已经达到。
//{"total":"315","new_list":[{"id":"1850","title":"……

将响应格式化一下:

格式化响应.jpg

发现响应本身是一个jsonObject,我们要的是 new_list 节点,它是一个jsonArray,照此思路我们来解析它。

//将响应字符串  先 转为 JSONObject
JSONObject allObj = JSON.parseObject(str);
//取出其中的new_list节点 作为JSONArray
JSONArray new_list = allObj.getJSONArray("new_list");

//我们来遍历一下这个JSONArray
JSONObject item = null;
for(int i = 0;i < new_list.size();i++){
    item = new_list.getJSONObject(i);
    System.out.println(item.getString("title"));
    System.out.println(item.getString("content"));
    System.out.println(item.getString("up_time"));
}

遍历结果.jpg

成功!


关于存储到数据库中,等有时间再更新一下本帖。。

本文地址:https://blog.lisok.cn/post/4.html
版权声明:本文为原创文章,版权归 Hygge 所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

 评论列表

  1. 访客
    访客  @回复

    期待更新更新!