BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

有货iOS数据非侵入式自动采集探索实践

| 作者 曹镏 关注 0 他的粉丝 发布于 2017年12月26日. 估计阅读时间: 25 分钟 | 都知道硅谷人工智能做的好,你知道 硅谷的运维技术 也值得参考吗?QCon上海带你探索其中的奥义

随着有货APP的不断迭代开发,数据和业务部门对于客户端用户行为数据的需求越来越多;为了更好的监控APP使用的状况,客户端团队对于APP自身的运行的数据需求也愈发迫切。迫切地需要一套客户端数据采集的工具,自动、全量采集用户行为数据,满足各个部门对于数据的需求。

有货APP团队为此开发一套数据采集的SDK,主要的功能如下:

  1. 页面访问流。用户在使用APP期间浏览了哪些页面。
  2. 浏览数据曝光。用户在某个页面上浏览了哪些商品。
  3. 业务数据自动采集。用户在使用APP期间点击了哪些位置,触发了哪些操作。
  4. 性能数据自动采集。用户使用APP期间,页面加载时长是多少,图片加载时长多少,网络请求时长多少等。

此外,所有的数据采集要自动化,无侵入,即不需要人工埋点,集成SDK即可使用,不改动或尽量少改动原有代码。

基于以上需求,AOP是技术方案的最佳选择,而iOS上实现AOP则需要依靠Objective-C中runtime的黑魔法--Method Swizzle实现。漫漫的踩坑填坑的旅程由此开端,接下来我们一一品尝实现思路和方法吧。

页面访问流

用户访问页面统计需要解决的问题有两个:

  1. 统计事件切入点,即何时统计。
  2. 统计数据字段,即统计哪些数据。

整体流程如下图:

统计事件切入点

用户访问页面统计的一般思路是在View Controller生命周期方法:

  • viewDidAppear上报页面进入事件。
  • viewDidDisappear上报页面退出事件,

即可得出用户访问页面路径,两个事件时间戳之差即为用户在页面停留的时间。

通常我们APP中的View Controller都会继承自某个基类,我们在基类的对应方法中进行统计即可,然而对于没有从基类继承的View Controller就无能为力了。

借助于AOP,我们可以更优雅的完成这项工作:在UIViewController的load方法里swizzle viewDidAppear和viewDidDisappear方法,原有代码无需改动。

统计数据字段

根据数据需求,设置了如下的统计字段:

  • PAGE_ID,当前页面的标识。
  • SOURCE_ID,当前页面的前一个页面的标识。
  • TYPE_ID,当前页面一些关键信息,如商品id,品牌id等。
  • TIMESTAMP,当前事件生成的时间戳。

页面进入和退出的事件,均上报上述的数据结构。

其中还有几个问题是需要考虑的:

1.PAGE_ID和SOURCE_ID如何定义

因为需要统一iOS和Android的PAGE_ID,所以需要做配置下发。iOS端拿到的是一份plist的文件,文件的key的View Controller的类名的字符串表示,value则是PAGE_ID。

2.PAGE_ID和SOURCE_ID如何获取

PAGE_ID直接根据当前View Controller的class即可取到,SOURCE_ID稍显复杂,需要根据APP页面嵌套堆栈结构来确认具体的获取方法,通常是从UINavigationController的导航栈中取前一个View Controller的page id即可。

至此,页面访问流统计已基本完成,根据页面进入退出的PAGE_IDSOURCE_ID串出一条完整的用户浏览路径,并得出用户在每个页面的停留时间。

浏览数据曝光

采集到用户的浏览路径,以及在每个页面的停留时间后,在某些特定的页面,如首页、商品列表页面,我们还想知道用户在页面上滑动了几屏,看了哪些活动、商品,以便于更好的为用户推荐喜欢的商品。

用户看到的屏幕上的一块区域,认为是资源位,那么用户看到的内容是由一个个资源位组成。那么曝光的含义如下:

  • 资源位从屏幕可视区域外,进入到可视区域内(任意部分可见即可),即是一次曝光。
  • 资源位从可视区域移出后,再次进入可视区域,算做新的一次曝光。
  • 页面切换和下拉刷新时,算作新的一次曝光。

我们知道iOS中页面元素的基本组成单位是view,因此我们只需要判断view是否在可视区域,即可知悉当前view上的资源位是否需要曝光,从而做出相应的曝光操作,采集数据,上报接口等。

由以上的分析可知,待解决的问题主要有两个:

  1. view的可见性判断
  2. view曝光数据采集

view的可见性判断

查询UIView Class Reference可以看到setFrame:layoutSubivews方法,可用于设置subview的frame。每次view fame更新均会调用此方法。因此,我们可以通过runtime swizzle此方法实现,添加一些数据采集相关的操作。

我们为UIView添加了以下属性:

  • yh_viewVisible:view是否可见,默认否。可见性由否->是的时候,触发一次曝光数据采集的操作。
  • yh_viewVisibleRect:view可见区域,默认CGRectZero。
  • yh_visibleSubviews:view所有可见的subview。

首先明确下几个术语的定义和规则:

1.view的subview可见需要同时满足的3个条件:

  • subview.hidden为false,即view没有被隐藏。
  • subview.alpha大于等于0.01,即view是可见的。
  • subview的frame是否在view的可见区域内。

反之,只要以上任何一个条件不满足,我们就认为此subview当前是不可见的。

2.设置view为可见

  • 设置yh_viewVisibleRect为可见区域frame。
  • 设置yh_viewVisible为true。
  • 将view加入superview的yh_visibleSubviews数组。

3.设置view为不可见

  • 设置yh_viewVisibleRectCGRectZero
  • 设置yh_viewVisiblefalse
  • 将view自superviewyh_visibleSubviews数组移除。

Swzzile setFrame:,执行以下操作:

  • 若view是UIScrollView,则根据当前frame和contentInset计算当前yh_viewVisibleRect。不是则将当前frame设置为yh_viewVisibleRect

Swzzile layoutSubivews,调用yh_updateVisibleSubViews方法,其中执行以下操作:

  • 判断view.yh_viewVisible与view自身的可见性,若view不可见,则迭代其subview的为不可见,并终止后续操作。
  • 判断view. yh_visibleSubviews中view是否还是view的subview,不是则设置subview为不可见。
  • 判断是否是UITableViewWrapperView,是则view的yh_viewVisibleRect的originy取其superview的bounds的origin y。这么做是因为实践中发现UITableView设置bounds的会使view的可见区域产生变化,需要重新设置。
  • 遍历view的subview,若subview可见则设置其为可见,否则设置为不可见。

经过以上的这些操作,我们就能知道某个view及其subview的是否可见。

view曝光数据采集

为了取到view对应的数据,同样为UIView添加了以下属性:

  • yh_exposureData:字典类型,用来存储此view节点需要曝光的数据。

那么还有两个问题存在:

  1. view曝光数据的粒度
  2. view及其subview的节点的曝光数据组装时机

view曝光数据的粒度

根据项目中的实践经验,一般以UITableViewCell或者UICollectionViewCell为最小粒度。同时,在最末节点的yh_exposureData字典中,增加一个key:isEnd,用来标识是否已经是最末的节点。

view及其subview的曝光数据组装时机

一般是在最末节点的可见性变化时,由下向上的遍历最末节点的superview,组装所有数据。

因此我们覆写了setYh_viewVisible:的方法,即yh_viewVisible的set方法。执行以下操作:

  • 若当前self.yh_viewVisible变化为false->true,且self.yh_exposureData包含最末节点的标记,则由下向上的遍历最末节点的superview,组装所有数据。
  • 设置self.yh_viewVisible的值。

至此,我们已经解决了view的可见性判断和曝光数据采集的问题。数据上报及策略不在赘述。

此方案有几个缺点

  1. 需要手动设置曝光数据。
  2. 需要在合适时机手工调用view.yh_viewVisible触发数据采集,如viewdidappear等。
  3. 需要消耗一定的资源进行可视区域计算和曝光数据采集。

还有两个问题是值得注意的:

  1. UITableViewsetBounds:时会对view的frame造成改变,因此需要swizzle setBounds:方法,需要在设置bounds后,调用[self yh_updateVisibleSubViews];
  2. UIScrollView在setContentInset:时会影响view的可见区域,因此需要swizzle setContentInset:方法,需要在设置contentInset后,调用self.yh_viewVisibleRect = UIEdgeInsetsInsetRect(self.frame, contentInset);

业务数据自动采集

业务数据自动采集即业界流行的无埋点数据采集。

传统的客户端用户点击数据采集是基于手工埋点的,对哪个位置的数据感兴趣,就在这打个点,用户操作之后,随即触发数据上报。手工埋点的缺点很明显:错埋、漏埋。新版本发布后,经常有数据部门的小伙伴来反馈说,某某点位没有上报,某某点位上报错误的问题,开发的同事也苦不堪言。

无埋点数据采集带来了新的改变。首先基本上避免了手工埋点,个别情况需要特殊处理。其次由选择性的采集数据,变成了全量采集用户的所有点击触摸数据。

新的改变也会带来新的挑战,无埋点数据采集的成为现实的可能性仍然是基于Objective-C的runtime特性。实践过程中,思路上我们借鉴了iOS无埋点数据SDK的整体设计与技术实现,实现上借鉴了Sensors Analytics iOS SDK和Mixpanel iPhone。接下来,结合具体实践,介绍下我们的实现思路和遇到的一些问题。主要分以下三方面:

  1. 自动采集的点位如何确保唯一性。
  2. 不同的点位类型,需要swizzle哪些方法。
  3. swizzle过程中踩到的坑。

自动采集的点位如何确保唯一性

自动采集脱离了手工埋点,因此也没了点位的唯一标识。那我们要怎么唯一定位到自动采集的点位呢?很容易想到的一个方案是:基于页面view的树形结构。此方案可以分解为两个问题:

  1. view唯一标识如何定义。
  2. view唯一标识如何生成。

view唯一标识(view path)的定义

我们规定,一个典型的view path如下:

ViewController[0]/UIView[0]/UITableView[0]/UITableViewCell[0:2]/UIButton[0]

其中:

  1. 通过此标识可以在当前页面view树形结构中唯一的确定此元素。
  2. 标识的每一项由两部分组成:一是当前元素的class的字符串表示,二是当前元素在同级元素中的序号,自0开始计算。如当前第二个UIImageView,则是UIImageView1
  3. 标识不同项之间以/拼接。
  4. 标识的最顶层是当前view所在的ViewController。
  5. 对于UITableViewCell和UICollectionViewCell及类似的自定义组件,序号部分由两部分组成:section和row,并以:拼接。
  6. 标识的最末端是当前被点击或触摸的元素。

view唯一标识如何生成

view path生成过程:由触发操作的最末端元素向上查询,一直查到ViewController为止。假设当前点击view为A_View,从当前的A_View入手遍历view树,每一级的数据存入P_Array中,过程如下:

  1. 如果A_ViewUICollectionViewCell类型,获取A_View所处UICollectionView的indexPath,P_Array push路径信息[NSString stringWithFormat:@"%@[%ld:%ld]",[NSString stringWithFormat:@"%@",NSStringFromClass([A_View class])],(long)indexPath.section, (long)indexPath.row];
  2. 如果A_View是UITableViewCell类型,获取A_View所处UITableView的indexPath,P_Array push路径信息 [NSString stringWithFormat:@"%@[%ld:%ld]",[NSString stringWithFormat:@"%@",NSStringFromClass([A_View class])],(long)indexPath.section, (long)indexPath.row];
  3. 遍历A_View.superview的所有subviews,获取A_View处于同层级,并且同类型([A_View class])中第几个(index),P_Array push路径信息 [NSString stringWithFormat:@"%@[%d]",NSStringFromClass([A_View class]),index];
  4. 获取A_View所处的控制器A_VC,如果A_View是A_VC.view,则遍历结束。如果A_View不等同于A_VC.view,A_View = A_View.superview,重复步骤1-4直到A_View等同于A_VC.view。
  5. 遍历P_Array拼接A_View的完整路径。

各种类型的点位需要swizzle的方法

我们把APP中用户的操作分成四类:

  1. UICollectionView和UITableView的cell点击事件。
  2. UIControl(UISwitch,UIStepper,UISegmentedControl,UINavigationButton,UISlider,UIButton)类控件的点击事件。
  3. UIImageView和UILabel上的UITapGestureRecognizer触摸事件。
  4. UITabBar、UIAlertView、UIActionSheet等的点击事件。

这四类操作,需要swizzle的方法如下表所示:

其中UICollectionView,UITableView,UITabBar,UIAlertView,UIActionSheet实现方式类似,都是在load方法里swizzle setDelegate方法,在setDelegate后进行代理回调方法的swizzle操作,在回调方法中,先去执行原有的逻辑,再去获取对应的viewPath。

UIControl类的组件回调target的时候都会通过UIApplication的sendAction:to:from:forEvent:调用,因此我们选择swizzle此方法。实践中,先去获取对应的view path,再去执行原有逻辑。原因是考虑到如果先执行原有逻辑,页面可能发生变化,获取到的View Controller会出错。

UITapGestureRecognizer的事件则只处理应用在UIImageView、UILabel上的。swizzle addGestureRecognizer:方法,先去执行原有逻辑,然后再给view加上一个自定义的回调方法,这样,当手势触发时,自定义的回调也会被调用,我们在这时获取view path。

swizzle过程中踩到的坑

在测试过程中发现滑动商品列表偶现页面卡死现象,堆栈中的log显示是UICollectionView的yh_didSelectRowAtIndexPath: 自定义的函数被循环调用。

初步判断,应该是swizzle collectionView:didSelectItemAtIndexPath:出了问题。进一步查看代码,此处的swizzle逻辑是:先判断当前子类有没有具体的IMP,如果有就直接交换原IMP和我们自定义函数的IMP,如果子类是继承的,没有具体的函数实现,则先通过class_getMethodImplementation函数读取到在父类中的IMP,添加到子类上,再与自定义函数交换。

这样就会有一个问题:如果上述父类在其他地方,已经被执行过swizzle的逻辑,也就是说父类中的IMP已经与我们自定义的函数交换过,那么此处子类中读取到的IMP就已经是我们自定义函数的实现,所以后续再执行的交换就都是自定义函数IMP的交换,这样就导致了循环调用

因此,我们重新调整了此处swizzle的逻辑:首先判断子类能否响应自定义的函数,如果能则不处理;如果不能说明子类及其父类没有被swizzle过,则执行以下逻辑:按照从子类到父类的顺序,判断是否实现了collectionView:didSelectItemAtIndexPath:,如果有实现则执行原生函数IMP与自定义函数IMP的交换,swizzle结束。这样就避免了重复swizzle的情况。

性能数据自动采集

为了不断的优化客户端的用户体验,需要采集客户端发生的一些操作的性能数据。现阶段我们关心的数据类型有以下几类:

  1. UIViewController加载耗时。
  2. UIWebView加载耗时。
  3. 图片加载耗时。
  4. HTTP请求耗时。
  5. 点击操作响应耗时。

想要无侵入的统计上述数据,还是要借助runtime的魔力。

为了获取上述数据,需要swizzle的方法如下:

相应说明如下:

UIViewController加载时间统计,只需要在viewDidLoad里记录开始时间,在viewDidAppear里记录结束时间,即可得出加载耗时。

UIWebView加载时间统计,统计口径稍有不同。我们关注的是UIViewController打开到用户看到UIWebView内容这之间的耗时。因此我们需要在viewDidLoad里记录开始时间,在webViewDidFinishLoad里记录结束时间,即可得出加载耗时。

图片加载时间统计,图片加载我们用的是SDWebImage,因此只需对SDWebImageManager swizzle downloadImageWithURL:options:progress:completed:方法即可。

HTTP请求加载时间统计,需要同时处理NSURLConnection和NSURLSession的情况。对于NSURLConnection,除了上表列出来的方法,还需要自定义一个delegate接管所有的delegate相关操作,并转发到用户定义的delegate上。还要注意重写forwardingTargetForSelector:方法,增加以下操作:我们自定义的delegate里没有实现的代理方法,先判断是用户自定义的delegate是否实现了,如果是,则转发过去。

对于NSURLSession,请求开始时间要在resume方法里统计,此外swizzle resume方法时,需要采用一些特别是技巧,不然会swizzle不到,这点请自行google。

swizzle dataTaskWithRequest:completionHandler:和downloadTaskWithRequest:completionHandler:时,注意点是先判断completionHandler是否为nil,如果是直接调用原有逻辑即可。不然会导致completionHandler为nil的请求超时。

点击操作的响应耗时,我们只关注UIButton,只需swizzle sendAction:to:forEvent:,获取此方法原有逻辑的执行时间即可。

至此,有货iOS APP数据采集的思路和做法已经大略介绍结束。实践过程中,会遇到更多的困难和挑战。runtime像是一把锋利的菜刀,大厨拿在手里能做出美味佳肴,学徒却会不小心切到手,伤到自己,甚至别人。然而发现问题,解决问题这才是乐趣所在,踩坑挖坑填坑之路永不会停止,盼与诸君砥砺前行。

作者简介:

曹镏,有货技术部前端总监, 有超过5年的APP研发、管理经验。 关注前端架构、模块化/组件化。

感谢覃云对本文的审校。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

3334561427 by 上海开票_上海开发票_ 上海市新闻网

www.nyrcw.com.cn/zhiwei/job-3200.html
www.nyrcw.com.cn/zhiwei/company-2876.html
www.nyrcw.com.cn/zhiwei/job-3199.html
www.nyrcw.com.cn/zhiwei/company-2875.html
www.nyrcw.com.cn/zhiwei/job-3198.html
www.nyrcw.com.cn/zhiwei/company-2874.html
www.nyrcw.com.cn/zhiwei/job-3197.html
www.nyrcw.com.cn/zhiwei/company-2873.html
www.nyrcw.com.cn/zhiwei/job-3196.html
www.nyrcw.com.cn/zhiwei/company-2872.html
www.nyrcw.com.cn/zhiwei/job-3195.html
www.nyrcw.com.cn/zhiwei/company-2871.html
www.nyrcw.com.cn/zhiwei/job-3194.html
www.nyrcw.com.cn/zhiwei/company-2870.html
www.nyrcw.com.cn/zhiwei/job-3193.html
www.nyrcw.com.cn/zhiwei/company-2869.html
www.nyrcw.com.cn/zhiwei/job-3192.html
www.nyrcw.com.cn/zhiwei/company-2868.html
www.nyrcw.com.cn/zhiwei/job-3191.html
www.nyrcw.com.cn/zhiwei/company-2867.html
www.nyrcw.com.cn/zhiwei/job-3190.html
www.nyrcw.com.cn/zhiwei/company-2866.html
www.nyrcw.com.cn/zhiwei/job-3189.html
www.nyrcw.com.cn/zhiwei/company-2865.html
www.nyrcw.com.cn/zhiwei/job-3188.html
www.nyrcw.com.cn/zhiwei/company-2864.html
www.nyrcw.com.cn/zhiwei/job-3187.html
www.nyrcw.com.cn/zhiwei/company-2863.html
www.nyrcw.com.cn/zhiwei/job-3186.html
www.nyrcw.com.cn/zhiwei/company-2862.html
www.nyrcw.com.cn/zhiwei/job-3185.html
www.nyrcw.com.cn/zhiwei/company-2861.html
www.nyrcw.com.cn/zhiwei/job-3184.html
www.nyrcw.com.cn/zhiwei/company-2860.html
www.nyrcw.com.cn/zhiwei/job-3183.html
www.nyrcw.com.cn/zhiwei/company-2859.html
www.nyrcw.com.cn/zhiwei/job-3182.html
www.nyrcw.com.cn/zhiwei/company-2858.html
www.nyrcw.com.cn/zhiwei/job-3181.html
www.nyrcw.com.cn/zhiwei/company-2857.html
www.nyrcw.com.cn/zhiwei/job-3180.html
www.nyrcw.com.cn/zhiwei/company-2856.html
www.nyrcw.com.cn/zhiwei/job-3179.html
www.nyrcw.com.cn/zhiwei/company-2855.html
www.nyrcw.com.cn/zhiwei/job-3178.html
www.nyrcw.com.cn/zhiwei/company-2854.html
www.nyrcw.com.cn/zhiwei/job-3177.html
www.nyrcw.com.cn/zhiwei/company-2853.html
www.nyrcw.com.cn/zhiwei/job-3176.html
www.nyrcw.com.cn/zhiwei/company-2852.html
www.nyrcw.com.cn/zhiwei/job-3175.html
www.nyrcw.com.cn/zhiwei/company-2851.html
www.nyrcw.com.cn/zhiwei/job-3174.html
www.nyrcw.com.cn/zhiwei/company-2850.html
www.nyrcw.com.cn/zhiwei/job-3173.html
www.nyrcw.com.cn/zhiwei/company-2849.html
www.nyrcw.com.cn/zhiwei/job-3172.html
www.nyrcw.com.cn/zhiwei/company-2848.html
www.nyrcw.com.cn/zhiwei/job-3171.html
www.nyrcw.com.cn/zhiwei/company-2847.html
www.nyrcw.com.cn/zhiwei/job-3170.html
www.nyrcw.com.cn/zhiwei/company-2846.html
www.nyrcw.com.cn/zhiwei/job-3169.html
www.nyrcw.com.cn/zhiwei/company-2845.html
www.nyrcw.com.cn/zhiwei/job-3168.html
www.nyrcw.com.cn/zhiwei/company-2844.html
www.nyrcw.com.cn/zhiwei/job-3167.html
www.nyrcw.com.cn/zhiwei/company-2843.html
www.nyrcw.com.cn/zhiwei/job-3166.html
www.nyrcw.com.cn/zhiwei/company-2842.html
www.nyrcw.com.cn/zhiwei/job-3165.html
www.nyrcw.com.cn/zhiwei/company-2841.html
www.nyrcw.com.cn/zhiwei/job-3164.html
www.nyrcw.com.cn/zhiwei/company-2840.html
www.nyrcw.com.cn/zhiwei/job-3163.html
www.nyrcw.com.cn/zhiwei/company-2839.html
www.nyrcw.com.cn/zhiwei/job-3162.html
www.nyrcw.com.cn/zhiwei/company-2838.html
www.nyrcw.com.cn/zhiwei/job-3161.html
www.nyrcw.com.cn/zhiwei/company-2837.html
www.nyrcw.com.cn/zhiwei/job-3160.html
www.nyrcw.com.cn/zhiwei/company-2836.html
www.nyrcw.com.cn/zhiwei/job-3159.html
www.nyrcw.com.cn/zhiwei/company-2835.html
www.nyrcw.com.cn/zhiwei/job-3158.html
www.nyrcw.com.cn/zhiwei/company-2834.html
www.nyrcw.com.cn/zhiwei/job-3157.html
www.nyrcw.com.cn/zhiwei/company-2833.html
www.nyrcw.com.cn/zhiwei/job-3156.html
www.nyrcw.com.cn/zhiwei/company-2832.html
www.nyrcw.com.cn/zhiwei/job-3155.html
www.nyrcw.com.cn/zhiwei/company-2831.html
www.nyrcw.com.cn/zhiwei/job-3154.html
www.nyrcw.com.cn/zhiwei/company-2830.html
www.nyrcw.com.cn/zhiwei/job-3153.html
www.nyrcw.com.cn/zhiwei/company-2829.html
www.nyrcw.com.cn/zhiwei/job-3152.html
www.nyrcw.com.cn/zhiwei/company-2828.html
www.nyrcw.com.cn/zhiwei/job-3151.html
www.nyrcw.com.cn/zhiwei/company-2827.html
www.nyrcw.com.cn/zhiwei/job-3150.html
www.nyrcw.com.cn/zhiwei/company-2826.html
www.nyrcw.com.cn/zhiwei/job-3149.html
www.nyrcw.com.cn/zhiwei/company-2825.html
www.nyrcw.com.cn/zhiwei/job-3148.html
www.nyrcw.com.cn/zhiwei/company-2824.html
www.nyrcw.com.cn/zhiwei/job-3147.html
www.nyrcw.com.cn/zhiwei/company-2823.html
www.nyrcw.com.cn/zhiwei/job-3146.html
www.nyrcw.com.cn/zhiwei/company-2822.html
www.nyrcw.com.cn/zhiwei/job-3145.html
www.nyrcw.com.cn/zhiwei/company-2821.html
www.nyrcw.com.cn/zhiwei/job-3144.html
www.nyrcw.com.cn/zhiwei/company-2820.html
www.nyrcw.com.cn/zhiwei/job-3143.html
www.nyrcw.com.cn/zhiwei/company-2819.html
www.nyrcw.com.cn/zhiwei/job-3142.html
www.nyrcw.com.cn/zhiwei/company-2815.html
www.nyrcw.com.cn/zhiwei/job-3141.html
www.nyrcw.com.cn/zhiwei/company-2814.html
www.nyrcw.com.cn/zhiwei/job-3140.html
www.nyrcw.com.cn/zhiwei/company-2812.html
www.nyrcw.com.cn/zhiwei/job-3139.html
www.nyrcw.com.cn/zhiwei/company-2811.html
www.nyrcw.com.cn/zhiwei/job-3138.html
www.nyrcw.com.cn/zhiwei/company-2810.html
www.nyrcw.com.cn/zhiwei/job-3137.html
www.nyrcw.com.cn/zhiwei/company-2809.html
www.nyrcw.com.cn/zhiwei/job-3136.html
www.nyrcw.com.cn/zhiwei/company-2808.html
www.nyrcw.com.cn/zhiwei/job-3135.html
www.nyrcw.com.cn/zhiwei/company-2807.html
www.nyrcw.com.cn/zhiwei/job-3134.html
www.nyrcw.com.cn/zhiwei/company-2806.html
www.nyrcw.com.cn/zhiwei/job-3133.html
www.nyrcw.com.cn/zhiwei/company-2805.html
www.nyrcw.com.cn/zhiwei/job-3132.html
www.nyrcw.com.cn/zhiwei/company-2804.html
www.nyrcw.com.cn/zhiwei/job-3131.html
www.nyrcw.com.cn/zhiwei/company-2803.html
www.nyrcw.com.cn/zhiwei/job-3130.html
www.nyrcw.com.cn/zhiwei/company-2802.html
www.nyrcw.com.cn/zhiwei/job-3129.html
www.nyrcw.com.cn/zhiwei/company-2801.html
www.nyrcw.com.cn/zhiwei/job-3128.html
www.nyrcw.com.cn/zhiwei/company-2800.html
www.nyrcw.com.cn/zhiwei/job-3127.html
www.nyrcw.com.cn/zhiwei/company-2799.html
www.nyrcw.com.cn/zhiwei/job-3126.html
www.nyrcw.com.cn/zhiwei/company-2797.html
www.nyrcw.com.cn/zhiwei/job-3125.html
www.nyrcw.com.cn/zhiwei/company-2796.html
www.nyrcw.com.cn/zhiwei/job-3124.html
www.nyrcw.com.cn/zhiwei/company-2795.html
www.nyrcw.com.cn/zhiwei/job-3123.html
www.nyrcw.com.cn/zhiwei/company-2794.html
www.nyrcw.com.cn/zhiwei/job-3122.html
www.nyrcw.com.cn/zhiwei/company-2791.html
www.nyrcw.com.cn/zhiwei/job-3121.html
www.nyrcw.com.cn/zhiwei/company-2790.html
www.nyrcw.com.cn/zhiwei/job-3120.html
www.nyrcw.com.cn/zhiwei/company-2789.html
www.nyrcw.com.cn/zhiwei/job-3119.html
www.nyrcw.com.cn/zhiwei/company-2788.html
www.nyrcw.com.cn/zhiwei/job-3118.html
www.nyrcw.com.cn/zhiwei/company-2787.html
www.nyrcw.com.cn/zhiwei/job-3117.html
www.nyrcw.com.cn/zhiwei/company-2786.html
www.nyrcw.com.cn/zhiwei/job-3116.html
www.nyrcw.com.cn/zhiwei/company-2785.html
www.nyrcw.com.cn/zhiwei/job-3115.html
www.nyrcw.com.cn/zhiwei/company-2784.html
www.nyrcw.com.cn/zhiwei/job-3114.html
www.nyrcw.com.cn/zhiwei/company-2783.html
www.nyrcw.com.cn/zhiwei/job-3113.html
www.nyrcw.com.cn/zhiwei/company-2782.html
www.nyrcw.com.cn/zhiwei/job-3112.html
www.nyrcw.com.cn/zhiwei/company-2781.html
www.nyrcw.com.cn/zhiwei/job-3111.html
www.nyrcw.com.cn/zhiwei/company-2780.html
www.nyrcw.com.cn/zhiwei/job-3110.html
www.nyrcw.com.cn/zhiwei/company-2779.html
www.nyrcw.com.cn/zhiwei/job-3109.html
www.nyrcw.com.cn/zhiwei/company-2778.html
www.nyrcw.com.cn/zhiwei/job-3108.html
www.nyrcw.com.cn/zhiwei/company-2777.html
www.nyrcw.com.cn/zhiwei/job-3107.html
www.nyrcw.com.cn/zhiwei/company-2776.html
www.nyrcw.com.cn/zhiwei/job-3106.html
www.nyrcw.com.cn/zhiwei/company-2775.html
www.nyrcw.com.cn/zhiwei/job-3105.html
www.nyrcw.com.cn/zhiwei/company-2774.html
www.nyrcw.com.cn/zhiwei/job-3104.html
www.nyrcw.com.cn/zhiwei/company-2772.html
www.nyrcw.com.cn/zhiwei/job-3103.html
www.nyrcw.com.cn/zhiwei/company-2771.html
www.nyrcw.com.cn/zhiwei/job-3102.html
www.nyrcw.com.cn/zhiwei/company-2770.html
www.nyrcw.com.cn/zhiwei/job-3101.html
www.nyrcw.com.cn/zhiwei/company-2769.html
www.nyrcw.com.cn/zhiwei/job-3100.html
www.nyrcw.com.cn/zhiwei/company-2768.html
www.nyrcw.com.cn/zhiwei/job-3099.html
www.nyrcw.com.cn/zhiwei/company-2767.html
www.nyrcw.com.cn/zhiwei/job-3098.html
www.nyrcw.com.cn/zhiwei/company-2766.html
www.nyrcw.com.cn/zhiwei/job-3097.html
www.nyrcw.com.cn/zhiwei/company-2765.html
www.nyrcw.com.cn/zhiwei/job-3096.html
www.nyrcw.com.cn/zhiwei/company-2764.html
www.nyrcw.com.cn/zhiwei/job-3095.html
www.nyrcw.com.cn/zhiwei/company-2763.html
www.nyrcw.com.cn/zhiwei/job-3094.html
www.nyrcw.com.cn/zhiwei/company-2762.html
www.nyrcw.com.cn/zhiwei/job-3093.html
www.nyrcw.com.cn/zhiwei/company-2761.html
www.nyrcw.com.cn/zhiwei/job-3092.html
www.nyrcw.com.cn/zhiwei/company-2760.html
www.nyrcw.com.cn/zhiwei/job-3091.html
www.nyrcw.com.cn/zhiwei/company-2758.html
www.nyrcw.com.cn/zhiwei/job-3090.html
www.nyrcw.com.cn/zhiwei/company-2757.html
www.nyrcw.com.cn/zhiwei/job-3089.html
www.nyrcw.com.cn/zhiwei/company-2756.html
www.nyrcw.com.cn/zhiwei/job-3088.html
www.nyrcw.com.cn/zhiwei/company-2755.html
www.nyrcw.com.cn/zhiwei/job-3087.html
www.nyrcw.com.cn/zhiwei/company-2754.html
www.nyrcw.com.cn/zhiwei/job-3086.html
www.nyrcw.com.cn/zhiwei/company-2753.html
www.nyrcw.com.cn/zhiwei/job-3085.html
www.nyrcw.com.cn/zhiwei/company-2752.html
www.nyrcw.com.cn/zhiwei/job-3084.html
www.nyrcw.com.cn/zhiwei/company-2751.html
www.nyrcw.com.cn/zhiwei/job-3083.html
www.nyrcw.com.cn/zhiwei/company-2750.html
www.nyrcw.com.cn/zhiwei/job-3082.html
www.nyrcw.com.cn/zhiwei/company-2749.html
www.nyrcw.com.cn/zhiwei/job-3081.html
www.nyrcw.com.cn/zhiwei/company-2748.html
www.nyrcw.com.cn/zhiwei/job-3080.html
www.nyrcw.com.cn/zhiwei/company-2746.html
www.nyrcw.com.cn/zhiwei/job-3079.html
www.nyrcw.com.cn/zhiwei/company-2745.html
www.nyrcw.com.cn/zhiwei/job-3078.html
www.nyrcw.com.cn/zhiwei/company-2744.html
www.nyrcw.com.cn/zhiwei/job-3077.html
www.nyrcw.com.cn/zhiwei/company-2742.html
www.nyrcw.com.cn/zhiwei/job-3076.html
www.nyrcw.com.cn/zhiwei/company-2741.html
www.nyrcw.com.cn/zhiwei/job-3075.html
www.nyrcw.com.cn/zhiwei/company-2740.html
www.nyrcw.com.cn/zhiwei/job-3074.html
www.nyrcw.com.cn/zhiwei/company-2739.html
www.nyrcw.com.cn/zhiwei/job-3073.html
www.nyrcw.com.cn/zhiwei/company-2738.html
www.nyrcw.com.cn/zhiwei/job-3072.html
www.nyrcw.com.cn/zhiwei/company-2737.html
www.nyrcw.com.cn/zhiwei/job-3071.html
www.nyrcw.com.cn/zhiwei/company-2736.html
www.nyrcw.com.cn/zhiwei/job-3070.html
www.nyrcw.com.cn/zhiwei/company-2735.html
www.nyrcw.com.cn/zhiwei/job-3069.html
www.nyrcw.com.cn/zhiwei/company-2734.html
www.nyrcw.com.cn/zhiwei/job-3068.html
www.nyrcw.com.cn/zhiwei/company-2733.html
www.nyrcw.com.cn/zhiwei/job-3067.html
www.nyrcw.com.cn/zhiwei/company-2732.html
www.nyrcw.com.cn/zhiwei/job-3066.html
www.nyrcw.com.cn/zhiwei/company-2731.html
www.nyrcw.com.cn/zhiwei/job-3065.html
www.nyrcw.com.cn/zhiwei/company-2730.html
www.nyrcw.com.cn/zhiwei/job-3064.html
www.nyrcw.com.cn/zhiwei/company-2729.html
www.nyrcw.com.cn/zhiwei/job-3063.html
www.nyrcw.com.cn/zhiwei/company-2728.html
www.nyrcw.com.cn/zhiwei/job-3062.html
www.nyrcw.com.cn/zhiwei/company-2727.html
www.nyrcw.com.cn/zhiwei/job-3061.html
www.nyrcw.com.cn/zhiwei/company-2726.html
www.nyrcw.com.cn/zhiwei/job-3060.html
www.nyrcw.com.cn/zhiwei/company-2725.html
www.nyrcw.com.cn/zhiwei/job-3059.html
www.nyrcw.com.cn/zhiwei/company-2724.html
www.nyrcw.com.cn/zhiwei/job-3058.html
www.nyrcw.com.cn/zhiwei/company-2723.html
www.nyrcw.com.cn/zhiwei/job-3057.html
www.nyrcw.com.cn/zhiwei/company-2722.html
www.nyrcw.com.cn/zhiwei/job-3056.html
www.nyrcw.com.cn/zhiwei/company-2721.html
www.nyrcw.com.cn/zhiwei/job-3055.html
www.nyrcw.com.cn/zhiwei/company-2720.html
www.nyrcw.com.cn/zhiwei/job-3054.html
www.nyrcw.com.cn/zhiwei/company-2719.html
www.nyrcw.com.cn/zhiwei/job-3053.html
www.nyrcw.com.cn/zhiwei/company-2718.html
www.nyrcw.com.cn/zhiwei/job-3052.html
www.nyrcw.com.cn/zhiwei/company-2717.html
www.nyrcw.com.cn/zhiwei/job-3051.html
www.nyrcw.com.cn/zhiwei/company-2716.html
www.nyrcw.com.cn/zhiwei/job-3050.html
www.nyrcw.com.cn/zhiwei/company-2715.html
www.nyrcw.com.cn/zhiwei/job-3049.html
www.nyrcw.com.cn/zhiwei/company-2714.html
www.nyrcw.com.cn/zhiwei/job-3048.html
www.nyrcw.com.cn/zhiwei/company-2713.html
www.nyrcw.com.cn/zhiwei/job-3047.html
www.nyrcw.com.cn/zhiwei/company-2712.html
www.nyrcw.com.cn/zhiwei/job-3046.html
www.nyrcw.com.cn/zhiwei/company-2711.html
www.nyrcw.com.cn/zhiwei/job-3045.html
www.nyrcw.com.cn/zhiwei/company-2710.html
www.nyrcw.com.cn/zhiwei/job-3044.html
www.nyrcw.com.cn/zhiwei/company-2709.html
www.nyrcw.com.cn/zhiwei/job-3043.html
www.nyrcw.com.cn/zhiwei/company-2708.html
www.nyrcw.com.cn/zhiwei/job-3042.html
www.nyrcw.com.cn/zhiwei/company-2707.html
www.nyrcw.com.cn/zhiwei/job-3041.html
www.nyrcw.com.cn/zhiwei/company-2706.html
www.nyrcw.com.cn/zhiwei/job-3040.html
www.nyrcw.com.cn/zhiwei/company-2705.html
www.nyrcw.com.cn/zhiwei/job-3039.html
www.nyrcw.com.cn/zhiwei/company-2704.html
www.nyrcw.com.cn/zhiwei/job-3038.html
www.nyrcw.com.cn/zhiwei/company-2703.html
www.nyrcw.com.cn/zhiwei/job-3037.html
www.nyrcw.com.cn/zhiwei/company-2702.html
www.nyrcw.com.cn/zhiwei/job-3036.html
www.nyrcw.com.cn/zhiwei/company-2701.html
www.nyrcw.com.cn/zhiwei/job-3035.html
www.nyrcw.com.cn/zhiwei/company-2700.html
www.nyrcw.com.cn/zhiwei/job-3034.html
www.nyrcw.com.cn/zhiwei/company-2699.html
www.nyrcw.com.cn/zhiwei/job-3033.html
www.nyrcw.com.cn/zhiwei/company-2698.html
www.nyrcw.com.cn/zhiwei/job-3032.html
www.nyrcw.com.cn/zhiwei/company-2697.html
www.nyrcw.com.cn/zhiwei/job-3031.html
www.nyrcw.com.cn/zhiwei/company-2696.html
www.nyrcw.com.cn/zhiwei/job-3030.html
www.nyrcw.com.cn/zhiwei/company-2695.html
www.nyrcw.com.cn/zhiwei/job-3029.html
www.nyrcw.com.cn/zhiwei/company-2694.html
www.nyrcw.com.cn/zhiwei/job-3028.html
www.nyrcw.com.cn/zhiwei/company-2693.html
www.nyrcw.com.cn/zhiwei/job-3027.html
www.nyrcw.com.cn/zhiwei/company-2692.html
www.nyrcw.com.cn/zhiwei/job-3026.html
www.nyrcw.com.cn/zhiwei/company-2691.html
www.nyrcw.com.cn/zhiwei/job-3025.html
www.nyrcw.com.cn/zhiwei/company-2690.html
www.nyrcw.com.cn/zhiwei/job-3024.html
www.nyrcw.com.cn/zhiwei/company-2688.html
www.nyrcw.com.cn/zhiwei/job-3023.html
www.nyrcw.com.cn/zhiwei/company-2686.html
www.nyrcw.com.cn/zhiwei/job-3022.html
www.nyrcw.com.cn/zhiwei/company-2685.html
www.nyrcw.com.cn/zhiwei/job-3021.html
www.nyrcw.com.cn/zhiwei/company-2684.html
www.nyrcw.com.cn/zhiwei/job-3020.html
www.nyrcw.com.cn/zhiwei/company-2683.html
www.nyrcw.com.cn/zhiwei/job-3019.html
www.nyrcw.com.cn/zhiwei/company-2682.html
www.nyrcw.com.cn/zhiwei/job-3018.html
www.nyrcw.com.cn/zhiwei/company-2681.html
www.nyrcw.com.cn/zhiwei/job-3017.html
www.nyrcw.com.cn/zhiwei/company-2680.html
www.nyrcw.com.cn/zhiwei/job-3016.html
www.nyrcw.com.cn/zhiwei/company-2679.html
www.nyrcw.com.cn/zhiwei/job-3015.html
www.nyrcw.com.cn/zhiwei/company-2678.html
www.nyrcw.com.cn/zhiwei/job-3014.html
www.nyrcw.com.cn/zhiwei/company-2677.html
www.nyrcw.com.cn/zhiwei/job-3013.html
www.nyrcw.com.cn/zhiwei/company-2676.html
www.nyrcw.com.cn/zhiwei/job-3012.html
www.nyrcw.com.cn/zhiwei/company-2676.html
www.nyrcw.com.cn/zhiwei/job-3011.html
www.nyrcw.com.cn/zhiwei/company-2675.html
www.nyrcw.com.cn/zhiwei/job-3010.html
www.nyrcw.com.cn/zhiwei/company-2674.html
www.nyrcw.com.cn/zhiwei/job-3009.html
www.nyrcw.com.cn/zhiwei/company-2673.html

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

1 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT