Skip to content

4.3 转换器

desert edited this page Apr 29, 2018 · 10 revisions

转换器是最为常用的一种类型,当然它的使用也是最复杂的。

[TOC]

1. 基础概念

转换器有三种子类型:

  • UDF:单文档->单文档:如提取数字, 如删除该列,它仅涉及文档内部的修改
  • UDAF:单文档->多文档:典型的如从爬虫转换,每一行url都可能生成20个甚至更多的文档,它的行为很像cross(交叉)模式下的生成器。
  • C:多文档->单文档:很少见,需要时再进行介绍

如果你熟悉ODPS,A模式其实是UDF,B模式是UDAF。

绝大多数转换器都是UDF类型。但同一个转换器在不同的配置下,可能会有多种行为,例如从爬虫转换,如果选择的网页采集器为One(单文档)模式,则该转换器为UDF模式,若为List模式,则为UDAF模式。

1.2 关于输入列和输出列

输入列,就是要输入这个模块的列,(Hawk1时代也称作原列名); 输出列,则指的是模块输出的列。 UDF模式下,如果新列名为空,则新列名等于原列名,直接修改在原始列上。

如果在UDAF模式下,参考UDAF的特别说明

我承认我实在不会起名字,各种变量的名字和模块的名字设计的都不好,可惜一旦发布出去,就很难再修改了。在杭州喝了点酒,写文档晕乎乎的哈哈哈。

1.3 UDAF的特别说明

当你使用List模式的爬虫,或单转多时,虽然生成了多个文档,但原始的数据(如URL)不见了。这是因为Hawk丢弃了这些列。

经过大量实践,如果不这么做,每个新数据后面,都会跟上原始的老数据,如果1转20,则老数据会重复生成20次,这是没有必要的。有时不得不拖入大量的删除该列来 当然,有时转换时需要包含原始数据的部分列,则可在转换器的新列名中填写要鲤鱼跳龙门的列的名称,中间用空格分割。

在Hawk3中,还支持在新列名中输入*号,此时所有的原始列都会添到新的文档之中。 注意,UDAF的新列可能会覆盖掉原始列的数据,因此多检查列名,避免意料之外的覆盖。

2. 各模块使用说明

2.1 删除该列,添加新列,修改列名

向要删除的列,直接拖入删除该列,即可删掉。

由于删除之后,该工具就看不到了,要想修改可以在左侧的模块列表里选择,修改和删除。

修改列名:拖入的列是原始列,填写新列名后,数据就转换到了新列上去。也可直接在列上的文本框中修改列名,效果是类似的。

2.2 合并多列

神器之一!

该模块可以将多个列合并成一个列。常见的如将page合并到url中,也可以通过文件名,合并出要保存的文件的位置,是使用次数最多的模块。

例如: format= {0}+{1}+{2}

能把三个列的内容用加号拼接起来。{0}代表拖入的列名,其他{1}{2}则需要其他列的名字来指定,例如其他列分别为B和C,则:

其他列= B C (中间用空格分割,不支持方括号表达式)

这种字符串表示法,使用的是C#的string.fomat语法。 注意括号是大括号

2.2 分页

Hawk3 新增的功能,非常实用简单!当遇到"总共2000个元素,每页30个,然后要生成页数,来产生url"的场景里非常合适。

拖入的列需要为数字,代表总数,填入最小值(也就是从几开始)和每页数量,即可生成分页的编号。当然,最小值和每页数量都可以使用方括号表达式。

2.2 正则转换器,提取数字

正则转换器需要列名,它需要输入正则表达式,可匹配一个和多个内容。

设置匹配编号为正数n时,它可将第n个匹配结果转换到新列上。如果不填写新列名,则内容直接覆盖原始列。

若编号为小于0且匹配出多个结果,可以将多个输出列名可用空格分割,写在新列名里(记不记得新列名就是输出?),若该列不需要添加,可用_表示,如编号为-1, 输出列a b _ d, 匹配的四个结果会分别放到a,b,忽略和d列。

提取数字是正则转换器的特例,它能够提取浮点或整数,也能包含正负数。

如果选择反向,则会返回倒数第n个内容。如果没有发现匹配,则返回空。

2.3 字符分割,正则分割

需要列名,Hawk会通过字符或正则表达式分割目标列,返回第n个内容。 若勾选倒序,则返回倒数第n个内容。

2.4 正则替换

需要列名,使用正则表达式替换目标文本。此工具非常有用,强烈建议学习正则表达式。

2.5 字符首尾抽取

当文本为CABD时,需要获取B,而B非常长,写正则表达式提取有很大困难时,可以使用本模块。 此时,首串填写A,尾串填写D,则Hawk就能将B夹逼出来。如果勾选包含首尾字符,则输出ABD,否则只有B。

注意,建议A和D在文本中是唯一的,否则抽取出来的B可能并不是你想要的。 该工具特别适合在抽取网页的某一特定内容时使用。

2.6 Python转换器

神器!神器!神器! 你可以编写多行的类似Python3风格的代码,支持中文变量,中文字符串也不需要在前面加u。 举几个例子:

  1. 将A列的内容,赋值到B列: data[B]=data[A]
  2. 将A列的内容删掉 del data[A]
  3. 如果列名填写了A,则value代表A列的值,可以直接写 (value)+1

python转换器也有三种工作模式:

  • 不进行转换: 直接将结果填入该单元格
  • One: 将得到的文档,横向拼接在原始文档右边
  • List: 此时转换器行为,特别类似List模式下的网页采集器。

注意:

  1. 你可以在文本框中定义函数,但不建议太过复杂
  2. 很难引入第三方库,这受限于C#使用的ironpython(一个C#和Python交互的模块)的功能, Hawk3中引入了调用第三方库的功能,通过编写库路径,从而能够在脚本中import库,但功能支持并不好。
  3. 不论操作如何,脚本的最后一行需要是个可求值的元素,传递给对应的列,比如: return a #这是错误的 a+b 正确,可求值 lambda x:x+1 你确定要返回一个函数或lambda?肯定也是不对的
  4. data就是该行字典的默认命名,value是该单元格的默认命名,假设列名为A,则data[A]==value
  5. Python是强类型语言,输入的数据可能是字符串或数字,因此必要时需要做类型转换
  6. 其他细节请参考相关Python书籍。

2.7 Json转换器

当输入字符是Json时,可以通过Json转换器将文本转换为Json.其工作模式和python转换器一样,此处不赘述。

常见的问题是,网页给出的json格式并不标准,此时需要通过其他工具,对字符串进行预处理,方可转换为json。 json转换器的转换结果,实际上是一个动态类型的python对象。例如如下json:

{
  'key':[{}{}{}]
  'value':
        {
          'key1':value
          'key2':value
        }
}

拖入json转换器到该列,如果工作模式是NoTransform,则你可以在转换结果列,拖入python转换器,脚本内容填写data[key],工作模式选择List,则key中的数组自动会被提取出来。

其他使用方法就不多讲了,可以多试验。python和json转换器配合使用,能够解决一大类ajax网页的问题。更详细的内容,可参考3.1 动态嗅探

当然,如果json非常复杂,是不建议直接用Hawk做数据清洗的,正确的做法是将json保存成文本,之后用其他工具或手工编写代码后处理。

2.8 清除空白符

默认能去掉文本前后的空白字符,也可以通过勾选内部选项,清除文本中间的空白符。当然使用正则替换也能实现类似的要求,只是本模块会更简单。

2.9 并行

该转换器在调试模式和串行执行模式不起任何作用,仅仅作为一个标志。它能够在并行模式下,给执行引擎一个并行分叉的标志。还能设置为每个子线程分配多少个种子文档。具体的并行设置,参考4.4并行化

2.10 自增主键

可以添加新的一列,从1开始的自增主键。

2.11 搜索位置等web模块

自己研究吧