package com.athena.asm.tool.infosense; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 从文本中解析出可能的电子邮件地址 * @author aleck * * Email地址的详细定义可以参见: * http://en.wikipedia.org/wiki/E-mail_address#Valid_email_addresses * http://en.wikipedia.org/wiki/Hostname * 虽然Email地址本身约束很宽松,文中提到不同运营商会加入很多限制,而且各家不尽相同。 * 所以这里还是尽量以自己的理解,处理生活中常见的情况 * 1. LocalPart 可以出现[&'+-=_] + [a-z] + [A-Z] + [0-9] * 2. LocalPart 可以出现".",前提是不是第一个或者最后一个字符 * 3. DomainPart 是一个Hostname,可以出现的字符有 [a-z] + [A-Z] + [0-9] + [-] + [.] * 4. DomainPart 由'.'分割为若干段,每一段不能由'-'或者数字开头也不能由'-'结尾 * * 在此基础上,本函数识别如下不规范的写法 * 1. '@'和'.'的前后可以有空格 * 2. '@' 可以使用 "#", " at ", "_at_", "(at)"代替 * 3. '.' 可以使用" dot ", "_dot_", "(dot)", "点"代替 * */ public class EmailAddrSensor extends Sensor { protected EmailAddrSensor() { super(Type.EMAIL_ADDR); } private static final Pattern email = Pattern.compile( // local part, group 1 "(([&'+\\-=_a-zA-Z0-9]+(\\.|_dot_|\\s*(点|\\sdot\\s|\\(dot\\))\\s*))*[&'+\\-=_a-zA-Z0-9]+)" + // @, group 3 "(\\s*(@|#|\\sat\\s|_at_|\\(at\\))\\s*)" + // domain part 4 "(([a-zA-Z]+[a-zA-Z0-9\\-]*(\\.|_dot_|\\s*(点|\\sdot\\s|\\(dot\\))\\s*))*[a-zA-Z]+[a-zA-Z0-9\\-]*)" ); private String normalize(String raw) { // this is a naive implementation, forgive me return raw.replaceAll("(#|_at_|\\(at\\))", "@") .replaceAll("(点|\\s+dot\\s+|_dot_|\\(dot\\))", ".") .replaceAll("\\s+", ""); } @Override public List<Info> scan(CharSequence text) { List<Info> ret = new ArrayList<Info>(); Matcher matcher = email.matcher(text); while (matcher.find()) { String original = matcher.group(); String content = normalize(original); ret.add(new Info(Type.EMAIL_ADDR, content, original, matcher.start())); } return ret; } }