JAVA正则表达式第二个作用:爬取

目录

本地数据爬取:

本地爬取练习:

网络爬取:

      -----  以下为均本地数据爬取:

带条件爬取

贪婪爬取和非贪婪爬取:

例题 1:使获取 1 为不贪婪

*例题 2:使获取 0、1 都为不贪婪


之前介绍了正则表达式的语法 和 第一个作用(校验字符串)

本地数据爬取:

目的:获取满足正则表达式规则的所有字符串

先来认识几个名词:

Pattern:表示正则表达式

Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取

本地爬取代码示例:

/* 有如下文本,请按照要求爬取数据。
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:规则
//m要在str中找符合p规则的小串,
Matcher m = p.matcher(str);


//3.循环
//拿着文本匹配器从头开始读取,寻找是否有满足规则的子串
//如果没有,方法返回false
//如果有,返回true。在底层记录子串的起始索引和结束索引+1,
//0,4
while(m.find()){
    String s=m.group();
        sout(s);
}
//方法底层会根据find方法记录的索引进行字符串的截取
//substring(起始索引,结束索引);包头不包尾
//(0,4)但是不包含4索引
//会把截取的小串进行返回。

本地爬取练习:

需求:把下面文本中的座机电话,邮箱,手机号,热线都爬取出来。

手机号的正则表达式:1[3-9]d{9}

邮箱的正则表达式:w+@[w&&[^_]]{2,6}(.[a-zA-Z]{2,3}){1,2}

座机电话的正则表达式:0d{2,3}-?[1-9]d{4,9}

热线电话的正则表达式:400-?[1-9]\d{2}-?[1-9]\d{3}

package pachong;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexDemo8 {

    public static void main(String[] args) {

  

String s = "电话:18512516758,18512508907"+"或者联系邮箱:[email protected]," +
        "座机电话:01036517895,010-12345678" +"邮箱:[email protected]," +
        "热线电话:400-618-9090,400-618-4000,4006184000,4006189090";


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);
            }
        }
}

网络爬取:

网络爬虫暂时混个眼熟:

需求:

把该链接

:悬赏通缉嫌疑人,30名在逃盗抢骗嫌疑人个人资料正脸照曝光(2)_社会新闻_海峡网中所有的身份证号码都爬取出来。

(学习需求)

代码示例:


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

//1.创建一个URL对象
URL url = new URL("http://www.hxnews.com/news/gn/shxw/201811/01/1641427_2.shtml");

//2.连接上这个网络:保证网络是畅通的
URLConnection conn = url.openConnection();

//读取网络数据:将连接转换为输入流,并通过BufferedReader来逐行读取网络返回的数据。
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
//获取正则表达式规则:调用静态方法getRole()获取预先定义好的正则表达式字符串,这个例子中的正则表达式用于匹配中国大陆的严格格式身份证号。
String regex = getRole();
Pattern p = Pattern.compile(regex);

//数据处理和匹配:遍历BufferedReader读取的每一行数据,
// 对每行使用Pattern对象的matcher()方法生成Matcher对象,
// 然后通过Matcher对象的find()方法查找与正则表达式匹配的子串。
// 若找到匹配项,则调用group()方法打印出匹配的字符串。
while ((line = br.readLine()) != null) {
    //m会在line中找符合p规则的小串
    Matcher m = p.matcher(line);
    while(m.find()){
        System.out.println(m.group());
    }
}
//关闭资源:在所有数据处理完成后,关闭BufferedReader以释放系统资源。
br.close();
}
    //获取规则
    public static String getRole() {
        //严格的身份证;
        return "[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]";
    }
}

      -----  以下为均本地数据爬取:

带条件爬取

看下面例题:

文本:

"Windows XP:发布于2001年,Windows Vista:发布于2006年,Windows 7:发布于2009年, Windows 8:发布于2012年,Windows 10:发布于2015年,Windows 11:发布于2021年"

  • 需求1:爬取版本号为Vista、7、8、10、11的Windows文本,(但是只要Windows,不显示版本号)。
  • 需求2:爬取版本号为的Vista、7、8、10、11的Windows文本。正确爬取结果为:Windows Vista Windows 7 Windows 8 Windows 10 Windows 11
  • 需求3:爬取除了版本号为Vista、7、8、10、11的Windows文本,

// 注意:空格

public class Test04_Required02 {
    public static void main(String[] args) {

String s=" Windows XP:发布于2001年,Windows Vista:发布于2006年,Windows 7:发布于2009年," +
" Windows 8:发布于2012年,Windows 10:发布于2015年,Windows 11:发布于2021年";

//1
String regex1="Windows\s(?=Vista|7|8|10|11)";// \s表示空白字符
Pattern p1=Pattern.compile(regex1);
Matcher m = p1.matcher(s);
while(m.find()){
    System.out.println(m.group());
}

//2
String regex2="Windows\s(?:Vista|7|8|10|11)";//?:可省略
Pattern p2=Pattern.compile(regex2);
Matcher m2 = p2.matcher(s);

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

//3:注意
String regex3="Windows\s(?!Vista|7|8|10|11)\w+";
Pattern p3=Pattern.compile(regex3);
Matcher m3 = p3.matcher(s);

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

控制台:

Windows

Windows

Windows

Windows

Windows

Windows Vista

Windows 7

Windows 8

Windows 10

Windows 11

Windows XP

非捕获分组:正则表达式分组括号中介绍


贪婪爬取和非贪婪爬取:

注意:正则表达式规则中的量词才会有贪婪和非贪婪的区别(因为 字符类和与字符类只能匹配单个字符,也就没有贪婪和非贪婪之分)

正则表达式规则中的量词:才会有贪婪和非贪婪的区别。这些量词决定了其前面的表达式匹配字符的次数。

贪婪:它会尽可能多地匹配所涵盖的字符。(默认就是贪婪)

非贪婪:在量词后加上 ? 可以使其变为非贪婪,它会尽可能少地匹配所涵盖的字符。

例如,对于表达式"ab+":

"ab+"将会贪婪地匹配尽可能多的b,即匹配连续出现的b。

贪婪爬取获取结果:abbbbbbbbbbbb

"ab+?"将会非贪婪地匹配尽可能少的b,即只匹配一个b。

非贪婪爬取获取结果:ab

例题 1:使获取 1 为不贪婪

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

String regex="01+?";

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


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

控制台:

01

*例题 2:使获取 0、1 都为不贪婪

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

String regex="0{1}1+?";

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


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

控制台:

01