2.常用API(爬虫,正则表达式)

常用API(爬虫,正则表达式)

爬虫

​ 本地爬虫:Pattern:表示正则表达式;
​ Matcher:文本匹配器,作用按照正则表达式的规则读取字符串,从头开始读取,在大串中去找符合匹配规则的子串;
​ find:1.拿着文本匹配器从头开始读取,寻找是否有满足规则的子串;如果没有,方法返回false;如果有:返回true。在 底层记录子串的起始索引和结束索引+1(包头不包尾巴);
​ 2.第二次在调用find的时候,会继续读取后面的内容;读取到第二个满足要求的子串,方法会继续返回true;并把 第二个子串的起始索引和结束索引+1,进行记录;
​ group:方法底层会根据find方法记录的索引进行字符串的截取;第二次调用group方法的时候,会根据find方法记录的索 引再次截取子串;
​ 例子:

package com.caihongjia.a07regexdemo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo03 {
    public static void main(String[] args) {
        String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,"+
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信未来不久Java17也会逐渐登上历史舞台";

        //method1();

        //1.获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //2.获取文本匹配器的对象
        Matcher m = p.matcher(str);

        //3.利用循环获取
        while(m.find()){
            String s = m.group();
            System.out.println(s);
        }

    }

    private static void method1() {

        String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,"+
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信未来不久Java117也会逐渐登上历史舞台";


        //Pattern:表示正则表达式
        //Matches:文本匹配器,作用按照正则表达式的规则读取字符串,从头开始读取
        //          在大串中去找符合匹配规则的子串。

        //获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //获取文本匹配器的对象
        //m:文本匹配器的对象
        //str:大串
        //p:规则
        //m要在str中找符合p规则的小串
        Matcher m = p.matcher(str);

        //拿着文本匹配器从头开始读取,寻找是否有满足规则的子串
        //如果没有,方法返回false
        //如果有:返回true。在底层记录子串的起始索引和结束索引+1
        //0,4
        boolean b = m.find();

        //方法底层会根据find方法记录的索引进行字符串的截取
        //subString(起始索引,结束索引);包头不包尾
        //(0,4)但是不包含4索引
        //会把截取的小串进行返回
        String s1 = m.group();
        System.out.println(s1);

        //第二次在调用find的时候,会继续读取后面的内容
        //读取到第二个满足要求的子串,方法会继续返回true
        //并把第二个子串的起始索引和结束索引+1,进行记录
        b = m.find();

        //第二次调用group方法的时候,会根据find方法记录的索引再次截取子串
        String s2 = m.group();
        System.out.println(s2);

        boolean b1 = m.find();
        String s3 = m.group();
        System.out.println(s3);
    }
}

​ 有条件的爬取:?理解为前面的数据Java
​ =表示在Java后面要跟随的数据,但是在获取的时候,只获取前半部分
​ :表示在Java后面要跟随的数据,但是在获取的时候,获取全部数据
​ !表示在Java后面要跟随的数据,获取除了与后面数据有关的以外的全部前面数据

​ 例子:

package com.caihongjia.a07regexdemo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo04 {
    public static void main(String[] args) {
        /*
        需求1:爬取版本号为8,11,17的Java文本,但是只要Java,不显示版本号
        需求2:爬取版本号为8,11,17的Java文本,正确爬取结果为:Java8 Java11 Java17
        需求3:爬取版本号为8,11,17的Java文本

        */
        String str = "java自从95年问世以来,经历了很多版本,目前企业中用的最多的是JAva8和Java11,"+
                "因为这两个是长期支持版本,下一个长期支持版本是JAVa17,相信未来不久JAVA17也会逐渐登上历史舞台";

        //1.定义正则表达式
        //2.?理解为前面的数据Java
        //3.=表示在Java后面要跟随的数据
        //4.但是在获取的时候,只获取前半部分
        //需求1
        String regex1 = "((?i)Java)(?=8|17|11)"; //?i忽略大小写
        //需求2
        String regex2 = "((?i)Java)(8|17|11)";
        String regex3 = "((?i)Java)(?:8|17|11)";
        //需求3
        String regex4 = "((?i)Java)(?!8|17|11)";

        Pattern p = Pattern.compile(regex4);
        Matcher m = p.matcher(str);

        while(m.find()){
            System.out.println(m.group());
        }
        System.out.println("============================");


    }
}

​ 贪婪爬取:在爬取数据的时候尽可能的多获取数据,Java中,默认的就是贪婪爬取 ab+

​ 非贪婪爬取:在爬取数据的时候尽可能的少获取数据,如果我们在数量词+或者* 的后面加上问号,那么此时就是非贪婪爬取 ab+?

​ 例子:

package com.caihongjia.a07regexdemo;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo05 {
    public static void main(String[] args) {
        //贪婪爬取:在爬取数据的时候尽可能的多获取数据    ab+
        //非贪婪爬取:在爬取数据的时候尽可能的少获取数据  ab+?

        //ab+:
        //贪婪爬取:abbbbbbbb
        //非贪婪爬取:ab

        //Java中,默认的就是贪婪爬取
        //如果我们在数量词+或者* 的后面加上问号,那么此时就是非贪婪爬取

        String str = "java自从95年问世以来,abbbbbbbbbbbbbbb经历了很多版本,目前企业中用的最多的是JAva8和Java11,"+
                "因为这两个是长期支持版本,下一个长期支持版本是JAVa17,相信未来不久JAVA17也会逐渐登上历史舞台";

        String regex = "ab+?";

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);

        while(m.find()){
            System.out.println(m.group());
        }
    }
}

​ 正则表达式补充方法:

​ replaceAll(String regex,String newStr) :按照正则表达式的规则进行替换
​ 细节:方法在底层跟之前一样也会创建文本解析器的对象
​ 然后从头开始去读取字符串中的内容,只要有满足的,那么就使用第二个参数去替换

​ 例子:

package com.caihongjia.a07regexdemo;

public class RegexDemo06 {
    public static void main(String[] args) {
        //public String replaceAll(String regex,String newStr)      按照正则表达式的规则进行替换
        //Public String[] split(String regex)                       按照正则表达式的规则切割字符串

        /*
        有一段字符串:小诗诗qwertyuiop123小丹丹qwertyuiop123小慧慧
        要求1:把字符串中三个名字之间的字母替换为vs
        要求2:把字符串中的三个名字分割出来

        */

        String s = "小诗诗qwertyuiop123小丹丹qwertyuiop123小慧慧";
        //细节:
        //方法在底层跟之前一样也会创建文本解析器的对象
        //然后从头开始去读取字符串中的内容,只要有满足的,那么就使用第二个参数去替换
        String result1 = s.replaceAll("[\\w&&[^_]]+", "vs");
        System.out.println(result1);

    }
}

​ split(String regex):按照正则表达式的规则切割字符串

​ 例子:

package com.caihongjia.a07regexdemo;

public class RegexDemo06 {
    public static void main(String[] args) {
        //public String replaceAll(String regex,String newStr)      按照正则表达式的规则进行替换
        //Public String[] split(String regex)                       按照正则表达式的规则切割字符串

        /*
        有一段字符串:小诗诗qwertyuiop123小丹丹qwertyuiop123小慧慧
        要求1:把字符串中三个名字之间的字母替换为vs
        要求2:把字符串中的三个名字分割出来

        */

        String s = "小诗诗qwertyuiop123小丹丹qwertyuiop123小慧慧";
        //细节:
        //方法在底层跟之前一样也会创建文本解析器的对象
        //然后从头开始去读取字符串中的内容,只要有满足的,那么就使用第二个参数去替换
//        String result1 = s.replaceAll("[\\w&&[^_]]+", "vs");
//        System.out.println(result1);

        String[] arr = s.split("[\\w&&[^_]]+");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        

    }
}

​ 正则表达式分组:捕获分组和非捕获分组

​ 捕获分组:
​ 概念:可以获取每组中的内容反复使用;
​ 组号的特点:从1开始,连续不间断;以左括号为基准,最左边的是第一组;
​ 非捕获分组:
​ 概念:分组之后不需要再用本组数据,仅仅把数据括起来,不占组号;
​ (?😃(?=)(?!)都是非捕获分组;
​ 例子:

package com.caihongjia.a07regexdemo;

public class RegexDemo07 {
    public static void main(String[] args) {
        //分组:
        //每组是有组号的,也就是序号。
        //规则1:从1开始,连续不间断
        //规则2:以左括号为基准,最左边的是第一组,其次为第二组,以此类推


        //需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
        //举例:a123a     b456b       17891       &abc&       a123b(false)
        //  \\组号:表示把第x组的内容再出来用一次
        String regex1 = "(.).+\\1";
        System.out.println("a123a".matches(regex1));
        System.out.println("b456b".matches(regex1));
        System.out.println("17891".matches(regex1));
        System.out.println("&abc&".matches(regex1));
        System.out.println("a123b".matches(regex1));
        System.out.println("--------------------------------------");


        //需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
        //举例:abc123abc      b456b       123789123       &!@abc&!@       abc123abd(false)
        String regex2 = "(.+).+\\1";
        System.out.println("abc123abc".matches(regex2));
        System.out.println("b456b".matches(regex2));
        System.out.println("123789123".matches(regex2));
        System.out.println("&!@abc&!@".matches(regex2));
        System.out.println("abc123abd".matches(regex2));
        System.out.println("--------------------------------------");


        //需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
        //举例:aaa123aaa      bbb456bbb       111789111       &&abc&&
        //* 0次或多次

        //(.):把首字母看做一组
        // \\1:把首字母拿出来再次使用
        // *:作用于\\1,表示后面重复的内容出现0次或多次
        String regex3 = "((.)\\2*).+\\1";
        System.out.println("aaa123aaa".matches(regex3));
        System.out.println("bbb456bbb".matches(regex3));
        System.out.println("111789111".matches(regex3));
        System.out.println("&&abc&&".matches(regex3));
        System.out.println("aaa123aab".matches(regex3));
        System.out.println("--------------------------------------");

    }
}
package com.caihongjia.a07regexdemo;

public class RegexDemo08 {
    public static void main(String[] args) {
        //捕获分组:后续还要继续使用本组的数据
        //正则内部使用:\\组号
        //正则外部使用:\\$组号

        /*
        需求:
            将字符串:我要学学编编编编程程程程程程
             替换为:我要学编程
         */

        String str = "我要学学编编编编程程程程程程";

        //需求:把重复的内容 替换为 单个的
        //学学        学
        //编编编编     编
        //程程程程程程  程
        //(.):表示把重复内容的第一个字符看做一组
        //\\1表示第一字符再次出现
        //+ 至少一次
        //$1:   表示把正则表达式中第一组的内容,再拿出来用
        String s1 = str.replaceAll("(.)\\1+", "$1");
        System.out.println(s1);
    }
}
package com.caihongjia.a07regexdemo;

public class RegexDemo09 {
    public static void main(String[] args) {
        /*
            非捕获分组:分组之后不需要再用本组数据,仅仅是把数据括起来

            身份证号码:
            41080119930228457x
            510801197609022309
            15040119810705387X

        */

        //身份证号码的简易正则表达式
        //非捕获分组:仅仅是把数据括起来
        //特点:不占用组号
        //这里\\1报错原因:(?:)就是非捕获分组,此时是不占用组号的。

        //(?:)  (?=)  (?!) 都是非捕获分组‘
        //更多使用第一个
        String regex1 = "[1-9]\\d{16}(?:\\d|X|x)\\1";
        String regex2 = "[1-9]\\d{16}(\\d|X|x)\\1";

        System.out.println("41080119930228457x".matches(regex));

    }
}
posted @ 2023-04-17 21:41  回家太晚太悲催  阅读(59)  评论(0)    收藏  举报