从网页中提取日期

时间:2011-05-23 16:50:23

标签: java jquery date extraction selenium-webdriver

我想从网页中提取不同格式的日期。我正在使用Selenium2 Java API与浏览器进行交互。我还使用jQuery进一步与文档交互。因此,欢迎两层的解决方案。

日期可以在不同的区域设置中具有非常不同的格式。此外,月份名称可以写为文本或数字。我需要尽可能多地匹配日期,并且我知道有很多组合。

例如,如果我有这样的HTML元素:

<div class="tag_view">
    Last update: May,22,2011 
    View :40
</div>

我希望提取和识别日期的相关部分:

May,22,2011

现在应将其转换为常规Java Date对象。

更新

这应该适用于来自任何网页的HTML,日期可以包含在任何格式的任何元素中。例如,在Stackoverflow上,源代码如下所示:

<span class="relativetime" title="2011-05-13 14:45:06Z">May 13 at 14:45</span>

我希望它以最有效的方式完成,我想这将是一个返回标准化日期表示的jQuery选择器或过滤器。但我愿意接受你的建议。

3 个答案:

答案 0 :(得分:1)

由于我们不能将自己局限于任何特定元素类型或任何元素的子元素,因此您基本上都在讨论搜索整个页面的文本以查找日期。以任何效率执行此操作的唯一方法是使用正则表达式。由于您正在寻找任何格式的日期,因此您需要为每种可接受的格式使用正则表达式。一旦你定义了那些是什么,只需编译正则表达式并运行如下:

var datePatterns = new Array();
datePatterns.push(/\d\d\/\d\d\/\d\d\d\d/g);
datePatterns.push(/\d\d\d\d\/\d\d\/\d\d/g);
...

var stringToSearch = $('body').html(); // change this to be more specific if at all possible
var allMatches = new Array();
for (datePatternIndex in datePatterns){
    allMatches.push(stringToSearch.match(datePatterns[datePatternIndex]));
}

您可以通过Google搜索找到更多日期正则表达式,或者自己创建它们,它们非常简单。有一点需要注意:您可以将上面的一些正则表达式组合起来以创建更高效​​的程序。我会非常小心,这可能会导致您的代码很难快速阅读。每个日期格式执行一个正则表达式似乎更清晰。

答案 1 :(得分:0)

您可以考虑使用getText获取元素文本,然后拆分String,如 -

String s = selenium.getText("css=span.relativetime");
String date = s.split("Last update:")[1].split("View :")[0];

答案 2 :(得分:0)

我自己会回答这个问题,因为我想出了一个有效的解决方案。我很感激评论。

/**
 * Extract date
 * 
 * @return Date object
 * @throws ParseException 
 */
public Date extractDate(String text) throws ParseException {
    Date date = null;
    boolean dateFound = false;

    String year = null;
    String month = null;
    String monthName = null;
    String day = null;
    String hour = null;
    String minute = null;
    String second = null;
    String ampm = null;

    String regexDelimiter = "[-:\\/.,]";
    String regexDay = "((?:[0-2]?\\d{1})|(?:[3][01]{1}))";
    String regexMonth = "(?:([0]?[1-9]|[1][012])|(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))";
    String regexYear = "((?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3}))";
    String regexHourMinuteSecond = "(?:(?:\\s)((?:[0-1][0-9])|(?:[2][0-3])|(?:[0-9])):([0-5][0-9])(?::([0-5][0-9]))?(?:\\s?(am|AM|pm|PM))?)?";
    String regexEndswith = "(?![\\d])";

    // DD/MM/YYYY
    String regexDateEuropean =
        regexDay + regexDelimiter + regexMonth + regexDelimiter + regexYear + regexHourMinuteSecond + regexEndswith;

    // MM/DD/YYYY
    String regexDateAmerican =
        regexMonth + regexDelimiter + regexDay + regexDelimiter + regexYear + regexHourMinuteSecond + regexEndswith;

    // YYYY/MM/DD
    String regexDateTechnical =
        regexYear + regexDelimiter + regexMonth + regexDelimiter + regexDay + regexHourMinuteSecond + regexEndswith;

    // see if there are any matches
    Matcher m = checkDatePattern(regexDateEuropean, text);
    if (m.find()) {
        day = m.group(1);
        month = m.group(2);
        monthName = m.group(3);
        year = m.group(4);
        hour = m.group(5);
        minute = m.group(6);
        second = m.group(7);
        ampm = m.group(8);
        dateFound = true;
    }

    if(!dateFound) {
        m = checkDatePattern(regexDateAmerican, text);
        if (m.find()) {
            month = m.group(1);
            monthName = m.group(2);
            day = m.group(3);
            year = m.group(4);
            hour = m.group(5);
            minute = m.group(6);
            second = m.group(7);
            ampm = m.group(8);
            dateFound = true;
        }
    }

    if(!dateFound) {
        m = checkDatePattern(regexDateTechnical, text);
        if (m.find()) {
            year = m.group(1);
            month = m.group(2);
            monthName = m.group(3);
            day = m.group(3);
            hour = m.group(5);
            minute = m.group(6);
            second = m.group(7);
            ampm = m.group(8);
            dateFound = true;
        }
    }

    // construct date object if date was found
    if(dateFound) {
        String dateFormatPattern = "";
        String dayPattern = "";
        String dateString = "";

        if(day != null) {
            dayPattern = "d" + (day.length() == 2 ? "d" : "");
        }

        if(day != null && month != null && year != null) {
            dateFormatPattern = "yyyy MM " + dayPattern;
            dateString = year + " " + month + " " + day;
        } else if(monthName != null) {
            if(monthName.length() == 3) dateFormatPattern = "yyyy MMM " + dayPattern;
            else dateFormatPattern = "yyyy MMMM " + dayPattern;
            dateString = year + " " + monthName + " " + day;
        }

        if(hour != null && minute != null) {
            //TODO ampm
            dateFormatPattern += " hh:mm";
            dateString += " " + hour + ":" + minute;
            if(second != null) {
                dateFormatPattern += ":ss";
                dateString += ":" + second;
            }
        }

        if(!dateFormatPattern.equals("") && !dateString.equals("")) {
            //TODO support different locales
            SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatPattern.trim(), Locale.US);
            date = dateFormat.parse(dateString.trim());
        }
    }

    return date;
}

private Matcher checkDatePattern(String regex, String text) {
    Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    return p.matcher(text);
}