精华内容
下载资源
问答
  • <li><a href="?bid=2&did=0&eid=1227">高速路上停车捡葫芦引发交通事故一人身亡</a><span>...怎么用正则表达式提取href=“”,“高速。。。身亡”,“2013-09-29”等信息
  • JMeter关联:JMeter正则表达式提取器与JSON提取器

    万次阅读 多人点赞 2019-06-21 17:22:31
    JMeter关联的实现1、关联的释义与简单示例2、常用正则表达式详解3、正则表达式提取器2、JSON值提取 前言:下文中会多次使用到【BeanShell Sampler】和【Debug Sampler】,前者的作用是模拟一个请求,返回自定义的...

    前言

    本文主要内容是:使用使用正则表达式提取器和JSON提取器实现关联。

    下文中会多次使用到BeanShell SamplerDebug Sampler,前者其实是起到一个mock server的作用,返回自定义的响应结果,后者能够输出JMeter的变量情况。

    关于JMeter的使用,花费大量精力写了JMeter的一系列文章,有图有案例,一方面总结起来作为备忘,一方面希望能给初学者一些帮助。觉得有所帮助的朋友,请点个赞,对于疏漏之处也欢迎指教。

    1 关联的释义与示例

    关联在接口测试中是一个非常重要的概念,它的意思是在两个或多个接口间建立逻辑上的依赖与联系。

    关联的使用场景往往要满足以下条件:

    1. A接口响应结果中的数据被后续的接口所引用
    2. A接口响应结果中被后续接口引用的数据是动态变化且无法提前预知的

    例如,登录接口-下订单接口这样2个接口组成的流程,就是非常典型的关联案例。

    首先,登录接口返回包含用户身份认证信息的token,后续的下订单接口需要附带上这个token才能被服务器识别身份。

    Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

    要想实现这个场景,我们需要这么做:

    1. 在登录接口响应结果中将token提取出来并保存在变量中,这里可以使用【正则表达式提取器】和【JSON提取器】。
    2. 在后续接口中引用已经保存好的token,一般通过【HTTP信息头管理器】

    形成的脚本如下。

    1、登录接口的响应结果:

    {
    	"code" : 200,
    	"msg" : "SUCCESS",
    	"data" : {
    		"accessToken" : "PJqx4566Ggf10qJv6firYAFS408p0us",
    		"info" : {
    			"id" : 10000,
    			"level" : 0,
    			"twiceGoogleAuth" : false,
    			"twiceMobileAuth" : true,
    			"twiceEmailAuth" : false,
    			"tradePwdAlways" : false,
    			"tradePwdHours" : false,
    			"lastLoginDate" : null,
    			"lastLoginAddress" : null,
    			"depositFlag" : true,
    			"loginCount" : 0,
    			"emailRegister" : false,
    			"nation" : 211,
    			"webLoginCount" : 0
    		}
    	}
    }
    

    2、从登录接口响应结果中提取token的值,并保存到名称为myToken的变量中:
    在这里插入图片描述

    3、引用前面保存的token值(前面保存变量为什么,这里就引用什么)
    在这里插入图片描述
    4、后续接口中,成功引用了到了myToken的值:
    在这里插入图片描述

    接下来,我们以 WeatherWS 这个网站的两个接口为示例,使用【正则表达式提取器】完成一个关联实现。

    接下来的测试场景是这样的:

    1. 请求 getRegionProvince 接口,得到包含各个省份 code 的列表,并在这个列表里提取北京code
    2. 将北京的 code 作为getSupportCityDataSet接口 theRegionCode 参数的参数值,请求接口得到北京下辖的行政区域列表。

    在这里插入图片描述
    getRegionProvince的接口说明如下:

    GET /WebServices/WeatherWS.asmx/getRegionDataset? HTTP/1.1
    Host: ws.webxml.com.cn
    HTTP/1.1 200 OK
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    
    <?xml version="1.0" encoding="utf-8"?>
    <DataSet xmlns="http://WebXml.com.cn/">
      <schema xmlns="http://www.w3.org/2001/XMLSchema">schema</schema>xml</DataSet>
    

    getSupportCityDataSet的接口说明如下:

    GET /WebServices/WeatherWS.asmx/getSupportCityDataset?theRegionCode=string HTTP/1.1
    Host: ws.webxml.com.cn
    HTTP/1.1 200 OK
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    
    <?xml version="1.0" encoding="utf-8"?>
    <DataSet xmlns="http://WebXml.com.cn/">
      <schema xmlns="http://www.w3.org/2001/XMLSchema">schema</schema>xml</DataSet>
    

    根据上面的接口说明,先建立下面的脚本:
    在这里插入图片描述
    整体的脚本结构如上图所示,下面依次看每个组件的内容和作用。

    1、【HTTP请求】getRegionProvince
    在这里插入图片描述

    1. IP:ws.webxml.com.cn
    2. 路径:/WebServices/WeatherWS.asmx/getRegionDataset
    3. 作用:获得中国省份、直辖市、地区;国家名称(国外)和与之对应的ID
    4. 相应结果(为节省篇幅,删除了大量无关数据):
    <?xml version="1.0" encoding="utf-8"?>
    <DataSet xmlns="http://WebXml.com.cn/">
      <xs:schema id="getRegion" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
      </xs:schema>
      <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
        <getRegion xmlns="">
          <Province diffgr:id="Province5" msdata:rowOrder="4">
            <RegionID>3117</RegionID>
            <RegionName>河北</RegionName>
          </Province> 
          <Province diffgr:id="Province29" msdata:rowOrder="28" diffgr:hasChanges="inserted">
            <RegionID>311101</RegionID>
            <RegionName>北京</RegionName>
          </Province>
         <Country diffgr:id="Country1" msdata:rowOrder="0">
            <RegionID>3320</RegionID>
            <RegionName>阿尔及利亚</RegionName>
          </Country>
        </getRegion>
      </diffgr:diffgram>
    </DataSet>
    

    观察相应结果,北京的RegionID是311101,但如何将它提取出来并保存到变量中呢?这就要用到【正则表达式提取器】了。在HTTP请求getRegionDataset上添加【后置处理器】-【正则表达式提取器】。

    2、【正则表达式提取器】:
    在这里插入图片描述

    1. 引用名称:code,后面引用该值时,将使用${code}的固定写法。
    2. 正则表达式:<RegionID>(.+?)</RegionID>\r\n\ <RegionName>北京</RegionName>,注意中间的8个空格,不能多一个也不能少一个。
    3. 模板:$1$,表示取第一列,下文【正则表达式提取器】会有详细解释。
    4. 匹配数字:1,表示取第一行,下文【正则表达式提取器】会有详细解释。

    3、【HTTP请求】getSupportCityDataSet
    在这里插入图片描述

    1. IP:ws.webxml.com.cn
    2. 路径:/WebServices/WeatherWS.asmx/getSupportCityDataset?theRegionCode=${code}
    3. 作用:获得支持的城市/地区名称和与之对应的ID
    4. 相应结果:
      在这里插入图片描述
      在这里插入图片描述

    2 常用正则表达式详解

    正则表达式描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

    正则表达式是相对繁琐抽象的,理解和记忆难度较高,因此这里对JMeter中能用到的正则表达式语法(主要是限定符)进行一下讲解。

    据我个人经验,(.+?)这个表达式基本就够用了,何况正则表达式提取远不如JSON提取器使用频率高,所以这一节大可以略过,直接看第三节。

    字 符描 述
    .匹配除换行符 \n 之外的任何单字符
    *贪婪,匹配前面的子表达式零次或多次,等价于{0,}
    +占有,匹配前面的子表达式一次或多次,等价于{1,}
    ?懒惰,匹配前面的子表达式零次或一次 ,等价于 {0,1}
    {n}n 是一个非负整数。匹配确定的 n 次。例如a{3}匹配“aaaaa”,能匹配到“aaa”
    {n,m}重复n到m次,例如正则 “a{3,4}” 将a重复匹配3次或者4次
    *?重复任意次,但尽可能少重复,如 “acbacb” 正则 “a.*?b” 只会取到第一个"acb"
    +?重复1次或更多次,但尽可能少重复,与上面一样,不同的是至少重复一次
    ??重复0次或1次,但尽可能少重复,如 “aaacb” 正则 “a.??b” 只会取到最后的三个字符"acb"
    {n,m}?重复n到m次,但尽可能少重复,如 “aaaaaaaa” 正则 “a{0,m}” 因为最少是0次所以取到结果为空
    {n,}?重复n次以上,但尽可能少重复,如 “aaaaaaa” 正则 “a{1,}” 最少是1次所以取到结果为 “a”

    部分表达式使用【正则表达式测试器】实测结果如下:

    1. *:0次或多次,因为0个也被能匹配,所以b、c和末尾被匹配成空
      在这里插入图片描述
    2. +:一个或多个,因为至少要匹配一个,不会有空字符串
      在这里插入图片描述
    3. :0个或一个,同*一样,没有a的被匹配成空字符串
      在这里插入图片描述
    4. a{n}:
      在这里插入图片描述
    5. a{n,m}
      在这里插入图片描述
    6. a{n,}
      在这里插入图片描述

    3 正则表达式提取器

    正则表达式提取器一般在取样器上创建,它的作用是在取样器(包括HTTP请求和BeanShell Sampler及其他取样器)的结果中按照一定的规则提取特定的值,并保存到内存中的某一个字段上,正则表达式所在的取样器之后的组件,都能通过引用方式(格式:${XXX})使用该值。
    在这里插入图片描述

    3.1 参数详解

    名称描述必须
    名称脚本中显示的这个元件的描述性名称
    Apply toMain sample only:仅适用于主样本,默认用这个就可以了
    Field to check要检查的响应字段,即在取样器响应内容的哪个区域进行匹配
    Name of created variable引用名称,即匹配到的变量存储的名称,一般会有[refname]_g(匹配数量)、[refname]_g0 (整体)、[refname]_gn(某个具体匹配值)等多个变量,
    Regular Expression正则表达式,用于分析响应数据的正则表达式,除非使用$0$组,否则必须至少包含一组括号
    Template模板,如果在正则表达式中有多结果,则可以是$2$$3$等等,表示解析到的第几个值给title,如:$1$表示解析到的第1个值
    Match No. (0 for Random)匹配数字,取第几,0代表随机取值,-1代表全部取值,1、2、3等表示多行返回值取第几个值。
    Default Value缺省值,如果表达式没有取得到值,就使用这个默认值
    Use empty default value勾选此项后,如果未提取到值,则给变量赋予空字符串,而不是null

    3.2 使用示例

    先看这么一个场景,假如响应内容ccBBmmAABBAAddBBAA,想在该响应内容中提取AAddBB并存储到参数test中,该如何处理?

    首先,观察待匹配字符串的左右边界分别是BBAA,那么正则表达式应写成BB(.+?)AA,在【正则表达式测试器】中测试一下:
    在这里插入图片描述
    可以看到,第1列(列从0开始计数)第二行是我们想要的结果,因此【正则表达式提取器】中按下图填写:
    在这里插入图片描述
    接下来,我们使用【BeanShell Sampler】模拟服务,来测试一下:
    在这里插入图片描述
    在这里插入图片描述
    HTTP请求IP中引用正则表达式提取器提取到的test
    在这里插入图片描述
    在这里插入图片描述

    4 JSON提取器

    在【后置处理器】中,有一个【JSON提取器】,与【正则表达式提取器】有类似的作用,不同的是,前者专为处理JSON型的响应结果而生。
    在这里插入图片描述

    4.1 参数详解

    名称描述必须
    Name名称,脚本中显示的这个元件的描述性名称
    Names of chreated variables匹配到的数据存储的变量名称,后续可以使用${variable name}引用它
    JSON Path ExpressionsJSON路径表达式
    Default Values默认值,如果JSON 路径表达式未能匹配到值,将使用该默认值
    Match No. (0 for Random)如果匹配到多个结果,选择使用哪个。0代表随机,-1代表全部,x代表第x个
    Compute concatenation var勾选此项后,如果匹配到多个结果,JMeter会使用","将他们连接起来,存储在的变量中

    4.2 使用示例

    接下来,我们看一个示例:

    假如接口返回下面的JSON数据,我们想在其中提取“周芷若”到“name”参数中。

    {
    	"status":200,
    	"data":[{"id":101,"name":"张无忌"},{"id":102,"name":"周芷若"}]
    }
    

    首先,构造脚本结果如下图,【BeanShell Sampler】作为mock server返回上面的数据:
    在这里插入图片描述

    return "{\"status\":200,\"data\":[{\"id\":101,\"name\":\"张无忌\"},{\"id\":102,\"name\":\"周芷若\"}]}";
    

    在【BeanShell Sampler】下面添加【后置处理器】–【JSON Extractor】
    在这里插入图片描述
    这里解释一下【JSON Path expression】的写法,

    • . 首先$.这部分是固定写法
    • data表示在JSON串以"data"为key获取value,也就是"[{\"id\":101,\"name\":\"张无忌\"},{\"id\":102,\"name\":\"周芷若\"}]"。
    • data所对应的值是一个JSONArray(JSON数组)格式,里面有两个JSONObject(JSON对象),第二个JSONObject是我们需要的,因此再按索引值"1"去获取,写作data[1],写到这里,我们得到了{\"id\":102,\"name\":\"周芷若\"}这个JSONObject,接下来再根据name这个key去获取相应的值,就得到"周芷若"了。

    运行脚本,查看结果树中的【Debug Sampler】的响应数据:
    在这里插入图片描述

    后来在自己开发接口自动化框架的过程中,借鉴JMeter的这个功能,做了一个工具类,在响应结果是JSON串的接口中提取数据十分方便。

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * @author guozhengMu
     * @version 1.0
     * @date 2018/12/20 13:07
     * @description 根据自定义的字符串解析提取json中的特定内容
     * @modify
     */
    public class JsonPathExpression {
        public static void main(String[] args) {
            String str = "{\"data\" : {\"deth\" : {\"bids\" : [[\"3.637\", \"360000\"]],\"asks\" : [[\"4.273\", \"662\"],[[{\"a\":[1,2]}]]]}}}";
    //      String result = jsonPathExpression("{\"status\" : 200,\"employees\" : [{\"firstName\" : \"Bill\",\"lastName\" : \"Gates\"}, {\"firstName\" : \"George\",\"lastName\" : \"Bush\"}]}", "$.employees[1].firstName");
            String result = jsonPathExpression(str, "$.data.deth.asks[1].[0].[0].a[1]");
            System.out.println(result);
        }
    
        /**
         * 根据路径表达式解析JSON
         *
         * @param jsonString 待处理的字符串
         * @param matcher    路径表达式
         * @return
         */
        public static String jsonPathExpression(String jsonString, String matcher) {
            String[] jsons = matcher.split("\\.");
    
            JSONObject object = JSON.parseObject(jsonString);
            JSONArray array = new JSONArray();
            String result = "";
            int index;
    
            for (int i = 1; i < jsons.length; i++) {
                if (jsons[i].contains("[")) {
                    // 解析数字
                    index = getIndex(jsons[i]);
                    if (i == jsons.length - 1) { // 最后一层
                        // 特殊情况处理
                        if (jsons[i].length() <= 3) {
                            // []必然是从array中取值
                            result = array.getString(index);
                        } else {
                            array = object.getJSONArray(jsons[i].split("\\[")[0]);
                            result = array.getString(index);
                        }
                    } else { // 不是最后一层
                        if (jsons[i].length() <= 3) {
                            try {
                                array = array.getJSONArray(index);
                            } catch (Exception e) {
                                object = array.getJSONObject(index);
                            }
                        } else {
                            // 不知道下一层是array还是object
                            try {
                                array = object.getJSONArray(jsons[i].split("\\[")[0]).getJSONArray(index);
                            } catch (Exception e) {
                                object = object.getJSONArray(jsons[i].split("\\[")[0]).getJSONObject(index);
                            }
                        }
                    }
                } else {
                    if (i != jsons.length - 1) {
                        object = object.getJSONObject(jsons[i]);
                    } else {
                        result = object.getString(jsons[i]);
                    }
                }
            }
            return result;
        }
    
        /**
         * 将字符串中的数字解析出来
         *
         * @param string:待处理的字符串
         * @return
         */
        public static int getIndex(String string) {
            try {
                String regEx = "[^0-9]";
                Pattern pattern = Pattern.compile(regEx);
                Matcher matcher = pattern.matcher(string);
                String index = matcher.replaceAll("").trim();
                return Integer.valueOf(index);
            } catch (Exception e) {
                return 0;
            }
        }
    }
    

    5 疑难杂症

    这一节主要记录一些比较特殊的场景和其解决方案。

    5.1 提取多个值

    • 响应结果:
    {
    	"result" : {
    		"similar" : [{
    				"id" : "us-B072HFDHKY",
    				"asin" : "B072HFDHKY"
    			}, {
    				"id" : "us-B073WM827B",
    				"asin" : "B073WM827B"
    			}, {
    				"id" : "us-B07GY17KFZ",
    				"asin" : "B07GY17KFZ"
    			}, {
    				"id" : "us-B076NYPS7M",
    				"asin" : "B076NYPS7M"
    			}, {
    				"id" : "us-B07NSBBX7L",
    				"asin" : "B07NSBBX7L"
    			}, {
    				"id" : "us-B077W9GHDV",
    				"asin" : "B077W9GHDV"
    			}
    		]
    	},
    	"code" : 0,
    	"message" : "操作成功!"
    }
    
    • 实现目标:在响应结果中前3个 asin 的值。

    以上场景,响应结果是JSON格式,在正常情况下,使用【后置处理器】中的【JSON Extractor】显然是很方便的(提取路径:$.result.similar[0].asin 即可获取第一个 asin 的值)。但由于要提取不止一个 asin 值,【JSON Extractor】就不太适用了,这时候要用到【正则表达式提取器】。

    1. 建立下面的脚本结构:
      在这里插入图片描述
      【BeanShell Sampler】的作用依然是模拟接口响应:
    return 
    "{\"result\":{\"similar\":[{\"id\":\"us-B072HFDHKY\",\"asin\":\"B072HFDHKY\"},{\"id\":\"us-B073WM827B\",\"asin\":\"B073WM827B\"},{\"id\":\"us-B07GY17KFZ\",\"asin\":\"B07GY17KFZ\"},{\"id\":\"us-B076NYPS7M\",\"asin\":\"B076NYPS7M\"},{\"id\":\"us-B07NSBBX7L\",\"asin\":\"B07NSBBX7L\"},{\"id\":\"us-B077W9GHDV\",\"asin\":\"B077W9GHDV\"}]},\"code\":0,\"message\":\"操作成功!\"}";
    
    1. 【正则表达式提取器】:
      在这里插入图片描述
      正则表达式:"asin":(.+?)"}

    2. 运行脚本,查看结果:
      在这里插入图片描述
      可见,所有 asin 值已经被提取并保存在内存中,后续的组件中可以任意引用。

    3. 引用值
      在这里插入图片描述
      在这里插入图片描述

    5.2 多个值合并

    如果响应内容是<name = Author value = Muguozheng>,我们同时提取到Author:MuguozhengAuthorMuguozheng作为下次请求参数,该如何做呢?

    首先,去【正则表达式试验器】中测试
    在这里插入图片描述
    根据匹配要求和正则表达式的测试结果,【正则表达式提取器】如下:
    在这里插入图片描述
    正则表达式:<name = (.+?) value = (.+?)>
    模板:$1$;$2$

    运行后查看结果树,后面的sampler(取样器)引用规则如下:

    1. 使用${test}可以引用Author:Muguozheng
    2. 使用${test_g}可以引用2这个数值
    3. 使用${test_g0}可以引用<name = Author value = Muguozheng>
    4. 使用${test_g1}可以引用Author
    5. 使用${test_g2}可以引用Muguozheng

    在这里插入图片描述

    5.3 左右边界不好确定

    假如响应结果是这么一个字符串:<name = Readers value = 马云,马化腾,刘强东>(向三位大佬致敬),想要提取马化腾这个值。

    这个例子的难点在于,正则表达式的左右边界无法确定,因为马化腾的右边界,刘强东也是响应内容中的动态值(这里的动态指的是,下次请求整体的响应内容可能变成"<name = Readers value = 张三,李四,王五>")。

    这里,正则表达式写成下面的样式即可:
    在这里插入图片描述
    于是,【Beanshell Sampler】写入模拟数据

    return "<name = Readers value = 马云,马化腾,刘强东>";
    

    【正则表达式提取器】可以如下图输入:
    在这里插入图片描述
    正则表达式:<name = Readers value = (.+?),(.+?),(.+?)>
    模板:$2$

    运行后查看结果树:
    在这里插入图片描述

    5.4 多个匹配结果

    在实际工作中,接口响应结果可能是一个集合,具有同样的左右边界,但我们需要的是最新的那条,一般是最后一条。

    如下,新建一个【Beanshell Sampler】模拟接口:

    return "<td>您的验证码是:400836,切勿将验证码告诉他人<td><td>您的验证码是:54297,切勿将验证码告诉他人<td><td>您的验证码是:65291,切勿将验证码告诉他人<td>";
    

    接下来在【Beanshell Sampler】下创建【正则表达式提取器】(匹配数字写-1,表示取所有匹配结果):
    在这里插入图片描述
    正则表达式:您的验证码是:(.+?),切勿将

    添加【Debug Sampler】和【查看结果树】后运行脚本,在【查看结果树】中可以看到,【正则表达式提取器】匹配结果:
    在这里插入图片描述

    code_1=400836
    code_1_g=1
    code_1_g0=您的验证码是:400836,切勿将
    code_1_g1=400836
    code_2=54297
    code_2_g=1
    code_2_g0=您的验证码是:54297,切勿将
    code_2_g1=54297
    code_3=65291
    code_3_g=1
    code_3_g0=您的验证码是:65291,切勿将
    code_3_g1=65291
    code_matchNr=3
    

    那么我们想获得匹配结果的最后一个,该怎么操作呢?这个问题的难点在于,事先无法确定匹配结果的数量,而解决这个难点的关键就在于code_matchNr这个参数,它的含义是匹配到的结果的数量,它的值就是最后一个匹配结果的索引。

    很明显,取code_${code_matchNr}就等值于code_3,无论匹配结果的数量是多少,code_${code_matchNr}都代表着最后一条结果。

    JMeter不支持嵌套引用,所以${code_${code_matchNr}}这种写法是不正确的。想正确引用该值,需要打开【Tools】-【函数助手对话框】,选择_V,填入code_${code_matchNr},点击生成:
    在这里插入图片描述
    ${__V(code_${code_matchNr})} 这个表达式就表示引用了匹配结果的最后一个。

    5.5 其他特殊用法

    在身份证中匹配提取出生日期,正则表达式如下图:
    在这里插入图片描述

    以上就是如何使用正则表达式提取器和JSON提取器实现关联的全部内容,觉得不错的朋友请点个赞和收藏,有不准确之处,欢迎指正。

    展开全文
  • 正则表达式提取器是: 在同一个线程组内,当前的B请求需要获取A请求返回的数据作为参数,这也是常说的关联,将上一个请求的响应结果作为下一个请求的参数,则需要对A请求的响应报文使用后置处理器——正则表达式提取...

    Jmeter 正则表达式提取器——身份证切取
    正则表达式提取器是: 在同一个线程组内,当前的B请求需要获取A请求返回的数据作为参数,这也是常说的关联,将上一个请求的响应结果作为下一个请求的参数,则需要对A请求的响应报文使用后置处理器——正则表达式提取器,其中最方便最常用的就是正则表达式提取器了。
    在这里插入图片描述
    引用名称:变量名 是你在B请求中需要调用的名字,后文中引用${变量名}

    正则表达式:所需要A请求中返回数据格式。例如 token: “{(.+?)}”或 token:“{(.*?)}”。

    模板:如果正则表达式有多个提取结果,则结果是数组形式,模板$ 1$, $ 2 $ 等等,表示把解析到的第几个值赋给变量;从1开始匹配,以此类推。
    若只有一个结果,则只能是$1 $;

    匹配数字(0代表随机):正则表达式匹配数据的结果可以看做一个数组,表示如何取值:0代表随机取值,正数n则表示取第n个值(比如1代表取第一个值),负数则表示提取所有符合条件的值。

    缺省值:匹配失败时候的默认值;通常用于后续的逻辑判断,一般通常为特定含义的英文大写组合,比如:ERROR等。

    身份证是18位数字号码组成,前1~6位为区域号码,7 ~ 14位是生日日期,15 ~ 17位是顺序码,最后1位是校验码
    正则表达式:
    (.{6})(.{8})(.{3})(.)
    (.{6}):任意字符匹配6次,对应前6为的区号
    (.{8}):任意字符匹配8次,对应生日日期
    对应的第二组
    $ 2 $

    在这里插入图片描述

    展开全文
  • 在美国,2017 年圣诞节的表示是“12/25/17”,而在欧洲,同一个日子却表示为“25/12/17”...# 美国日期正则表达式 us = r'((([01]?\d)[-/]([0123]?\d))([-/]([0123]\d)\d\d)?)' mdy = re.findall(us, 'Santa came 12/

    在美国,2017 年圣诞节的表示是“12/25/17”,而在欧洲,同一个日子却表示为“25/12/17”。这里构造的日期和时间提取器尝试适配上面两种日/月的表示顺序,并检查以确保是有效的日期

    import re
    from datetime import date
    import datetime
    
    # 美国日期的正则表达式
    us = r'((([01]?\d)[-/]([0123]?\d))([-/]([0123]\d)\d\d)?)'
    mdy = re.findall(us, 'Santa came 12/25/2017. An elf appeared 12/12.')
    print(mdy)
    
    # 结构化提取的日期
    # lstrip() 方法用于截掉字符串左边的空格或指定字符
    dates = [{'mdy': x[0], 'md': x[1], 'm': int(x[2]), 'd': int(x[3]),
                 'y': int(x[4].lstrip('/') or 0), 'c': int(x[5] or 0)} for x in mdy]
    print(dates)
    
    # 基本的上下文管理
    # 使用在内存的结构化数据的上下文中最近读取到的年份来
    # 填充任何缺失的数字字段
    for i, d in enumerate(dates):
        for k, v in d.items():
            if not v:
                d[k] = dates[max(i - 1, 0)][k]
    
    print(dates)
    datetimes = [date(d['y'], d['m'], d['d']) for d in dates]
    print(datetimes)
    
    
    # 欧洲日期的正则表达式
    eu = r'((([0123]?\d)[-/]([01]?\d))([-/]([0123]\d)?\d\d)?)'
    dmy = re.findall(eu, 'Alan Mathison Turing OBE FRS (23/6/1912-7/6/1954) was an English computer scientist.')
    print(dmy)
    dmy = re.findall(eu, 'Alan Mathison Turing OBE FRS (23/6/12-7/6/54) was an English computer scientist.')
    print(dmy)
    
    # 综合提取
    # 识别年份
    # 两位数表示的年份,30-99 = 1930-1999
    yr_19xx = (r'\b(?P<yr_19xx>' +
               '|'.join('{}'.format(i) for i in range(30, 100)) +
               r')\b')
    # 一位或者两位数表示的年份,01-30 = 2001-2030
    # 02d 格式一个整数( d )到最小宽度2( 2 )的字段,左侧填充零(前导 0 )
    yr_20xx = (r'\b(?P<yr_20xx>' +
               '|'.join('{:02d}'.format(i) for i in range(10)) + '|' +
               '|'.join('{}'.format(i) for i in range(10, 30)) +
               r')\b')
    # 3 位数或者 4 位数表示的年份的前几位数字,如“123 A.D.”中的“1”
    # 或者“2018”中的“20”
    yr_cent = r'\b(?P<yr_cent>' + '|'.join('{}'.format(i) for i in range(1, 40)) + r')'
    # 位数或者 4 位数表示的年份的后两位数字,如“123 A.D.”中的“23”
    # 或者“2018”中的“18”
    yr_ccxx = r'(?P<yr_ccxx>' + '|'.join('{:02d}'.format(i) for i in range(0, 100)) + r')\b'
    yr_xxxx = r'\b(?P<yr_xxxx>(' + yr_cent + ')(' + yr_ccxx + r'))\b'
    yr = (r'\b(?P<yr>' +
          yr_19xx + '|' + yr_20xx + '|' + yr_xxxx +
          r')\b')
    # finditer()函数实现每次只返回一个,并且返回所在的位置
    groups = list(re.finditer(yr, "0, 17, 2000, 01, '08, 99, 1984, 2030/1970 85 47 `66"))
    full_years = [g['yr'] for g in groups]
    print(full_years)
    
    # 用正则表达式识别月份名称
    mon_words = 'January February March April May June July August September October November December'
    mon = (r'\b(?P<mon>' + '|'.join('{}|{}|{}|{}|{:02d}'.format(m, m[:4], m[:3], i + 1, i + 1) for i, m in enumerate(mon_words.split())) + r')\b')
    print(re.findall(mon, 'January has 31 days, February the 2nd month of 12, has 28, except in a Leap Year.'))
    
    # 组合信息提取正则表达式
    day = r'(?P<day>' + '|'.join('{:02d}|{}'.format(i, i) for i in range(1, 32)) + r')\b'
    eu = (r'\b(' + day.replace('<day', '<eu_day') + r')\b[-,/ ]{0,2}\b(' + mon.replace('<mon', '<eu_mon') + r')\b[-,/ ]{0,2}\b(' + yr.replace('<yr', '<eu_yr') + r')\b')
    us = (r'\b(' + mon.replace('<mon', '<us_mon') + r')\b[-,/ ]{0,2}\b(' + day.replace('<day', '<us_day') + r')\b[-,/ ]{0,2}\b(' + yr.replace('<yr', '<us_yr') + r')\b')
    date_pattern = r'\b(' + eu + '|' + us + r')\b'
    print(list(re.finditer(date_pattern, '31 Oct, 1970 25/12/2017')))
    
    # 验证日期
    dates = []
    es_groups = list(re.finditer(date_pattern, "0, 12/25/2017, 2000, 01, '08, 99, 1984, 31/10/1970, 85 47 `66"))
    for g in es_groups:
        month_num = (g['us_mon'] or g['eu_mon']).strip()
        try:
            month_num = int(month_num)
        except ValueError:
            month_num = [w[:len(month_num)] for w in mon_words].index(month_num) + 1
        date = datetime.date(int(g['us_yr'] or g['eu_yr']), month_num, int(g['us_day'] or g['eu_day']))
        dates.append(date)
    print("dates:", dates)
    
    
    展开全文
  • 提取文本里的日期,并提供日期格式验证

    问题描述

    提取文本里的日期,并提供日期格式验证




    解决方案

    import re
    import time
    import datetime
    
    
    def validate_date(text):
        '''验证日期格式
    
        :param text: 待检索文本
    
        >>> validate_date('2020-05-20')
        True
        >>> validate_date('2020-05-32')
        False
        '''
        try:
            if text != time.strftime('%Y-%m-%d', time.strptime(text, '%Y-%m-%d')):
                raise ValueError
            return True
        except ValueError:
            return False
    
    
    def validate_datetime(text):
        '''验证日期+时间格式
    
        :param text: 待检索文本
    
        >>> validate_datetime('2020-05-20 13:14:15')
        True
        >>> validate_datetime('2020-05-32 13:14:15')
        False
        '''
        try:
            if text != datetime.datetime.strptime(text, '%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d %H:%M:%S'):
                raise ValueError
            return True
        except ValueError:
            return False
    
    
    def match_date(text):
        '''正则表达式提取文本所有日期
    
        :param text: 待检索文本
    
        >>> match_date('日期是2020-05-20 13:14:15.477062.')
        ['2020-05-20']
        '''
        pattern = r'(\d{4}-\d{1,2}-\d{1,2})'
        pattern = re.compile(pattern)
        result = pattern.findall(text)
        return result
    
    
    def match_datetime(text):
        '''正则表达式提取文本所有日期+时间
    
        :param text: 待检索文本
    
        >>> match_datetime('日期是2020-05-20 13:14:15.477062.')
        ['2020-05-20 13:14:15']
        '''
        pattern = r'(\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2})'
        pattern = re.compile(pattern)
        result = pattern.findall(text)
        return result
    




    参考文献

    1. Python正则表达式匹配日期与时间
    2. Python日期和时间库datetime
    3. re — 正则表达式
    展开全文
  • 正则表达式提取文本的日期

    千次阅读 2012-11-22 16:26:00
    接到需求,将数据库里面的一些标题数据中含有日期的给提取出来,利用提取的时间和当前时间来计算时间间隔,本像利用sql 的patindex等函数来提取,发现sql来写比较繁琐,后用正则表达式结合C#实现,本文主要记录正则...
  • 正则表达式提取时间

    千次阅读 2016-09-20 14:13:19
    时间的各种格式都可以通过正则表达式来匹配,例如我们想精确匹配HH:mm的时间,即包含小时和分钟,可以...把开头和结尾的去掉:([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]更多关于时间和日期正则表达式,参考: RegExL
  • jemter之正则表达式提取

    千次阅读 2016-09-30 10:49:47
    通常在使用jemter进行接口测试时,上一个接口的返回值传给下个接口,这时就需要用到正则表达式提取相关参数并进行参数化,话不多说,开始吧 例如:App端需要进行实现一个点赞的操作 1.点赞首先需要登录,用户名...
  • python+正则表达式提取“参考文献”中的作者名,发表日期等信息
  • time = "2020-01-01 # 这是一个日期" num = re.sub(r'#.*$', "", time)#以#为分隔,去掉后面的信息 print("这个时间是:", num) 结果: 这个时间是: 2020-01-01 2、截取某符号前后的内容 案例1: txt = '我的电话...
  • 匹配中文字符的正则表达式: [u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII...
  • 正则表达式教程及常用正则表达式

    千次阅读 2016-12-07 01:22:52
    正则表达式教程、常用正则表达式以及正则表达式测试工具
  • Object、正则表达式日期操作
  • JS正则表达式完整版

    万次阅读 多人点赞 2018-07-17 13:14:13
    第一章 正则表达式字符匹配攻略 1 两种模糊匹配 2. 字符组 3. 量词 4. 多选分支 5. 案例分析 第1章 小结 第二章 正则表达式位置匹配攻略 1. 什么是位置呢? 2. 如何匹配位置呢? 3. 位置的特性 4. 相关...
  • 正则表达式提取tom网页内容。http://astro.tom.com/sagittarius.html    写道 package rex.simple;import java.io.*;import java.net.*;import java.util.regex.*;public class AstroExtractor { //输出...
  • 1、asp.net正则表达式提取网址、标题、图片等 例如,有如下的字符串: &lt;li&gt;&lt;a href="http://www.webkaka.com/blog/archives/how-to-add-links-on-baidu-blog.html" title="...
  • import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { public static void main(String[] args) { String str = "户号:...
  • PHP中的正则表达式函数 ...PCRE库使用和Perl相同的语法规则实现了正则表达式的模式匹配,其使用以“preg_”为前缀命名的函数。另一套是由POSIX(Portable Operation System interface)扩展库提供的。POSIX扩展
  • 正则表达式(Regular Expression) 是用于匹配字符串中字符串组合的模式,在js中,正则表达式是对象(js万物皆对象) 用于:创建密码 提交表单,匹配字符串,过滤敏感词,提取特定的字符串。用于搜索 前端目前主要...
  • 在一些抓取、过滤等情况下, 正则表达式 regular expression 的优势是很明显的。 例如,有如下的字符串: 代码如下:<li><a>”article-date”>[09/11]</span>FCKEditor高亮代码插件测试</a></li> 现在,需要提取 href...
  • 正则表达式学习1、正则表达式是一门独立的学科,和任何编程语言无关,2、在编程中使用正则表达式最主要是用来做字符串模式匹配。3、在正则表达式中规定一些特殊符号,每一个符号都具有特殊含义。4、在实际开发中我们...
  • 提取整数 import re s = "azx0.231xa54-*+895/5.23+56aax45as21e5wqdw2.wqd2-0.23wqd" res = re.findall(r"-?\d+", s) print(res) 提取小数 import re s = "azx0.231xa54-*+895/5.23+56aax45as21e5wqdw2.wqd...
  • 正则表达式提取新闻发生时间

    千次阅读 2017-09-12 10:46:26
    最近在提取新闻事件的发生时间,现在只是实现了一个最简单的新闻,获取新闻报到时间和正文的时间。 方案:把正文中出现的第一个时间作为事情的发生时间,并按照统一的格式进行输出xxxx-xx-xx 某年某月某日这种格式。...
  • 什么是正则表达式? 英文Regular Expression,是计算机科学的一个重要概念,它使用一种数学算法来解决计算机程序中的文本检索,匹配等问题,正则表达式语言是一种专门用于字符串处理的语言。在很多语言中都提供了对它...
  • 正则表达式笔记--常用正则表达式
  • golang正则表达式提取email地址

    千次阅读 2019-08-28 22:15:37
    package main import ( "fmt" "regexp" ) func main(){ //re:=regexp.MustCompile("ccmouse@gmail.com") texts:= []struct { text string }{ {"My email is ccmouse@gmail.com"}, {"ccmouse@gmail....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,481
精华内容 9,792
关键字:

正则表达式提取日期