爬虫
一、正则表达式的作用
1、作用一
- 校验字符串是否满足规则
2、作用二
- 在一段文本中查找满足要求的内容
二、练习:本地爬虫和网络爬虫
1、本地爬虫
- 有如下文本,请按照要求爬取数据。
- Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台
- 要求:找出里面所有的JavaXX
package com.app.demo27_regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test3 {
public static void main(String[] args) {
/*
正则表达式的作用:爬虫
本地爬虫:
有如下文本,请按照要求爬取数据:
Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,
因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台
要求:找出里面所有的JavaXX
*/
String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
"因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
method1(str);
System.out.println("------------------------------");
// 1.获取正则表达式的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
// 2.获取文本匹配器的对象
Matcher m = p.matcher(str);
// 3.利用循环寻找符合规则的子串
while (m.find()) {
// 4.输出符合规则的子串
System.out.println(m.group());
}
}
private static void method1(String str) {
/*
Pattern: 表示正则表达式
Matcher: 文本匹配器,作用是按照正则表达式的规则去读取字符串,从头开始读取。
在大串中去找符合匹配规则的子串。
*/
// 1.获取正则表达式的对象
Pattern p = Pattern.compile("Java\\d{0,2}");
/*
2.获取文本匹配器的对象
m: 文本匹配器的对象
str: 大串
p: 规则
意思: m要在str中找符合p规则的小串
*/
Matcher m = p.matcher(str);
/*
拿着文本匹配其从头开始读取,寻找是否有满足规则的子串
如果没有,find()方法返回false
如果有,返回true。在底层会记录子串的起始索引和结束索引+1:
假如字符串:Java自从95年
匹配到Java,则记录Java子串的起始索引为0,结束索引为3+1=4
(0,4)
*/
boolean b = m.find();
/*
group()方法底层会根据find()方法记录的索引进行字符串的截取:
subString(起始索引, 结束索引); 包头不包尾
(0, 4) 截取时,不包含4索引的数据
group()方法最终会把截取的小串返回
*/
String s1 = m.group();
System.out.println(s1);
/*
第二次调用find()方法的时候,会继续读取后面的内容
读取到第二个满足规则的子串,find()方法会继续返回true
并把第二个子串的起始索引和结束索引+1,进行记录
*/
b = m.find();
// 第二次调用group()方法的时候,会根据find()方法记录的索引再次截取子串
String s2 = m.group();
System.out.println(s2);
}
}
Java
Java8
------------------------------
Java
Java8
Java11
Java17
Java17
Process finished with exit code 0
2、网络爬虫
- 把链接:http://ent.cctv.com/lm/494/-1/54463.html中所有的身份证号码都爬取出来。
package com.app.demo27_regex;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test4 {
public static void main(String[] args) throws Exception {
/*
扩展练习:正则表达式的作用-网络爬虫
把链接:http://ent.cctv.com/lm/494/-1/54463.html
中所有的身份证号码都爬取出来。
*/
// 1.创建一个URL对象
URL url = new URL("http://ent.cctv.com/lm/494/-1/54463.html");
// 2.连接上这个网址
URLConnection conn = url.openConnection();
// 3.创建一个字符缓冲输入流对象去读取网络中的数据
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// 4.定义一个空字符串用于接收按照行读取到的数据
String line;
// 5.获取正则表达式的对象 pattern
String regex = "[1-9]\\d{17}";
Pattern pattern = Pattern.compile(regex);
// 6.在读取的时候每次读取一整行
while ((line = br.readLine()) != null) {
// 7.拿着文本匹配器的对象matcher按照pattern的规则去读取当前的这一行信息
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
// 8.输出读取到的当前行信息
System.out.println(matcher.group());
}
}
// 8.关闭流,释放资源
br.close();
}
}
410802197407191510
432623197801303011
410329197212250114
420105197812270020
110105197105175312
421022198301257824
370602198301275418
110102955100408672
370602198108300239
142601197107251920
110228197504206729
Process finished with exit code 0
3、练习
-
需求:把下面文本中的座机电话、邮箱、手机号码、热线都爬取出来。
来黑马程序员学习Java, 手机号:18512516758,18512508907 或者联系邮箱:boniu@itcast.cn, 座机电话:01036517898,010-98951256 邮箱:bozai@itcast.cn, 热线电话:400-618-9090,400-618-4000,4006184000,4006189090
-
分析:
-
手机号的正则表达式:
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}
-
package com.app.demo27_regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test5 {
public static void main(String[] args) {
/*
正则表达式练习:
需求:把下面文本中的座机电话、邮箱、手机号码、热线都爬取出来。
来黑马程序员学习Java,
手机号:18512516758,18512508907
或者联系邮箱:boniu@itcast.cn,
座机电话:01036517898,010-98951256
邮箱:bozai@itcast.cn,
热线电话:400-618-9090,400-618-4000,4006184000,4006189090
分析:
手机号的正则表达式: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}
*/
String str = "来黑马程序员学习Java,\n" +
"手机号:18512516758,18512508907\n" +
"或者联系邮箱:boniu@itcast.cn,\n" +
"座机电话:01036517898,010-98951256\n" +
"邮箱:bozai@itcast.cn,\n" +
"热线电话:400-618-9090,400-618-4000,4006184000,4006189090";
// 1.获取正则表达式的对象
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})";
Pattern p = Pattern.compile(regex);
// 2.获取文本匹配器的对象
// 利用m去读取str,会按照p的规则找里面的小串
Matcher m = p.matcher(str);
// 3.利用循环获取每一个数据
while (m.find()) {
// 4.输出符合规则的数据
System.out.println(m.group());
}
}
}
18512516758
18512508907
boniu@itcast.cn
01036517898
010-98951256
bozai@itcast.cn
400-618-9090
400-618-4000
4006184000
4006189090
Process finished with exit code 0
三、带条件爬取
- 有如下文本,请按照要求爬取数据。
- java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17,相信在未来不久JAVA17也会逐渐登上历史舞台。
- 需求1:爬取版本号为8,11,17的Java文本,但是只要Java,忽略大小写,不显示版本号
- 需求2:爬取版本号为8,11,17的Java文本,忽略大小写,显示版本号
- 需求3:爬取除了版本号为8,11,17的Java文本
package com.app.demo27_regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test6 {
public static void main(String[] args) {
/*
正则表达式的作用-爬虫:
带条件的爬取数据:
- 有如下文本,请按照要求爬取数据。
- java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本,
下一个长期支持版本是JAVa17,相信在未来不久JAVA17也会逐渐登上历史舞台。
- 需求1:爬取版本号为8,11,17的Java文本,但是只要Java,忽略大小写,不显示版本号
- 需求2:爬取版本号为8,11,17的Java文本,忽略大小写,显示版本号
- 需求3:爬取除了版本号为8,11,17的Java文本
*/
String str = "java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本," +
"下一个长期支持版本是JAVa17,相信在未来不久JAVA17也会逐渐登上历史舞台。";
// 1.需求一:定义正则表达式
/*
?: 理解为前面的数据Java
=: 表示在Java后面要跟随的数据
但是在获取的时候,只获取前半部分
*/
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)";
reptile(str, regex1);
System.out.println();
reptile(str, regex2);
reptile(str, regex3);
System.out.println();
reptile(str, regex4);
}
/**
* 爬虫
* @param str 数据
* @param regex1 正则表达式
*/
private static void reptile(String str, String regex1) {
// 获取正则表达式的对象
Pattern p = Pattern.compile(regex1);
// 获取文本匹配器的对象,利用m去读取str,会按照p的规则找里面的小串
Matcher m = p.matcher(str);
// 利用循环获取每一个数据
while (m.find()) {
// 输出获取到的每一个数据
System.out.println(m.group());
}
}
}
Java
JAva
JAVa
JAVA
Java8
JAva11
JAVa17
JAVA17
Java8
JAva11
JAVa17
JAVA17
java
Process finished with exit code 0
四、贪婪爬取和非贪婪爬取
-
有如下文本,请按照要求爬取数据。
-
java自从95年问世以来,abbbbbbbbbbaaaaaaaaaaaaaaaaaaa
经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17,相信在未来不久JAVA17也会逐渐登上历史舞台。
-
-
需求1:按照ab+的方式爬取ab,b尽可能多获取
-
需求2:按照ab+的方式爬取ab,b尽可能少获取
package com.app.demo27_regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test7 {
public static void main(String[] args) {
/*
贪婪爬取和非贪婪爬取:
只写+或*表示贪婪匹配
+?或*?表示非贪婪匹配
贪婪爬取:在爬取数据的时候尽可能的多获取数据
非贪婪爬取:在爬取数据的时候尽可能的少获取数据
ab+:
贪婪爬取:abbbbbbbbbb
非贪婪爬取:ab
Java当中,默认的就是贪婪爬取
如果我们在数量词+或*的后面加上问号,那么此时就是非贪婪爬取
- java自从95年问世以来,abbbbbbbbbbaaaaaaaaaaaaaaaaaaa
经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17,
相信在未来不久JAVA17也会逐渐登上历史舞台。
- 需求1:按照ab+的方式爬取ab,b尽可能多获取
- 需求2:按照ab+的方式爬取ab,b尽可能少获取
*/
String str = "java自从95年问世以来,abbbbbbbbbbaaaaaaaaaaaaaaaaaaa" +
"经历了很多版本,目前企业中用的最多的是Java8和JAva11,因为这两个是长期支持版本,下一个长期支持版本是JAVa17," +
"相信在未来不久JAVA17也会逐渐登上历史舞台。";
// 需求1:
String regex1 = "ab+";
// 需求2:
String regex2 = "ab+?";
reptile(str, regex1);
reptile(str, regex2);
}
/**
* 爬虫
* @param str 数据
* @param regex 正则表达式
*/
private static void reptile(String str, String regex) {
// 获取正则表达式的对象
Pattern p = Pattern.compile(regex);
// 获取文本匹配器的对象,利用m去读取str,会按照p的规则找出小串
Matcher m = p.matcher(str);
// 利用循环获取每个数据
while (m.find()) {
System.out.println(m.group());
}
}
}
abbbbbbbbbb
ab
Process finished with exit code 0
五、正则表达式在字符串方法中的使用
方法名 | 说明 |
---|---|
public String[] matches(String regex) | 判断字符串是否满足正则表达式的规则 |
public String replaceAll(String regex,String newStr) | 按照正则表达式的规则进行替换 |
public String[] split(String regex) | 按照正则表达式的规则切割字符串 |
-
有一段字符串:
小诗诗fefefefdsdsfdge1232小蛋蛋sgwgkdkdj123123小灰灰
-
需求1:把字符串中三个姓名之间的字符替换为vs
-
需求2:把字符串中三个姓名切割出来
package com.app.demo27_regex;
public class Test8 {
public static void main(String[] args) {
/*
正则表达式在字符串方法中的使用:
- 有一段字符串:
小诗诗fefefefdsdsfdge1232小蛋蛋sgwgkdkdj123123小灰灰
- 需求1:把字符串中三个姓名之间的字符替换为vs
- 需求2:把字符串中三个姓名切割出来
*/
String str = "小诗诗fefefefdsdsfdge1232小蛋蛋sgwgkdkdj123123小灰灰";
// 需求1:
/*
细节:replaceAll方法在底层跟之前一样会创建文本解析器的对象
然后从头开始去读取字符串的内容,只要有满足的,那么就用第二个参数去替换。
*/
String regex1 = "[\\w&&[^_]]+";
String result1 = str.replaceAll(regex1, "vs");
System.out.println(result1);
// 需求2:
String[] arr = str.split(regex1);
for (String s : arr) {
System.out.println(s);
}
}
}
小诗诗vs小蛋蛋vs小灰灰
小诗诗
小蛋蛋
小灰灰
Process finished with exit code 0