Java正则表达式学习笔记,分离网页邮件地址的蜘蛛程序

引言

RegularExpressions(正则表达式)非常强大,可以极大的减轻我们日常写程序时处理字符串的负担。这两天学习了一下正则表达式,做了一些学习笔记,每一个知识点后面都有详细的例子,分享给大家。文章最后是我写的一个简单的分离网页中的邮件地址的蜘蛛程序,供大家一起交流学习。


1.  用途

正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

2.  使用Pattern和Matcher

涉及到的类为:java.util.regex.Pattern、java.util.regex.Matcher和java.lang.String
//编译一个正则表达式模式,匹配时按照其语法规则,编译之后匹配效率高
Pattern pa=Pattern.compile("[\\w]+"); 
//生成一个匹配器对象
Matcher m=pa.matcher("abcd1234");
//matches: 用模式匹配整个字符串
m.matches();
//find: 用模式匹配符合要求的子串(从当前位置开始匹配)
m.find();
//group:返回匹配成功的子串
m.group();
//lookingAt:每次从头开始,用模式匹配符合要求的子串
m.lookingAt();

3.  次数符号

包括:X*,X+,X?,X{n},X{n,},X{n,m}
“X*” :X出现0次或多次
“X+”:X出现1次或多次
“X?”:X出现0次或1次
“X{n}”:X正好出现n次
“X{n,}”:X至少出现n次
“X{n,m}”:X至少出现n次不多于m次
System.out.print("aaaa".matches("a{4}"));             
System.out.print("127.23.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
System.out.print("214523145234532".matches("\\d{3,100}"));
输出:
true;    false;    true;

4.  范围符号

“[ …]”:表示从中括号以内的字符集合里中取一个字符;
“^”:表示取反
“[^ …]”:表示从中括号以内的字符集合的补集中取一个字符
System.out.print("a".matches("[^bacdefg]"));
//下面三种都是或者的意思:or
System.out.print("a".matches("[a-zA-Z]"));
System.out.print("a".matches("[a-z]|[A-Z]"));
System.out.print("a".matches("[a-z[A-Z]]"));
//求两部分的交集,然后再取值
System.out.print("a".matches("[a-z&&[A-Z]]"));
System.out.print("a".matches("[a-z&&[^A-Z]]"));
输出:false;    true;    true;    true;    false;    false;

5.  转意字符

在RegularExpressions里面一个"\"(反斜杠本身)在代码层面需要"\\\\"表示 。因为在字符串层面表示一个"\"(反斜杠本身)需要"\\"表示,字符串变成RegularExpressions时 ,"\"同样表示转意字符,即在字符串和RegularExpressions里面 "\"都是转意字符,如果真实需要一个"\"(反斜杠本身)要用一个"\"转意另外一个"\"才能表示。 
System.out.print("\\".matches("\\\\"));
输出:true;

6.  边界符号

“^”没在中括号里面时,表示一行的第一个字符;$表示一行的最后一个字符。
System.out.print("hello sir".matches("^h[a-zA-Z[ ]]*r$"));
System.out.print("hello sir".matches(".+o\\s[a-z]{1,3}r$"));
//检验一篇文章是否为空白行,一行开头即换行不是空白行
System.out.print(" \n".matches("^[\\s&&[^\\n]].*\\n$"));
输出:true;    true;    true;

7.  替换方法

实现把匹配的字符串全部替换为特定的字符串 。
Pattern pa=Pattern.compile("java",Pattern.CASE_INSENSITIVE);
Matcher m=pa.matcher("Java JAVA i lOVE java YOU hate JaVa ,dO You jAvA 01234567890");
//sb用来装替换的之后的字符串
StringBuffer sb=new StringBuffer();
 while(m.find())
{
       //这里面还可以实现更加精确的控制,比如说奇数和偶数替换成不同的
        m.appendReplacement(sb,"JAJA");
}
//把余下的没有匹配成功的字符串添加到末尾
m.appendTail(sb);
p(sb);

8.  分组符号

用一对“()”表示分组。RegularExpressions从左数起,"("出现的次序即为组号 。
Pattern pa=Pattern.compile("^[1-3](\\w{1,3})([0-9]*([A-Z]$))");
//1组:(\\w{1,3}) 结果:sd0
//2组:([0-9]*([A-Z]$)) 结果:1234567890H
//3组:([A-Z]$) 结果:H
Matcher m=pa.matcher("1sd01234567890H");
p(m.find());
p(m.group(2));

9.  配合Find使用的函数

Pattern pa=Pattern.compile("[\\w]+"); 
Matcher m=pa.matcher("abcd1234");
m.find();
使用Find方法后,可以使用group()、start()和end()方法。
group:返回匹配成功的子串;
如果找到了子串可以使用start()和end()方法查看子串在母串中的位子。
start:返回找到的子串的开始位置;
end:返回找到的子串的最后一个字符的后一个位置;

10.  匹配模式

Greedy quantifiers为贪婪的匹配方式,默认为这种方式 ;
例如:[A-Z]{5,10}它每次总是先吞10字符看能不能匹配,不能的话再吐一个再匹配 ;
Greedy quantifiers写法:[A-Z]{5,10},a+ ;
Reluctant quantifiers和Greedy quantifiers相反,总是先吞最少个数的 ;
Reluctant quantifiers写法:[A-Z]{5,10}?,a+?(后面都有一个问号);

11.  可分离网页中的邮件地址的简单蜘蛛程序

本程序仅为单机使用,即把网页下载处理。
/**
 * 利用正则表达式,分离出网址中的邮箱地址
 * @author 忘川
 */
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EmailSpider
{
    public static void main(String[] args) throws UnsupportedEncodingException, IOException
    {
        System.out.print("请输入文件路径或文件夹路径:");
        Scanner scan = new Scanner(System.in);
        getFiles(scan.nextLine());
       
        for (Iterator<File> i = _allFiles.iterator(); i.hasNext();)
        {
            File file = i.next();
            String name = file.getName();
            //从后缀为.html和.htm的文件中寻找邮件地址,过滤无用的文件
            if (file.getName().matches(".+\\.html$") || file.getName().matches(".+\\.htm$"))
            {
                spider(file);
            }
        }
        BufferedWriter bWriter = new BufferedWriter(new FileWriter(".\\email.txt"));
        for (Iterator<Map.Entry<Integer, String>> i = email.entrySet().iterator(); i.hasNext();)
        {
            Map.Entry<Integer, String> kv = i.next();
            bWriter.write(kv.getKey() + "\t" + kv.getValue() + "\r\n");
        }
        bWriter.flush();
        bWriter.close();
    }
    private static List<File> _allFiles = new ArrayList<File>();
    private static Map<Integer, String> email = new HashMap<Integer, String>();
    private static int Number = 0;
    private static void spider(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
    {
        InputStreamReader inre = new InputStreamReader(new FileInputStream(file), "GBK");
        BufferedReader bReader = new BufferedReader(inre);
        String line = "";
        //编译一个正则表达式
        Pattern pa = Pattern.compile("[\\w[-.]]+@[\\w]+\\.[a-zA-Z[.]]+");
        Matcher m = null;
        while ((line = bReader.readLine()) != null)
        {
            //生成一个匹配器
            m = pa.matcher(line);
            //寻找匹配的子串
            while (m.find())
            {
                //返回匹配成功(即符合模式)子串
                String adress = m.group();
                //去掉email后面的“.”,发生的概率1/100左右
                while (adress.endsWith("."))
                {
                    adress = adress.substring(0, adress.length() - 1);
                }
                //去掉重复的email地址
                if (!email.containsValue(adress))
                {
                    email.put(Number++, adress);
                }
            }
        }
        bReader.close();
    }
    private static void getFiles(String path)
    {
        File file = new File(path);
        if (file.isFile())
        {
            _allFiles.add(file);
            return;
        } else
        {
            File[] list = file.listFiles();
            for (File f : list)
            {
                getFiles(f.getPath());
            }
        }
    }
}
部分结果:

序号      邮件地址
435      szsl8@sina.com 
436      yaxu520@163.com 
437      xhngweigrass@yahoo.com.cn 
438      915650881@qq.com 
439      aji301314@163.com 
440      197008946@qq.com 
441      294470767@qq.com 
442      imei598@163.com 
443      16717890@QQ.COM 
444      618168737@qq.com 
445      lubirdhui@163.com 
446      benmaofc7496@163.com 
447      yp867107@163.com 

测试了几个网页,从其中分离处理1000多个邮件地址,以上为部分结果。公布的邮箱地址经过手动脱敏处理,仅用来说明程序的性能,不涉及个人隐私。垃圾邮寄每日困扰这我们的生活,希望大家谨慎在网页上留下邮箱地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值