年前走查脚本代码时,发现大家对selenium功能都在重复造轮子,而且容易出现一些常见低级bug。于是在闲暇之余,封装一些常用的selenium功能。
在某些网页中,存在多个frame嵌套。而selenium提供的find_element函数只能在当前frame中查找,不能切换到其他frame中,需要从最上级frame中逐步切换(当然也可以指定xpath的绝对路径,但是一般没人这么做)。在我们写代码过程中,需要明确知道当前frame位置和需要寻找元素的frame位置。在frame切换过程中,容易因为疏忽导致frame切换错误导致元素无法找到的bug。
页面中分布的frame,可以理解为树状结构。因此我们可以采用递归的方式, 沿着某条搜索路线frame节点,依次对树中每个节点均做一次访问。
我们以163网址上的登录框为例:点击登录按钮,d出登录iframe页面。输入框位置在iframe中,因此我们不能使用xpath获取元素位置,需要进入iframe中,然后获取元素。
手动切换ifame可能会产生bug,因此需要一套自动切换和检索frame的机制。具体代码如下:
需要注意的是:如果页面中多个frame中,存在相同的xpath元素。还是需要指定frame的路径,否则会返回搜索到的第一个元素。
强制等待
直接调用系统timesleep函数,不管页面加载情况一定会等待指定的时间, 即使元素已被加载 。
1如果设置的时间较长,会浪费时间
2如果设置的时间较短,元素可能没有加载。
页面中某元素如果未能立即加载,隐式等待告诉WebDriver需等待一定的时间,然后去查找元素。默认不等待,隐式等待作用于整个WebDriver周期,只需设置一次即可。
1在上文的find_element函数中,采用递归方式在所有frame寻找元素。若采用隐式等待,则在每个frame中都需要等待设定的时间,耗时非常长。
2某些页面我们想要的元素已经加载完毕,但是部分其他资源未加载。隐式等待必须等待所有元素加载完毕,增加额外等待时间。
显示等待一般作用于某一个元素,在设定的时间范围内,默认每间隔05秒查找元素。返回被加载的元素,若超过设定的时间范围未能查找则报错。显示等待作为selenium常用的等待机制,我们来看下他的源码和机制。
driver 注释中解释为WebDriver实例,但是代码中并未有相关检测,因此可以传入任何对象
但是__repr__函数中使用到session_id属性,如果需要显示属性或者转为str对象,最好在driver对象中添加session_id属性
在until函数中,我们可以看到driver对象传入method函数。在计时结束前,在不断循环执行method函数,如果method函数有正常返回值则退出循环,否则报TimeoutException错误。
可以采用装饰器对隐式等待进行封装,这样代码更加精简
同样的,采用装饰器对其他常用的函数进行封装,例如强制等待、点击、输入文本等。
装饰器虽然很方便,但也会产生一些麻烦。例如在find_element函数递归调用过程中,理应只要执行一次装饰器函数。但因为装饰器已经装饰完毕,导致每次递归都会执行。例如强制等待的sleep函数,如果递归次数越多等待时间越长。
解除装饰器一般有两种做法:一是约定参数,当递归第二次调用时则不生效。例如
这种方式实现简单,容易理解。但是增加了参数限制,在fun函数中就不能使用first_sleep参数。
二是采用装饰器采用wrapped实现,通过访问wrapped属性获得原始函数。例如
但是某一个函数被多个装饰器装饰时,需要递归解除装饰器。例如
最后整体代码如下
这次的封装其实还存在很多问题
1find_element函数不仅仅只是提供查找元素功能,还提供一些其他功能,因此叫element_operation更为合适。
2find_element函数的参数过多,并且很多参数的使用并不在函数本身中,对代码阅读很不友好。
3得小心避免参数重复问题,假设装饰器sleep和装饰器wait_time都使用time这个参数,将无法区分具体是哪个函数使用。
4不利于扩展和维护,当功能过多时find_element的参数过于庞大。
如果只是简单地封装和使用,上面这种方式也能达到较好的效果。如果想进一步封装,建议采用链式调用方式,装饰器辅助封装。例如
这样函数的扩展性和可阅读性有较大的提升
#include <iostream>
#include <vector>
#include <list>
using namespace std;
template<typename ElementType, typename ContainerType>
ElementType maxElement(ContainerType &container)
{
typename ContainerType::iterator it = containerbegin();
ElementType max = it;
while( ++it != containerend() )
{
if( it > max )max = it;
}
return max;
}
template<typename ElementType, typename ContainerType>
ElementType minElement(ContainerType &container)
{
typename ContainerType::iterator it = containerbegin();
ElementType min = it;
while( ++it != containerend() )
{
if( it < min )min = it;
}
return min;
}
int main(int argc, char argv[])
{
vector<int> lst;
lstpush_back(1);
lstpush_back(5);
lstpush_back(3);
int max = maxElement<int, vector<int> >(lst);
printf("max is %d\n", max);
int min = minElement<int, vector<int> >(lst);
printf("min is %d\n", min);
list<int> lst2;
lst2push_back(10);
lst2push_back(50);
lst2push_back(30);
max = maxElement<int, list<int> >(lst2);
printf("max is %d\n", max);
min = minElement<int, list<int> >(lst2);
printf("min is %d\n", min);
return 0;
}
//1
int ReadRealData(double dArray[], int nCount)
{
long sumData = 0;
double dData;
int m_nCount;
cout<<"请输入数组的个数:"<<endl;
cin>>m_nCount;
while(m_nCount<=nCount)
{
cin>>dData;
if (dData == "\n") break;
dArray+sumData = &dData;
sumData = sumData + 1;
}
return sumData;
}
//2
int FindMinElement (double dArray[], int nCount)
{
double pMin;
pMin = dArray;
int pos=0;
for(int i = 0;i<nCount;i++)
{
if(pMin>(dArray+i))
{
pMin=(dArray+i);
pos = i;
}
}
return pos;
}
int FindMaxElement (double dArray[], int nCount)
{
double pMax;
pMax = dArray;
int pos=0;
for(int i = 0;i<nCount;i++)
{
if(pMax < (dArray+i))
{
pMin = (dArray+i);
pos = i;
}
}
return pos;
}
double Average(double dArray[], int nCount)
{
double dsum;
for(int i = 0;i<nCount;i++)
{
dsum = dsum +(dArray+i);
}
return dsum/nCount;
}
double Variance(double dArray[], int nCount)
{
double dresult;
//方差公式忘记了 你可以仿照上一个函数 根据公式自行写
return dresult;
}
//测试函数自己写
1)循环
对序列中的每个元素执行某项 *** 作 for_each()
2)查找 在序列中找出某个值的第一次出现的位置
find(a,a+
size,n)
返回b
当b=a+size
即没找到,a为指针
在序列中找出符合某谓词的第一个元素 find_if()
在序列中找出一子序列的最后一次出现的位置 find_end()
在序列中找出第一次出现指定值集中之值的位置 find_first_of()
在序列中找出相邻的一对值 adjacent_find()
计数 在序列中统计某个值出现的次数 count()
在序列中统计与某谓词匹配的次数 count_if()
比较 找出两个序列相异的第一个元素 mismatch()
两个序列中的对应元素都相同时为真
在序列中找到等于某值的连续n次出现的位置 equal(a,a+n,b,cmp)
equal_range(a,a+n,x)
搜索 在序列中找出一子序列的第一次出现的位置 search()
在序列中找出一值的连续n次出现的位置 search_n()
修改性序列 *** 作(27个)
复制 从序列的第一个元素起进行复制 copy()
从序列的最后一个元素起进行复制 copy_backward()
交换 交换两个元素 swap()
交换指定范围的元素 swap_ranges()
交换由迭代器所指的两个元素 iter_swap()
变换 将某 *** 作应用于指定范围的每个元素 transform()
替换 用一个给定值替换一些值 replace()
替换满足谓词的一些元素 replace_if()
复制序列时用一给定值替换元素 replace_copy()
复制序列时替换满足谓词的元素 replace_copy_if()
填充 用一给定值取代所有元素 fill()
用一给定值取代前n个元素 fill_n()
生成 用一 *** 作的结果取代所有元素 generate()
用一 *** 作的结果取代前n个元素 generate_n()
删除 删除具有给定值的元素 remove()
删除满足谓词的元素 remove_if()
复制序列时删除具有给定值的元素 remove_copy()
复制序列时删除满足谓词的元素 remove_copy_if()
唯一 删除相邻的重复元素 unique()
复制序列时删除相邻的重复元素 unique_copy()
反转 反转元素的次序 reverse(a,a+n)
复制序列时反转元素的次序 reverse_copy()
环移 循环移动元素 rotate(a,a+m,a+n)
以m位置为界交换前后序列
复制序列时循环移动元素 rotate_copy()
随机 采用均匀分布来随机移动元素 random_shuffle()
划分 将满足某谓词的元素都放到前面 partition()
将满足某谓词的元素都放到前面并维持原顺序 stable_partition()
序列排序及相关 *** 作(27个)
排序 以很好的平均效率排序 sort(a,a+20,cmp)
bool cmp( int a,
int b )
{ return a>b; }
在容器中或string用begin()
排序,并维持相同元素的原有顺序 stable_sort()
将序列的前一部分排好序 partial_sort()
复制的同时将序列的前一部分排好序 partial_sort_copy()
第n个元素 将第n各元素放到它的正确位置 nth_element()
二分检索 找到大于等于某值的第一次出现 lower_bound()
找到大于某值的第一次出现 upper_bound()
找到(在不破坏顺序的前提下)可插入给定值的最大范围 equal_range()
在有序序列中确定给定元素是否存在 binary_search()
归并 归并两个有序序列 merge()
归并两个接续的有序序列 inplace_merge()
有序结构上的集合 *** 作 一序列为另一序列的子序列时为真 includes()
构造两个集合的有序并集 set_union()
构造两个集合的有序交集 set_intersection()
构造两个集合的有序差集 set_difference()
构造两个集合的有序对称差集(并-交) set_symmetric_difference()
堆 *** 作 向堆中加入元素 push_heap()
从堆中d出元素 pop_heap()
从序列构造堆 make_heap()
给堆排序 sort_heap()
最大和最小 两个值中较小的 min()
两个值中较大的 max()
序列中的最小元素 min_element(a,a+n)
序列中的最大元素 max_element()
词典比较 两个序列按字典序的第一个在前 lexicographical_compare()
排列生成器 按字典序的下一个排列 next_permutation()
按字典序的前一个排列 prev_permutation()
子查询是SQL语句中非常重要的功能特性,它可以在SQL语句中利用另外一条SQL语句的查询结果,在Hibernate中HQL查询同样对子查询功能提供了支持。如下面代码所示:
List list=sessioncreateQuery(“from Customer c where 1>(select count(o) from corders o)”)list();
上面的程序查询订单数超过1的所有客户,因此和上面子查询HQL语句对应的SQL语句为:
Select from Customer c where 1>(select count(oid) from Order o where cid=ocustomer_ID);
如果子查询返回多条记录,则可以使用下面关键字:
all:表示子查询语句返回的所有记录
any:表示子查询语句返回的任意一条结果
some:与”any”等价
in:与”=any”等价
exists:表示子查询语句至少返回一条记录
例如:查询存在一条订单价格大于100的客户
From Customer c where 100>any(select oprice from corders o);
如果在子查询中 *** 作集合,HQL提供了一组 *** 纵集合的函数和属性:
size()函数和size属性:获得集合中元素的数量
minIndex()函数和minIndex属性:对于建立了索引的集合获得最小索引值(关于集合索引参考第一部分映射值类型集合)
minElement()函数和minElement属性:对于包含基本类型的元素集合,获得集合中值最小的元素
maxElement()函数和maxElement属性:对于包含基本类型元素的集合,获得集合中值最大的元素
element()函数:获得集合中所有元素
例如:查询订单数大于0的客户
From Customer c where size(corders)>0;或者From Customer c where corderssize>0;
以上HQL语句会生成类似如下的SQL语句:
Select from customer c where 0>(select count(oid) from order where o customer_ID =cid);
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <mathh>
using namespace std;
typedef double DataType;
typedef vector<DataType> DataList;
DataType Average(DataList const & data_list)
{
size_t n;
DataType sum;
DataList::const_iterator ite = data_listbegin();
if ( ite == data_listend() ) return (DataType) 0;
n = data_listsize();
for (sum = ite++; ite != data_listend(); ite++)
{
sum += ite;
}
return sum / n;
}
DataType StdDev(DataList const & data_list)
{
size_t n;
DataType avg, var, diff;
DataList::const_iterator ite = data_listbegin();
if ( ite == data_listend() ) return (DataType) 0;
n = data_listsize();
avg = Average(data_list);
var = 0;
for (;ite != data_listend(); ite++)
{
diff = ite - avg;
var += diff diff;
}
return sqrt(var/n);
}
int main(int argc, char argv)
{
DataList data_list;
DataType min=0, max=0, avg=0, dev=0, ele;
while ( cingood() && cinpeek() != '\n') {
cin >> ele; data_listpush_back(ele);
}
min = min_element(data_listbegin(), data_listend());
max = max_element(data_listbegin(), data_listend());
avg = Average(data_list);
dev = StdDev(data_list);
coutprecision(4);
coutsetf(ios::fixed, ios::floatfield);
cout << "Min: " << min << endl
<< "Max: " << max << endl
<< "Average: " << avg << endl
<< "Standard deviation: " << dev << endl;
coutunsetf(ios::floatfield);
return 0;
}
这里使用了函数模板
template <class T>
T min(T list, unsigned int len)
{ return (std::min_element(list,list+len)); }
a记录数组元素 N记录个数
#include<stdioh>
int a[100], N;
intfind_min_element(intbegin, intend) {
intret=begin, p;
for(p=begin+1; p<end; ++p)
if(p<ret) ret=p;
// return the position of the min element in the range [begin,end)
return ret;
}
interase_element(intpos,intbegin,intend) {
intp=pos;
for(;p+1<end;++p)
p=(p+1);
// return the position of the end of the array
return p;
}
int output(intbegin, intend) {
int p=begin;
for(;p<end;++p)
printf("%4d", p);
printf("\n");
}
int main() {
int i;
// input the array
scanf("%d", &N);
for(i=0;i<N;++i) scanf("%d", a+i);
// work1
// find the position of the min element
intp = find_min_element(a, a+N);
printf("min element = %d\n", p);
// erase the element at position p
N=erase_element(p,a,a+N)-a;
//output the new array
printf("elment number : %d\n", N);
output(a,a+N);
// work2
p = find_min_element(a,a+N);
printf("min element = %d\n", p);
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)