Java—— 网络爬虫

发布于:2025-05-24 ⋅ 阅读:(18) ⋅ 点赞:(0)

案例要求 

https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0
http://www.haoming8.cn/baobao/10881.html
http://www.haoming8.cn/baobao/7641.html

 上面三个网址分别表示百家姓,男生名字,女生名字,如图:

           

要求:

获取上述网址中的内容,利用正则表达式爬取姓氏和名字信息,并生成不重复的10个男生的姓名和10个女生的姓名 ,将生成的姓名保存到本模块下的a.txt文件中。

关于网络的方法

URL网址对象

构造方法 说明
public URL(String spec) 利用记录网址的字符串创建一个网址的对象
成员方法 说明
public URLConnection openConnection() 网址对象调用该方法让程序连接网址,返回程序和URL之间的通信链接对象

URLConnection通信链接对象

成员方法 说明
public InputStream getInputStream() 得到连接网址的字节输入流

关于爬虫的方法

Pattern正则表达式对象

构造方法 说明
public static Pattern compile(String regex) 获取正则表达式的对象,传递的是表示正则表达式的字符串
成员方法 说明
public Matcher matcher(String str) 正则表达式对象调用该方法获取文本匹配器的对象,传递的是需要进行查找的大串

Matcher文本匹配器对象

成员方法 说明
public boolean find() 让文本匹配器从头开始读取大串,寻找是否有满足正则表达式的子串。如果没有,方法返回false,如果有,返回true。在底层记录子串的起始索引和结束索引+1
public String group() 方法底层会根据find()方法记录的索引进行字符串的截取,返回截取的小串,该小串就是符合正则表达式要求的子串

代码实现

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test1 {
    public static void main(String[] args) throws IOException {

        //记录网址
        String familyNameWeb = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
        String boyNameweb = "http://www.haoming8.cn/baobao/10881.html";
        String girlNameweb = "http://www.haoming8.cn/baobao/7641.html";

        //调用方法网络爬取网址内容并以字符串形式返回
        String familyNameStr = webCrawler(familyNameWeb);
        String boyNameStr = webCrawler(boyNameweb);
        String girlNamewebStr = webCrawler(girlNameweb);


        //利用正则表达式获取网址中的姓氏和名字
        //按照所需数据在网址内容中的布局不同设置不同的正则表达式

        //百家姓网址中所需的百家姓数据都是4个中文一组后面跟逗号或句号,且只获取符合前的内容
        //中文的正则表达式为[\u4E00-\u9FA5]
        ArrayList<String> familyNameTempList = getData(familyNameStr, "([\\u4E00-\\u9FA5]){4}(?=,|。)");

        //男生名字网址中所需的名字数据都是2个中文一组后面跟顿号或句号,且只获取符合前的内容
        ArrayList<String> boyNameTempList = getData(boyNameStr, "([\\u4E00-\\u9FA5]){2}(?=、|。)");

        //女生名字网址中所需的名字数据都是2个中文加1个空格4组后面跟2个中文,都获取
        ArrayList<String> girlNameTempList = getData(girlNamewebStr,
                "(([\\u4E00-\\u9FA5]){2} ){4}[\\u4E00-\\u9FA5]{2}");


        //得到了初始数据集合,将其优化方便使用

        //System.out.println(familyNameTempList);
        //[赵钱孙李, 周吴郑王, 冯陈褚卫, 蒋沈韩杨,......
        //修改百家姓集合为:只保留前410个单姓,并且每一个姓氏占一个索引
        ArrayList<String> familyNameTemp2List = new ArrayList<>();
        ArrayList<String> familyNameList = new ArrayList<>();
        for (String s : familyNameTempList) {
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                familyNameTemp2List.add(c + "");
            }
        }
        //只保留前410个单姓
        for (int i = 0; i < 410; i++) {
            familyNameList.add(familyNameTemp2List.get(i));
        }
        //System.out.println(familyNameList);
        //[赵, 钱, 孙, 李, 周, 吴, 郑, 王,......

        //System.out.println(boyNameTempList);
        //[大气, 美好, 特色, 大气, 美好, 特色, 月星, 弘城, 雨国, 思明,.....
        //修改男生名字集合为:去除重复,每一个名字占一个索引
        ArrayList<String> boyNameList = new ArrayList<>();
        for (String s : boyNameTempList) {
            if (!boyNameList.contains(s)) {
                boyNameList.add(s);
            }
        }
        //System.out.println(boyNameList);
        //[大气, 美好, 特色, 月星, 弘城, 雨国, 思明, ......

        //System.out.println(girlNameTempList);
        //[彤舞 芊静 艾丝 惠蕙 语月, 依莹 瑶馨 曼珍 逸云 微婉,.....
        //修改女生名字集合为:去除重复,每一个名字占一个索引
        ArrayList<String> girlNameList = new ArrayList<>();
        for (String s : girlNameTempList) {
            String[] arr = s.split(" ");
            for (int i = 0; i < arr.length; i++) {
                girlNameList.add(arr[i]);
            }
        }
        //System.out.println(girlNameList);
        //[彤舞, 芊静, 艾丝, 惠蕙, 语月, 依莹, ......


        //调用方法根据准备好的数据分别获取不重复的10个男生名字和女生名字
        //参数为坐标的数据和男女要生成名字的数量
        ArrayList<String> nameList = getName(familyNameList, boyNameList, girlNameList, 10, 10);

        //利用缓冲字符输出流写到本模块下的a.txt文件中
        BufferedWriter bw = new BufferedWriter(new FileWriter("day05\\a.txt"));
        for (String s : nameList) {
            bw.write(s);
            bw.newLine();
        }
        bw.close();

    }

    private static ArrayList<String> getName(ArrayList<String> familyNameList, ArrayList<String> boyNameList,
                                             ArrayList<String> girlNameList, int bCount, int gCount) {

        //定义集合存储生成的不重复的男生名字
        HashSet<String> boyList = new HashSet<>();

        //生成男生名字
        while (true) {
            //存够数量跳出
            if (boyList.size() == bCount) {
                break;
            }
            //打乱集合中的内容
            Collections.shuffle(familyNameList);
            Collections.shuffle(boyNameList);
            //将打乱后的集合的0索引位置的姓和名拼接并标注男生,添加到男生名字集合中
            boyList.add(familyNameList.get(0) + boyNameList.get(0) + "-男");
        }

        //定义集合存储生成的不重复的女生名字
        HashSet<String> girlList = new HashSet<>();
        while (true) {
            //存够数量跳出
            if (girlList.size() == gCount) {
                break;
            }
            //打乱集合中的内容
            Collections.shuffle(familyNameList);
            Collections.shuffle(girlNameList);
            //将打乱后的集合的0索引位置的姓和名拼接并标注女生,添加到女生名字集合中
            girlList.add(familyNameList.get(0) + girlNameList.get(0) + "-女");
        }

        //定义集合存储生成的名字
        ArrayList<String> nameList = new ArrayList<>();
        //将男女名字集合中的数据放到一个集合中,方便返回
        for (String s : boyList) {
            nameList.add(s);
        }
        for (String s : girlList) {
            nameList.add(s);
        }

        return nameList;
    }


    //正则表达式
    private static ArrayList<String> getData(String str, String regex) {
        //定义集合存储符合正则表达式的数据
        ArrayList<String> list = new ArrayList<>();

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);
        while (m.find()) {
            String s = m.group();
            list.add(s);
        }

        return list;

    }


    //网络爬取
    private static String webCrawler(String web) throws IOException {

        //获取网址对象
        URL url = new URL(web);
        //让程序连接网址
        URLConnection uc = url.openConnection();
        //读取网址内的数据:
        //得到得到连接网址的字节输入流
        InputStream is = uc.getInputStream();
        //利用转换流将字节流转换为字符流方便读中文
        InputStreamReader isr = new InputStreamReader(is);
        //定义StringBuilder用于拼接读到的数据
        StringBuilder sb = new StringBuilder();
        //开始读
        int b;
        while ((b = isr.read()) != -1) {
            sb.append((char) b);
        }
        //读完关流
        isr.close();
        //返回读到的数据
        return sb.toString();
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到