黑马程序员——JAVA基础之正则表达式,网络爬虫
正则表达式:
概念:用于操作字符串的符合一定规则的表达式
特点:用于一些特定的符号来表示一些代码的操作,可以调用底层的代码对字符串进行操作。简化了代码的书写。
正则表达式利弊:
好处:正则的出现,对字符串的复杂操作变得更为简单。
弊端:符号的出现虽然简化了书写,但是却降低了阅读性。
常用符号:
构造 | 匹配 |
---|---|
|
|
字符 | |
x | 字符 x |
\\ | 反斜线字符 |
\0n |
带有八进制值 0 的字符 n (0 |
\0nn |
带有八进制值 0 的字符 nn (0 |
\0mnn |
带有八进制值 0 的字符 mnn(0 |
\xhh |
带有十六进制值 |
\uhhhh |
带有十六进制值 |
\t | 制表符 ('\u0009') |
\n | 新行(换行)符 ('\u000A') |
\r | 回车符 ('\u000D') |
\f | 换页符 ('\u000C') |
\a | 报警 (bell) 符 ('\u0007') |
\e | 转义符 ('\u001B') |
\cx | 对应于 x 的控制符 |
|
|||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
Greedy 数量词 | |
---|---|
X? | X,一次或一次也没有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,但是不超过 m 次 |
Reluctant 数量词 | |
---|---|
X?? | X,一次或一次也没有 |
X*? | X,零次或多次 |
X+? | X,一次或多次 |
X{n}? | X,恰好 n 次 |
X{n,}? | X,至少 n 次 |
X{n,m}? | X,至少 n 次,但是不超过 m 次 |
常见操作:
到底用四种功能中的哪一个呢?或者哪几个呢?
思路方式:
1,如果只想知道该字符是否对是错,使用匹配。
2,想要将已有的字符串变成另一个字符串,替换。
3,想要按照自定的方式将字符串变成多个字符串。切割。获取规则以外的子串。
4,想要拿到符合需求的字符串子串,获取。获取符合规则的子串。
匹配:其实用的就是String类中的matches方法。
/** * 匹配: * 手机号段只有 13xxx 15xxx 18xxxx * */ public class CheckDemo { public static void main(String[] args) { String tel = "15394485938"; String telReg = "1[358]\\d{9}"; System.out.println(tel.matches(telReg)); } }
切割:其实用的就是String类中的split方法。
/** * 切割: * 切割演示 */ public class SplitDemo { public static void main(String[] args) { splitDemo("sdwdwd","w"); } public static void splitDemo(String str,String reg) { String[] arr = str.split(reg); System.out.println(arr.length); for(String s : arr) { System.out.println(s); } } }
import java.util.TreeSet; /** 需求: 将ip地址进行地址段顺序的排序。 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.301 思路: 还按照字符串自然顺序,只要让他们每一段都是3位即可。 1、按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。 2、将每一段只保留3位。这样,所有的ip地址都是每一段3位。 */ public class SplitTest { public static void main(String[] args) { String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30"; ip = ip.replaceAll("(\\d+)","00$1");//保证每段至少三位 System.out.println(ip); ip = ip.replaceAll("0*(\\d{3})","$1");//每段只保留三位 System.out.println(ip); String[] arr = ip.split(" ");//按照空格切 TreeSet<String> ts = new TreeSet<String>();//定义一个TreeSet集合,利用元素自然排序 for(String s : arr) { ts.add(s); } for(String s : ts) { System.out.println(s.replaceAll("0*(\\d+)","$1"));//把每段前面多余的0替换掉 } } }
按叠词完成切割:为了让规则被重用,可将规则封装成一个组,用()完成。组的出现都有编号,从1开始。想要使用已有的组可通过\n(n就是组的编号)的形式来获取。
组:
用小括号标示,每定义一个小括号,就是一个组,而且有自动编号,从1开始。
只要使用组,对应的数字就是使用该组的内容。别忘了,数组要加\\。
(aaa(wwww(ccc))(eee))技巧,从左括号开始数即可。有几个左括号就是几组。
对于组中所匹配的字符,可以用$n来获取。$在正则中表示行的结尾,所以出现在正则中不能用来表示组,一般用于替换中。
替换:其实用的就是String类中的replaceAll();
/** * 替换演示: * */ public class ReDemo { public static void main(String[] args) { String str = "我我...我我...我要..要要...要要...进进进....进进...黑黑黑...黑马..马.马马...马...马"; str = str.replaceAll("\\.+",""); System.out.println(str); str = str.replaceAll("(.)\\1+","$1"); System.out.println(str); } }
获取:
先要将正则表达式编译成正则对象。使用的是Pattern中静态方法 compile(regex);
通过Pattern对象获取Matcher对象。
Pattern用于描述正则表达式,可以对正则表达式进行解析。
而将规则操作字符串,需要从新封装到匹配器对象Matcher中。然后使用Matcher对象的方法来操作字符串。
如何获取匹配器对象:通过Pattern对象中的matcher方法。该方法可以正则规则和字符串想关联。并返回匹配器对象。
使用Matcher对象中的方法即可对字符串进行各种正则操作。
/** * 获取:将字符串中的符合规则的子串取出。 * */ import java.util.regex.*; class RegexDemo2 { public static void main(String[] args) { getDemo(); } public static void getDemo() { String str = "ming tian jiu yao fang jia le ,da jia。"; System.out.println(str); String reg = "\\b[a-z]{4}\\b"; //将规则封装成对象。 Pattern p = Pattern.compile(reg); //让正则对象和要作用的字符串相关联。获取匹配器对象。 Matcher m = p.matcher(str); while(m.find()) { System.out.println(m.group()); System.out.println(m.start()+"...."+m.end()); } } }
网络爬虫(蜘蛛)
实际上是一个功能,用于搜集网络上的指定信息
可用于收集邮箱,qq号等之类的信息。
如通过关键字搜索blog,实际就是使用的“蜘蛛”,通过查找关键字获取相关的blog
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.regex.Matcher; import java.util.regex.Pattern; public class GetWebMail { //获取网页中mail public static void main (String[] args) throws Exception { //封装网页地址 URL url=new URL("http://tieba.baidu.com/p/1390896758"); //连接服务器 URLConnection conn=url.openConnection(); //带缓冲区的网页读取流 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line=null; //定义匹配邮件地址的正则表达式 String regex="\\w+@\\w+(\\.\\w+)+"; Pattern p=Pattern.compile(regex);//封装正则表达式 //读取网页数据 while ((line=br.readLine())!=null) { //正则关联数据 Matcher m=p.matcher(line); //寻找匹配邮箱 while (m.find()) { System.out.println(m.group());//输出匹配邮箱 } } } }
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.regex.Matcher; import java.util.regex.Pattern; public class GetFileMail { //获取文件中mail public static void main (String[] args) throws Exception { //将文件封装成对象 File file=new File("E:\\mail.txt"); //创建带缓冲区的读取流 BufferedReader br=new BufferedReader(new FileReader(file)); String line=null; //定义正则表达式 String regex="\\w+@[a-zA-Z]+(\\.[a-zA-z]+)+"; //创建Pattern对象,封装正则表达式 Pattern p=Pattern.compile(regex); //读取文件中数据 while ((line=br.readLine())!=null) { //关流字符串 Matcher m=p.matcher(line); while (m.find())//寻找匹配的字符串 { System.out.println(m.group());//输出匹配的字符串 } } } }