12 Java网络爬虫和IO流的综合练习(带权重的随机算法)


前言

学习这个爬虫前,先复习一下前面的正则表达式。参考博客

爬虫其实并不难,学习爬虫的最好例子就是直接上实际例子练习。


一、网络爬虫

案例一(先看这一个入门):

1 需求

在这里插入图片描述

现在我们需要测试一个随机点名系统,但是现在又一个难题就是我们没有姓名名单。所以我们的任务就是获取一份假的姓名名单将其保存在一个txt中。如果是少量姓名数据,人为写进txt中也是可以的。但是我们这里采用一种比较高端的方式–爬虫。

百家姓

男生名字

女生名字

下面我们就会爬取这三个网站上的信息来构造我们的点名系统名册。

2 爬取整个html

我们先来爬取整个网址看看是爬取下来的什么东西!

package cn.hjblogs.demo2;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class Test {
   
    public static void main(String[] args) throws IOException {
   
        /*
        * 制造假数据
        * 获取姓:https://hanyu.baidu.com/shici/detail?from=aladdin&pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d
        * 获取男生名字: http://www.haoming8.cn/baobao/10881.html
        * 获取女生名字: http://www.haoming8.cn/baobao/7641.html
        */

        // 1. 定义变量记录网址
        String familyNameNet = "https://hanyu.baidu.com/shici/detail?from=aladdin&pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d";
        String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
        String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";

        // 2 爬取数据,由于这里是爬取姓名,我们将所有数据拼接成一个字符串即可
        String familyNameData = webCrawler(familyNameNet);
        System.out.println(familyNameData);


    }

    /*
    * 作用:从网络中爬取数据,把数据拼接成字符串返回
    * 形参: 网址
    * 返回值:爬取到的所有数据
    * */
    public static String webCrawler(String net) throws IOException {
   
        StringBuilder sb = new StringBuilder();

        // 1 创建一个URL对象
        URL url = new URL(net);

        // 2 连接上这个网络,细节:保证网络是畅通的,在浏览器中能访问
        URLConnection conn = url.openConnection();

        // 3 读取数据 conn.getInputStream() 返回的是一个字节流,我们需要转换成字符流才能处理中文,所以转换流在某些场景下还是有用的
        InputStreamReader isr = new InputStreamReader(conn.getInputStream());
        int ch;
        while ((ch = isr.read()) != -1) {
   
            sb.append((char) ch);
        }
        isr.close();

        return sb.toString();
    }
}

看看我们直接爬取爬取下来了什么东西:
在这里插入图片描述
可以看到爬取了整个网页的html。但是整个html不是我们想要的,我们想从html中获取我们想要的内容就要使用正则表达式了。因此我们还需要写一个方法利用正则表达式从html中获取我们想要数据的方法。

3 使用正则表达式从html中获取想要内容

package cn.hjblogs.demo2;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
   
    public static void main(String[] args) throws IOException {
   
        /*
        * 制造假数据
        * 获取姓:https://hanyu.baidu.com/shici/detail?from=aladdin&pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d
        * 获取男生名字: http://www.haoming8.cn/baobao/10881.html
        * 获取女生名字: http://www.haoming8.cn/baobao/7641.html
        */

        // 1. 定义变量记录网址
        String familyNameNet = "https://hanyu.baidu.com/shici/detail?from=aladdin&pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d";
        String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
        String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";

        // 2 爬取数据,由于这里是爬取姓名,我们将所有数据拼接成一个字符串即可

        // (1)爬取姓
        String familyNameData = webCrawler(familyNameNet);
        // System.out.println(familyNameData);
        String regex1 = "(<div class=\"text\">)(.{1})(</div>)";       // 正则表达式,这里对其分一个组,我们只需要第二个组的数据
        ArrayList<String> familyName_lst = getData(familyNameData, regex1, 2);
        System.out.println(familyName_lst);       // [赵,钱,...]

        // (2)爬取男生名字
        String boyNameData = webCrawler(boyNameNet);
        // System.out.println(boyNameData);
        String regex2 = "([\\u4E00-\\u9FA5]{2})(、|。)";        // [\u4E00-\u9FA5]  表示一个中文字符
        ArrayList<String> boyName_lst = getData(boyNameData, regex2, 1);
        System.out.println(boyName_lst);             // [月星、弘城、雨国、...]


        // (3)爬取女生名字
        String girlNameData = webCrawler(girlNameNet);
        // System.out.println(girlNameData);
        String regex3 = "<p>((.. ){4}..)</p>";
        ArrayList<String> girlName_lst = getData(girlNameData, regex3, 1);
        System.out.println(girlName_lst);             // [彤舞 芊静 艾丝 惠蕙 语月, 依莹 瑶馨 曼珍 逸云 微婉, ...] 需要注意的是,这个一个元素中有多个名字,还需要进一步处理

        // 注意上述正则匹配还比较粗糙,可以根据实际情况进行调整,但是这里差不多可以够我们使用了
        // 下面这里就可以进一步处理,爬虫到这里就结束了。



    }

    /*
    * 作用:从网络中爬取数据,把数据拼接成字符串返回
    * 形参: 网址
    * 返回值:爬取到的所有数据
    * */
    public static String webCrawler(String net) throws IOException {
   
        StringBuilder sb = new StringBuilder();

        // 1 创建一个URL对象
        URL url = new URL(net);

        // 2 连接上这个网络,细节:保证网络是畅通的,在浏览器中能访问
        URLConnection conn = url.openConnection();

        // 3 读取数据 conn.getInputStream() 返回的是一个字节流,我们需要转换成字符流才能处理中文,所以转换流在某些场景下还是有用的
        InputStreamReader isr = new InputStreamReader(conn.getInputStream());
        int ch;
        while ((ch = isr.read()) != -1) {
   
            sb.append((char) ch);
        }
        isr.close();

        return sb.toString();
    }

    /*
    * 作用:从爬取的html中利用正则表达式获取数据
    * 参数一:html_str 爬取的html(str)
    * 参数二:regex 正则表达式
    * 参数三:group 正则表达式中的组,我们只要从匹配结果中获取我们想要的组的数据
    * 返回值:返回一个集合,集合中存储了我们想要的数据
    * */
    public static ArrayList<String> getData(String html_str, String regex, int group){
   
        // 1. 定义一个集合,用来存储数据
        ArrayList<String> list = new ArrayList<>();
        // 2. 按照正则表达式是规则,去获取数据
        Pattern pattern = Pattern.compile(regex);
        // 3 按照pattern的规则,去匹配html_str中的数据
        Matcher matcher = pattern.matcher(html_str);
        // 4. 遍历matcher,获取数据
        while (matcher.find()) {
   
            String s = matcher.group(group);  // 获取正则表达式中的第group组的数据
            list.add(s);
            // System.out.println(s);
        }
        return list;
    }

}



【注】:爬取的过程中药根据html不断调整合适的正则表达式,这点可以将上面的System.out.println(s);这行注释取消,String s = matcher.group();中不要传入参数看看匹配的是不是我们想要的来进一步调整,或者直接在html中CTRL+F使用正则查找功能。

while (matcher.find()) {
   
    String s = matcher.group();
    list.add(s);
    System.out.println(s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值