正则表达式(就是一种规则)与基础爬虫匹配
复习下之前的方法:
str.startswitch(“0”) 判断字符串是不是以0开头
Character.isDigit(char) 判断一个char类型字符是否是数字
1、⭐小例子
设定注册qq号必须为6-20位,且必须是数字,0不能开头
原始解法:
public static void main(String[] args) {
String qq = "243523523523523501234567890";
System.out.println(checkQQ(qq));
}
private static boolean checkQQ(String qq) {
// 长度判断
if (qq.length() < 0 || qq.length() > 20) {
return false;
}
// 如果第一个是0就返回false
if (qq.startsWith("0")) {
return false;
}
// 判断是否都是数字
for (int i = 0; i < qq.length(); i++) {
if (qq.charAt(i)<'0'||qq.charAt(i)>'9'){
return false;
}
}
return true;
}
正则表达式解法str.matches(“规则”)
public static void main(String[] args) {
String qq = "24352352352390";
// 第一位:1-9 \\d必须是数字 {start,end}数字个数的范围,最多有end个数,最少start位
// 意思就是 第一位只能是1-9的数字 后面只能是5-19个数字
System.out.println(qq.matches("[1-9]\\d{5,19}"));
}
2、正式介绍
⭐API帮助文档pattern
public static void main(String[] args) {
/*
验证手机号码 13112345678 13712345667 13945679927 139456799271
验证座机电话号码 020-2324242 02122442 027-42424 0712-3242434
验证邮箱号码 3232323@qq.com zhangsan@itcast.cnn dlei9@163.com dleieee9@pci.com.cn
*/
// 第一部分@的左边:\w+
// 可以是一个或者多个的字母数字下划线
// 第二部分:@ :这个符号有且仅有一次
// 第三部分@的右边:
// 3.1 点的左边:[\\w&&[^_]]{2,6} :可以是数字和字母不能是下划线2位到6位
// 3.2 点的必须有 \\.
// 3.3 点的右边:[a-zA-Z]{2,3} 可以是大小写英文2到3位
// 注意:这里可能会出现1到两次的域名例如:dleieee9@pci.com.cn分组处理用(){1,2}:(\.[a-zA-Z]{2,3}){1,2}
String emailRegex = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
String email1 = "3232323@qq.com";
String email2 = "zhangsan@itcast.cnn";
String email3 = "dlei9@163.com";
String email4 = "dleieee9@pci.com.cn";
System.out.println(email1.matches(emailRegex));
System.out.println(email2.matches(emailRegex));
System.out.println(email3.matches(emailRegex));
System.out.println(email4.matches(emailRegex));
System.out.println("------------------------------------------");
// ?代表0次或者1次
// 一、区号 0\d{2,3}
// 0:第一位必须是0;
// \d{2,3}:从第二位开始可以是任意数字,2到3位
// 二、- 出现一次或者0次用?
// 三、号码第一位不能0开头,第二位开始可以是任意数字,长度为5-10位
String telephoneNumberRegex = "0\\d{2,3}-?[1-9]\\d{4,9}";
String telephoneNumber1 = "020-2324242";
String telephoneNumber2 = "02122442";
String telephoneNumber3 = "027-42424";
String telephoneNumber4 = "0712-3242434";
System.out.println(telephoneNumber1.matches(telephoneNumberRegex));
System.out.println(telephoneNumber2.matches(telephoneNumberRegex));
System.out.println(telephoneNumber3.matches(telephoneNumberRegex));
System.out.println(telephoneNumber4.matches(telephoneNumberRegex));
System.out.println("------------------------------------------");
String iphoneNumberRegex = "1[3-9]\\d{9}";
String iphoneNumber1 = "13112345678";
String iphoneNumber2 = "1945679927";
String iphoneNumber3 = "12112345678";
String iphoneNumber4 = "23112345678";
System.out.println(iphoneNumber1.matches(iphoneNumberRegex));//true
System.out.println(iphoneNumber2.matches(iphoneNumberRegex));//false
System.out.println(iphoneNumber3.matches(iphoneNumberRegex));//false
System.out.println(iphoneNumber4.matches(iphoneNumberRegex));//false
}
3、插件 idea中点击setting 进入plugins 搜索any-rule
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LVKWN1E-1673759570549)(E:\Java\Java笔记\image\1673676804109.jpg)]
右击字符串显示anyRule出现各种规则,然后根据所得进行修改即可
4、例题
public static void main(String[] args) {
// 例题:用户用的正则表达式:字母数字下划线4-16位
String regex1="\\w{4,16}";
System.out.println("zhangsan123".matches(regex1)); //true
System.out.println("_23276".matches(regex1)); //true
System.out.println("weasd_wead222".matches(regex1)); //true
// 身份证号正则表达式:18位,前17位是任意数字,最后一位是数字或者是X或者x
System.out.println("=============================");
String regex2="[1-9]\\d{16}[Xx\\d]";
String regex3="[1-9]\\d{16}(\\d|((?i)x))";//忽略x的大小写
System.out.println("374535198802123012".matches(regex2));
System.out.println("37142512980214502X".matches(regex2));
System.out.println("=============================");
// 忽略大小写(?i)abc
System.out.println("aBC".matches("(?i)abc"));//true
System.out.println("374535198802123012".matches(regex3));
System.out.println("37142512980214502X".matches(regex3));
String ID="410801 1993 02 28 457x";
// 身份证号码的严格校验
// 前面6位,省份,市区,派出所等信息 第一位不能是0,后面5位是任意数 [1-9]\\d{5}
// 年的前半:18,19,20 (18|19|20)
// 年的后半:任意数字出现两次 \\d{2}
// 月份:第一位是0第二位就是任意数字,第一位是1第二位就是0-2 ((0\\d)|(1[0-2]))
// 日:0~31 (([0][1-9])|([1-2][\d])|(3[0-1]))
// 最后4位:前3位就是任意数字,最后一位就是x或者X或者任意数字 \d{3}(\d|((?i)x))
String regex4="[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0][1-9])|([1-2][\\d])|(3[0-1]))\\d{3}(\\d|((?i)x))";
System.out.println("41080119930228457x".matches(regex4));
}
常用符号
(?i)xxxx;忽略xxxx的大小写
String txt="Xx";
System.out.println(txt.matches("(?i)xx"))//true
System.out.println(txt.matches("(?i)Xx"))//true
System.out.println(txt.matches("(?i)XX"))//true
xxx(?=bb);?代表前面的xxx =表示xxx后面要跟随的数据bb;但是获取的时候只获取前半部分也就是 xxx
String txt="abc1是abc的第一部分,abc2是abc的第二部分";
Pattern compile = Pattern.compile("abc(?=1|2)");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
// 输出结果:爬取的是后面带有1或者2的数据 并且只显示前半部分
abc
abc
xxx(?:bb);?代表前面的xxx =表示xxx后面要跟随的数据bb;但是获取的时候全部获取
String txt="abc1是abc的第一部分,abc2是abc的第二部分";
Pattern compile = Pattern.compile("abc(?:1|2)");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
// 输出结果:爬取的是后面带有1或者2的数据,并且显示全部
abc1
abc2
xxx(?!bb);xxx后面不是bb的数据,只显示前半部分
String txt="abc1是abc的第一部分,abc2是abc的第二部分";
Pattern compile = Pattern.compile("abc(?!1|2)");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
// 输出结果:爬取的不是后面带有1和2的abc数据,并且只显示前半部分
abc
abc
5、爬虫案例
解析
public static void main(String[] args) {
String txt="Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本," +
"下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
// Pattern:表示正则表达式
// Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。
// 在大串中去找符合匹配规格的子串
// 获得一个正则表达式的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
// 获得文本匹配器的对象
// matcher:文本匹配器的对象
// txt:就是大串
// p就是规则
// matcher需要在txt中去找符合规则的子串
Matcher matcher = p.matcher(txt);
// 拿着文本匹配器去从头开始查找,如果找到就返回true 没找到返回false
// 底层会记录字串的:起始索引和结束索引+1
boolean b1 = matcher.find();
// 该方法会根据find()方法底层记录的索引去截取字符串
// 其实底层调用的subString(起始,结束)包头不包尾 :subString(0,4) ->Java
String group1 = matcher.group();
System.out.println(group1);
// 去当前位置去寻找第二个符合规则的字符串 记录索引
boolean b2 = matcher.find();
String group2 = matcher.group();
System.out.println(group2);
System.out.println(b2);
}
正式书写:打印出所有符合正则表达式的内容
public static void main(String[] args) {
String txt = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本," +
"下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
conformToRegex(txt);
}
public static void conformToRegex(String txt) {
Pattern regex = Pattern.compile("Java\\d{0,2}");
Matcher txtMatcher = regex.matcher(txt);
while (txtMatcher.find()) {
System.out.println(txtMatcher.group());
}
}
// 输出结果
Java
Java8
Java11
Java17
Java17
爬虫复习例子
public static void main(String[] args) {
// 需求:把下面文本中的电话,邮箱,手机号,热线都爬取出来。
String message = "来黑马程序员学习Java\n" +
"电话:18512516758,18512508907或者联系邮箱: boniu@itcast.cn,\n" +
"座机电话: 01036517895,010-98951256\n" +
"邮箱: bozai@itcast.cn\n" +
"热线电话: 400-618-9090,400-618-4000,4006184000,4006189090";
// 爬取电话号码
findIphoneNumber(message);
// 爬取邮箱
findEmail(message);
// 爬取座机号码
findTeleNumber(message);
// 爬取热线
findHotLine(message);
}
private static void findHotLine(String message) {
Pattern hotLinePattern = Pattern.compile("([1-9]\\d{2}-?){2}[1-9]\\d{3}");
Matcher matcher = hotLinePattern.matcher(message);
while (matcher.find()){
System.out.println(matcher.group());
}
}
private static void findTeleNumber(String message) {
Pattern teleNumberPattern = Pattern.compile("0\\d{2,3}-?[1-9]\\d{7}");
Matcher matcher = teleNumberPattern.matcher(message);
while (matcher.find()){
System.out.println(matcher.group());
}
}
private static void findEmail(String message) {
Pattern emailPattern = Pattern.compile("\\w+@[\\w&&[^_]]{2,6}(\\.(cn|com)){1,2}");
Matcher matcher = emailPattern.matcher(message);
while (matcher.find()){
System.out.println(matcher.group());
}
}
private static void findIphoneNumber(String message) {
Pattern iphoneNumberPattern = Pattern.compile("1[3-9]\\d{9}");
Matcher matcher = iphoneNumberPattern.matcher(message);
while (matcher.find()){
System.out.println(matcher.group());
}
}
带有条件的爬虫
public static void main(String[] args) {
String txt = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本," +
"下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
// 爬取java后面有版本号,但是还不显示版本号的数据 Java、Java、Java
findJava(txt);
// 爬取java后面有版本号,并且显示版本号 例如:Java8、Java11、Java17、Java17
findJava1(txt);
// 爬取除了版本号为:Java8、Java11、Java17的Java数据 例如:Java
findJava2(txt);
}
private static void findJava2(String txt) {
Pattern compile = Pattern.compile("(?i)java(?!8|11|17)");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
private static void findJava1(String txt) {
Pattern compile = Pattern.compile("(?i)Java(?:\\d{1,2})");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
private static void findJava(String txt) {
// 注释: xxx(?=) ->这里的?代表前面的xxx,=后面是xxx后面要拼接的字符串
// 这里的意思就是Java8/Java11/Java17都可以 但是不显示后面的
Pattern compile = Pattern.compile("(?i)Java(?=8|11|17)");
Matcher matcher = compile.matcher(txt);
while (matcher.find()) {
System.out.println(matcher.group());
}
}