Loadrunne 关联函数web_reg_save_param详解
3.7.5 关联函数web_reg_save_param详解(1)
上面说了常见的3种关联应用的方式,可以看到所谓关联都是使用web_reg_save_ param()函数将服务器返回的内容进行收集过滤的过程,接着我们来仔细研究一下关联函数提供的选项。
首先介绍一个函数web_set_max_html_param_len(),当关联出错的时候VuGen都会提示以下内容:
1. Action.c(20): Error -26377: No match found for the requested
parameter "WCSParam2". Check whether the requested boundaries
exist in the response data. Also, if the data you want to save
exceeds 256 bytes, use web_set_max_html_param_len to increase
the parameter size [MsgId: MERR-26377]
很多朋友看到这个错误就会头皮发麻,完全不知所措。这种错误99%都是由于关联的边界设置不合理导致没有关联到所需要的内容。系统提示使用web_set_max_html_ param_len()函数的目的是提醒如果被关联内容超出了默认的1024字节就会导致存放数据溢出,就会产生参数值为空、关联失败的情况(做附件下载的脚本就可能会遇到这个问题),但通常都不会关联到如此巨大的内容。
web_set_max_html_param_len()函数可以自定义关联返回值存放的参数的最大长度。
打开Insert/Add Step窗口,找到对应的web_set_max_html_param_len函数,如图3.152所示。
设置最大长度为9999999,如图3.153所示。
得到以下脚本:
1. web_set_max_html_param_len("9999999");
通过这个函数可以确保不会出现参数内容过长而无法存放的错误,不过这是以开销系统资源为代价的。可以用
web_set_max_html_param_len("1024"); 或是web_set_max_html_param_len("2048");
接着来看看web_reg_save_param()函数的选项,由于关联出来的内容存放在参数中,所以还是建议打开日志中的Parameter substitution选项,以方便调试跟踪。
打开Add Step添加步骤,选择web_reg_save_param函数,打开关联函数设置窗口。
Parameter Name
此处设置存放参数的名称,关联出来的内容将会存放在该参数中。这里受到Instance选项的影响。
例如:
设置Parameter Name为temp,当对应的Instance选项是任意一个数字的时候,只会关联一个匹配的记录,关联值将会存放在temp这个参数中。当 Instance是All的时候,关联成功后的值将会依次存放在"temp_数字"这样的参数数组中,并且还会添加一个temp_count的参数存放关联出来的记录条数。
Left Boundary
此处设置左边界,这里是用来填写关联对于数据处理的左匹配内容规则。
在左边界中存放的是一个字符串,例如填写的内容为"左边界"会被转换成以下形式:
1. web_reg_save_param("Param",
2. "LB=左边界",
3. "RB=",
4. LAST);
如果输入的内容里面有双引号,那么需要通过转义符来进行处理,转义符为\。例如:
1. web_reg_save_param("Param",
2. "LB=\"左边界",
3. "RB=",
4. LAST);
Match case
默认情况下边界是Match case的,也就是检查大小写的,可以取消下面的选项来忽略大小写检查,会看到函数变为以下形式:
1. web_reg_save_param("Param",
2. "LB/IC=左边界",
3. "RB=",
4. LAST);
Binary data
如果需要关联的内容是非ASCII字符的,那么需要使用该选项。选中该选项后可以看到函数变为以下形式:
1. web_reg_save_param("p", "LB/BIN=\\x3F\\xDD", "RB/BIN=\\xCCb", LAST);
Use # for any digit 有些时候需要关联的边界中有些变动的数字,并且由于这个数字导致关联非常难于设置边界,可以使用该选项,
现在需要从这个服务器返回中获得href对应的地址,应该怎么写边界呢?可以跳过变动的数字直接设置href=为左边界好了,但这样做可能会出现一个问题,如果服务器返回中间有很多href=这样的超链接,那么关联出来的数据可能就无法满足我们的需要,所以这里可以使用#来解决这个问题。
在这里关联的左边界内容应该为:
title="[Alt+2]" accessKey="2" href=",然后将这个内容写入关联函数,添加转义符,函数结果应该为:
1. web_reg_save_param("Param",
2. "LB/DIG=title=\"[Alt+#]\" accessKey=\"#\" href=\"",
3. "RB=",
4. LAST);
3.7.5 关联函数web_reg_save_param详解(2)
使用这样的左边界可以得到准确范围内的关联值,如果在项目中遇到一些很难确定关联边界的情况时,可以请求程序员编写一些便于区分的标识来方便进行关联的边界设置。
Use ^ as a wildcard for xxx alphanumerical characters
对比上面的功能,这里可以使用^符号来代替任何常用的字符。该功能有3个选项:All、LowerCase、UpperCase,使用^支持任意的字符,可以通过该选项来支持大写字母、小写字母或者不区分大小写。
# web_reg_save_param("time",
# "LB/ALNUMIC=Server response ti^^:",
# "RB=seconds",
# "Ord=1",
# "Search=Body",
# LAST)
该选项在某些时候能够帮助跳过边界中变动的内容完成抓取操作,但是注意这里使用的^符号是不支持长度变化的,也就是说一个^代表了一个字符的位置。如果需要关联的边界本身就是变动的,就不能通过普通的方法来解决了。
Right Boundary
此处设置右边界,这里是用来填写关联时对于数据处理的右匹配内容规则,选项同左边界。
Instance
这个关键字在很多函数里面都有应用,在这里可以填写任意一个整数,也可以填All。如果填写数字,那么说明从返回的记录中取出对应顺序的值,而填写All的话将会返回所有的内容。
当使用Ord=All时,关联函数会把所有匹配过滤策略的记录都抓出来,由于参数只能存放一条记录,所以关联函数会生成一个参数数组。被关联的记录会以{关联参数名_关联id}的形式生成参数列表,并且在最后会有一个{关联参数名_count}的参数来存放被关联到的记录条数。
例如:上面写过的一个关联函数如下所示:
1. web_reg_save_param("Param",
2. "LB/DIG=title=\"[Alt+#]\" accessKey=\"#\" href=\"",
3. "RB=\">",
4. "ORD=ALL",
5. LAST);
当Instance设置为All时,关联将会返回所有匹配左右边界的内容。
这个选项是专门针对框架结构的网站设计的,有些时候需要关联的内容是在某个框架中的,这个时候就需要说明所关联的页面是框架中的哪一个了。比如自动关联Web Tour页面就必须使用这个属性:
1. web_reg_save_param("WCSParam_Diff1",
2. "LB=userSession value=",
3. "RB=>",
4. "Ord=1",
5. "RelFrameId=1.2.1",
6. "Search=Body",
7. "IgnoreRedirections=Yes",
8. LAST);
这里的1.2.1说明Web Tour网站是基于在第一个大的框架中的第二个框架,第二个框架中的第一个页面这样的两次嵌套框架,所以如果想读取左下侧的页面,这个框架所属的编号就为1.2.1。
Not Found
如果关联的对象不存在,又该如何进行处理呢?默认值为ERROR,默认情况下如果没有关联到任何内容则提示错误
1. Action.c(20): Error -26377: No match found for the requested parameter
"time". Check whether the requested boundaries exist in the response
data. Also, if the data you want to save exceeds 256 bytes, use
web_set_max_html_param_len to increase the parameter size [MsgId: MERR-26377]
2. Action.c(20): Notify: Saving Parameter "time = "
3. Action.c(20): web_url("Mspetshop") highest severity level was "ERROR",
452988 body bytes, 11060 header bytes, 13 chunking overhead bytes [MsgId: MMSG-26387]
而选择WARNING,则只会简单提示没有抓到内容,不会产生错误。
Action.c(20): Warning -26377: No match found for the requested
parameter "time". Check whether the requested boundaries exist
in the response data. Also, if the data you want to save
exceeds 256 bytes, use web_set_max_html_param_len to
increase the parameter size [MsgId: MWAR-26377]
在很多时候关联不到内容也是正常的。例如需要关联一个板块中的帖子编号,就存在没有帖子的情况。为了确保关联的正确性,在某些情况下可以修改Not Found的提示方式为WARNING,并且为了确保没有帖子时不会对后面的操作产生影响,需要编写一个if语句进行判断,如下所示:
1. Action()
2. {
3. web_reg_save_param("topicid",
4. "LB=<a href=\"showtopic-",
5. "RB=.aspx\" target=\"_blank\"><img src=\"templates/default/images/ t_top",
6. "Ord=1",
7. "NotFound=WARNING",
8. "Search=NoResource",
9. LAST);
10.
11. web_url("Topic",
12. "URL=http://127.0.0.1/showforum-1.aspx",
13. "Resource=0",
14. "Referer=",
15. LAST);
16.
17. if (strcmp(lr_eval_string("{topicid}"),"")==0) {
18. return 0;
19. }
20. else
21. {
22. web_url("topic",
23. "URL=http://127.0.0.1/showtopic-{topicid}.aspx",
24. "Resource=0",
25. "Referer=",
26. LAST);
27. }
28. return 0;
29. }
这样如果该板块没有帖子,就不会执行后面请求帖子页面的操作了。
如果关联选项Ord为All时,这里if语句检查的对象应该修改为topicid_ count参数。
Search in
该项设置关联查询的范围,这里VuGen提供了4个选项:Header、Body、Noresource、All。我们将这4个选项划分两个大类。
Noresource
Noresource是从服务器返回的内容类别来考虑的,Noresource就是指只从资源文件中关联内容,也就是只从HTML文件格式中抓内容。
Header/Body/All
这3个选项都是从请求返回的所有内容进行关联处理,包括图片、JavaScript脚本等。区别在于对返回信息的分隔方式。在前面介绍HTTP的时候介绍过HTTP返回的内容其实是由Header(HTTP信息头)和Body(HTTP内容)组成的。
Header
指所关联的内容是所有服务器返回请求的HTTP头部分内容。可以通过查看服务器返回内容来了解,Body之前的内容都属于Header,例如:
1. Header:
2. ------------------------------------------
3. HTTP/1.1 200 OK
4. Date: Thu, 25 Sep 2008 06:27:37 GMT
5. Server: Apache/2.2.8 (Win32) PHP/5.2.5
6. X-Powered-By: PHP/5.2.5
7. Expires: Thu, 19 Nov 1981 08:52:00 GMT
8. Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
9. Pragma: no-cache
10. Keep-Alive: timeout=5, max=98
11. Connection: Keep-Alive
12. Transfer-Encoding: chunked
13. Content-Type: text/html; charset=UTF-8
3.7.5 关联函数web_reg_save_param详解(3)
Body
就是服务器返回在Body以后的内容,例如:
All
指服务器返回的所有内容。
关于Search in这个选项,一般使用得比较多的是Noresource,因为需要关联的内容一般都存放在HTML页面中,并且使用Noresource被关联到的内容又比较少(只返回一个HTML页面)比较适合常用处理,如果某些信息是放在HTTP头内的,那么只能用 Header了。
Save Length
关联出来的内容所需要保存的长度。
例如:通过左右边界关联出来的内容是"sessionid=123456&action=work",那么如何获得需要的 sessionid信息呢?可以使用Save Length来实现,注意这里必须确保被关联内容的长度恒定。将Save Length设置为16,关联出来的结果就变成"sessionid=123456"了,如果想得到后面的sessionid值,就要靠Save Offset选项了。
Save Offset
设置关联的内容偏移量,从第几位开始进行关联操作。继续上面的例子,如果需要获得123456这个字符串,则需要设置Save Offset为10,同时设置Save Length为6即可。
通过Save Length和Save Offset的设置,我们就可以方便地抓取服务器返回内容的任意一个部分了。
关联可以调整偏移量和长度,那么参数能做到吗?当然可以,如果需要对一个参数值进行偏移和长度设置,则需要使用lr_save_var()函数,例如下面的代码:
1. lr_save_string("I come from shanghai","city");
2. lr_save_var(lr_eval_string("{city}"),6,0,"result");
3. //从city这个参数中取6位长度的内容保存到result参数中
4. lr_save_var(lr_eval_string("{city}")+7,4,0,"result");
5. //从city这个参数的第7位开始取4个长度的内容保存到result参数中
可以看到运行的结果是:
1. Action.c(3): Notify: Saving Parameter "city = I come from shanghai"
2. Action.c(4): Notify: Saving Parameter "result = I come"
3. Action.c(5): Notify: Saving Parameter "result = from"
问题:
前面关联的左右边界都是静态的。如果左右边界是动态的,并且系统返回的id是不定长度的,那么如何使用关联函数将该id取出呢?这个问题在现实情况中会经常遇到,仅仅通过一个关联函数是无法处理的,这个时候还需要使用一个函数strtok()来进行字符内容切割(类似于正则表达式)。
strtok()函数的作用是通过某个分隔符来切分内容。
例如:
1. char city[1000];
2. char * token;
3. extern char * strtok(char * string, const char * delimiters ); //这个函数是扩展的要声明
4. strcpy(city,"this is shanghai!");
5. token = (char *)strtok(city," ");
6. lr_error_message(token);
7. token = (char *)strtok(NULL," ");
8. lr_error_message(token);
9. token = (char *)strtok(NULL," ");
10. lr_error_message(token);
通过这个函数可以得到三个字符:this、is、shanghai。通过空格来分隔字符串,可以得到第一个符合该条件的内容,如果需要继续分隔就使用strtok(NULL," ");语句。如果关联出来的内容sessionid是变动长度的,如"sessionid=54321123&action=work",则如何获得这个变动长度的sessionid呢?使用下面的代码即可解决:
1. char temp[100];
2. char * token;
3. extern char * strtok(char * string, const char * delimiters );
4. lr_save_string("sessionid=54321123&action=work","param");
5. strcpy(temp,lr_eval_string("{param}"));//取出参数值,并且赋值给变量temp
6. token = (char *)strtok(temp,"&");//使用&符号作为分隔符
这个时候token="sessionid=54321123",并且是根据&符号分隔的,所以id的长度可以任意变化,而token中的sessionid可以通过关联的时候Save Offset进行处理,或者使用strtok()函数对等号再次进行处理。
fyi,
http://book.51cto.com/art/200912/167688.htm
关联函数web_reg_save_param详解(2)
http://book.51cto.com/art/200912/168040.htm