Use regular expressions to crawl data and some methods of using regular expressions

1.8 Local data crawling

Pattern: Represents a regular expression Matcher: A text matcher that reads strings according to the rules of regular expressions, starting from the beginning. Find substrings that match the matching rules in the large string.

Code example:

package com.itheima.a08regexdemo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo6 {
    public static void main(String[] args) {
        /* 有如下文本,请按照要求爬取数据。
                Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,
                因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台
                要求:找出里面所有的JavaXX
         */
        String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
        //1.获取正则表达式的对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //2.获取文本匹配器的对象
        //拿着m去读取str,找符合p规则的子串
        Matcher m = p.matcher(str);
        //3.利用循环获取
        while (m.find()) {
            String s = m.group();
            System.out.println(s);
        }
    }
    private static void method1(String str) {
        //Pattern:表示正则表达式
        //Matcher: 文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。
        //          在大串中去找符合匹配规则的子串。
        //获取正则表达式的对象
        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);
    }
}

1.9 Web data crawling (understanding)

need:

Crawl out all the ID numbers in the link: https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i.

Code example:

public class RegexDemo7 {
    public static void main(String[] args) throws IOException {
        /* 扩展需求2:
            把连接:https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i
            中所有的身份证号码都爬取出来。
        */
        //创建一个URL对象
        URL url = new URL("https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i");
        //连接上这个网址
        //细节:保证网络是畅通
        URLConnection conn = url.openConnection();//创建一个对象去读取网络中的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        //获取正则表达式的对象pattern
        String regex = "[1-9]\\d{17}";
        Pattern pattern = Pattern.compile(regex);//在读取的时候每次读一整行
        while ((line = br.readLine()) != null) {
            //拿着文本匹配器的对象matcher按照pattern的规则去读取当前的这一行信息
            Matcher matcher = pattern.matcher(line);
            while (matcher.find()) {
                System.out.println(matcher.group());
            }
        }
        br.close();
    }
}

1.10 Crawling data practice

need:

Crawl out the landline phone number, email address, mobile phone number, and hotline in the text below.

Come to Black Horse Programmer to learn Java, mobile phone number: 18512516758, 18512508907 or email: [email protected] , landline phone: 01036517895, 010-98951256 email: [email protected] , hotline: 400-618-9090, 400- The regular expression of 618-4000, 4006184000, 4006189090 mobile phone number: 1[3-9]\d{9}

Code example:

package com.itheima.a08regexdemo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo8 {
    public static void main(String[] args) {
        /*
            需求:把下面文本中的座机电话,邮箱,手机号,热线都爬取出来。
            来黑马程序员学习Java,
            手机号:18512516758,18512508907或者联系邮箱:[email protected]
            座机电话:01036517895,010-98951256邮箱:[email protected]
            热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090
            手机号的正则表达式:1[3-9]\d{9}
            邮箱的正则表达式:\w+@[\w&&[^_]]{2,6}(\.[a-zA-Z]{2,3}){1,2}座机电话的正则表达式:θ\d{2,3}-?[1-9]\d{4,9}
            热线电话的正则表达式:400-?[1-9]\\d{2}-?[1-9]\\d{3}
        */
        String s = "来黑马程序员学习Java," +
                "电话:18512516758,18512508907" + "或者联系邮箱:[email protected]," +
                "座机电话:01036517895,010-98951256" + "邮箱:[email protected]," +
                "热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090";
        System.out.println("400-618-9090");
        String regex = "(1[3-9]\\d{9})|(\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2})" +
                "|(0\\d{2,3}-?[1-9]\\d{4,9})" +
                "(400-?[1-9]\\d{2}-?[1-9]\\d{3})";
        //1.获取正则表达式的对象
        Pattern p = Pattern.compile(regex);
        //2.获取文本匹配器的对象
        //利用m去读取s,会按照p的规则找里面的小串
        Matcher m = p.matcher(s);
        //3.利用循环获取每一个数据 while(m.find()){
        String str = m.group();
        System.out.println(str);
    }
}

1.11 Crawl as required

need:

With the following text, crawl data as required.

Since Java came out in 1995, it has experienced many versions. At present, Java8 and Java11 are the most used in enterprises, because these two are long-term support versions, and the next long-term support version is Java17. I believe that Java17 will gradually be released in the near future. on the stage of history.

Requirement 1:

Crawl the Java text whose version numbers are 8 and 11.17, but as long as Java is used, the version number is not displayed.

Requirement 2:

Crawl the Java text whose version numbers are 8, 11, and 17. The correct crawling results are: Java8 Java11 Java17 Java17

Requirement 3:

Crawl Java text except version numbers 8, 11, and 17. Code example:

public class RegexDemo9 {
    public static void main(String[] args) {
        /*
            有如下文本,按要求爬取数据。
                Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,
                因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台
            需求1:爬取版本号为8,11.17的Java文本,但是只要Java,不显示版本号。
            需求2:爬取版本号为8,11,17的Java文本。正确爬取结果为:Java8 Java11 Java17 Java17
            需求3:爬取除了版本号为8,11.17的Java文本,
        */
        String s = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
            "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
        //1.定义正则表达式
        //?理解为前面的数据Java
        //=表示在Java后面要跟随的数据
        //但是在获取的时候,只获取前半部分
        //需求1:
        String regex1 = "((?i)Java)(?=8|11|17)";
        //需求2:
        String regex2 = "((?i)Java)(8|11|17)";
        String regex3 = "((?i)Java)(?:8|11|17)";
        //需求3:
        String regex4 = "((?i)Java)(?!8|11|17)";
        Pattern p = Pattern.compile(regex4);
        Matcher m = p.matcher(s);
        while (m.find()) {
            System.out.println(m.group());
        }
    }
}

1.12 Greedy crawling and non-greedy crawling

Only write + and means greedy matching, if you add a question mark after + and means non-greedy crawling
+? non-greedy matching
*? non-greedy matching
Greedy crawling: Get as much data as possible when crawling data
Non-greedy crawling: Get as little data as possible when crawling data
Example:
If get data: ab+
Greedy crawling to get the result: abbbbbbbbbbbb
Non-greedy crawling to obtain results: ab

Code example:

public class RegexDemo10 {
    public static void main(String[] args) {
        /*
            只写+和*表示贪婪匹配
            +? 非贪婪匹配
            *? 非贪婪匹配
            贪婪爬取:在爬取数据的时候尽可能的多获取数据
            非贪婪爬取:在爬取数据的时候尽可能的少获取数据
            ab+:
            贪婪爬取:abbbbbbbbbbbb
            非贪婪爬取:ab
        */
        String s = "Java自从95年问世以来,abbbbbbbbbbbbaaaaaaaaaaaaaaaaaa" +
                "经历了很多版木,目前企业中用的最多的是]ava8和]ava11,因为这两个是长期支持版木。" +
                "下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
        String regex = "ab+";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(s);
        while (m.find()) {
            System.out.println(m.group());
        }
    }
}

1.13 Use regular expressions in String's split method

  • The prototype of the replaceAll() method of the String class:

public String replaceAll(String regex,String newStr)
//参数regex表示一个正则表达式。可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。
  • Code example:

/*
            有一段字符串:小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠
            要求1:把字符串中三个姓名之间的字母替换为vs
            要求2:把字符串中的三个姓名切割出来*/
String s = "小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠";
//细节:
//方法在底层跟之前一样也会创建文本解析器的对象
//然后从头开始去读取字符串中的内容,只要有满足的,那么就用第一个参数去替换。
String result1 = s.replaceAll("[\\w&&[^_]]+", "vs");
System.out.println(result1);

1.15 Regular expression - grouping brackets ( )

Details: How to identify the group number?

Only look at the left brackets, do not look at the brackets, according to the order of the left brackets, from left to right, the first group, the second group, the third group, etc.

/
//需求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&&
//(.):把首字母看做一组
// \\2:把首字母拿出来再次使用
// *:作用于\\2,表示后面重复的内容出现日次或多次
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));

1.16 Group exercises

need:

Will the string: I want to learn programming programming.

Replace with: I want to learn programming

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

1.17 Ignore case-insensitive writing

//(?i) :表示忽略后面数据的大小写
//忽略abc的大小写
String regex = "(?i)abc";
//a需要一模一样,忽略bc的大小写
String regex = "a(?i)bc";
//ac需要一模一样,忽略b的大小写
String regex = "a((?i)b)c";

1.18 Non-capturing packets

Non-capturing grouping: After grouping, there is no need to use this group of data, just enclose the data.

//身份证号码的简易正则表达式
//非捕获分组:仅仅是把数据括起来
//特点:不占用组号
//这里\\1报错原因:(?:)就是非捕获分组,此时是不占用组号的。
//(?:) (?=) (?!)都是非捕获分组//更多的使用第一个
//String regex1 ="[1-9]\\d{16}(?:\\d|x|x)\\1";
String regex2 ="[1-9]\\d{16}(\\d Xx)\\1";
//^([01]\d|2[0-3]):[0-5]\d:[@-5]\d$
System.out.println("41080119930228457x".matches(regex2));

1.19 Regular Expression Exercises

手机号码:1[3-9]\\d{9}
座机号码:0\\d{2,3}-?[1-9]\\d{4,9}
邮箱号码:\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}
24小时:([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d
       ([01]\\d|2[0-3])(:[0-5]\\d){2}
用户名:    \\w{4,16}
身份证号码,简单校验:
        [1-9]\\d{16}(\\d|X|x)
        [1-9]\\d{16}[\\dXx]
        [1-9]\\d{16}(\\d(?i)X)
身份证号码,严格校验:
        [1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9|[12])\\d|3[01])\\d{3}[\\dXx]

Guess you like

Origin blog.csdn.net/qq_69748833/article/details/132645256