快捷搜索:  汽车  科技

用正则表达式做简单日期(一起来写个通用时间正则表达式匹配吧)

用正则表达式做简单日期(一起来写个通用时间正则表达式匹配吧)xx时间前:2017-09-25 18:59:48 2017年09月25日18:59:54年月日 时分:2017-09-25 18:59 2017/09/25 18:59年月日 时分秒:

正则表达式在我爬虫开发中用的很频繁。尤其是当XPath和cssSelector 有心无力的时候。

现在,我遇到了一个这样的问题。我要爬取几十个网站的文章页,但是可能每个网站有自己的格式,我要汇总各种网站格式,然后将时间戳抽取出来。网站时间格式大致如下:

  • 年月日:

  • 2017-09-25 2017/09/25 2017.09.25 2017年09月25日

  • 年月日 时分:

  • 2017-09-25 18:59 2017/09/25 18:59

  • 年月日 时分秒:

  • 2017-09-25 18:59:48 2017年09月25日18:59:54

  • xx时间前:

  • 1分钟前 1 小时前 1天前 (这里暂时不考虑英文,其实差不多)

先把正则表达式放出来

(20\d{2}([\.\-/|年月\s]{1 3}\d{1 2}){2}日?(\s?\d{2}:\d{2}(:\d{2})?)?)|(\d{1 2}\s?(分钟|小时|天)前)

然后是结果

用正则表达式做简单日期(一起来写个通用时间正则表达式匹配吧)(1)

接下来我们就来构造这正则表达式

咋一看,挺复杂的正则表达式,但是无非就是那些语法构成,只要耐心点就很容易写出来

首先,我们要匹配日期,日期无非就 xxxxxx 这种格式,我们要主义的是三串数字之间的字符 比如 2017-09-25 2017/09/25 2017.09.25 这种无非就是分隔符的微弱区别。而我要抓的也仅是20xx年以后的东西,所以我可以这样写:

20\d{2}表示年份 d{1 2}表示月日 因为月份有 2 和02 两种情况

而中间的符号,常见的有 . \ 空格 中文这几种情况,根据自己需求可以酌情添加。

这样我们就把中间符号正则写出来了- [\.\-/|年月\s] .和- 需要转义,

还要注意的是 中文的时间后边可能会有个 日 字 所以也要匹配上 当然你可以选择用 * 但是我感觉效率应该没有固定了的高

接下来我们就该匹配时间了,时间这个相对简单,因为格式相对固定,区别在于有没有秒数。

根据之前的规则,我们可以很轻易写出 (\s\d{2}:\d{2}(:\d{2})?)?这里不再赘述。

然后是匹配 某个xx之前,这里需要注意的是,数字有一位或者两位之分以及数字和文字之间是否有空格,根据需求写出\d{1 2}\s?(分钟|小时|天)前

剩下的就是拼接了,日期和时间点之间是或的关系,所以需要 | 符号,

就这样一个正则表达式就写出来了

补上测试代码:

time_test = ['2017年09月25日' '2017-09-25' '2017/09/25' '2017 09 25' '2017年09月25日19:13:33' '2017-09-25 19:13:40' '1小时前' '1 天前'] for i in time_test: post_time = re.search( '(20\d{2}([\.\-/|年月\s]{1 3}\d{1 2}){2}日?(\s?\d{2}:\d{2}(:\d{2})?)?)|(\d{1 2}\s?(分钟|小时|天)前)' i) print(post_time)

正文结束,接下来是怎样将时间转换为时间戳,这里我用到了一个第三方库dateparser

附上相关代码

#!/usr/bin/env python # -*- coding: utf-8 -*- import re import dateparser import time import random time_re = re.compile('[年月日\s]') def generate_timestamp(post_time): now = int(time.time()) date_time = dateparser.parse(time_re.sub(' ' post_time)) if date_time: time_stamp = int(date_time.timestamp()) else: return now if time_stamp > now: time_stamp = now - random.randint(0 600) return time_stamp

猜您喜欢: