设计爬虫Hawk背后的故事

五年之痒

2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk。我花不少时间优化和推广它,得到的评价还算比较正面,因为负面评价也没什么渠道进我耳朵。

不过你知道我写这个东西花了多久吗? 掐头去尾,这是第五个年头了。

读研究生伊始,实验室开始做数据挖掘,但我发现大家做研究,都是一段段的代码,遇到新问题,就不得不再拷贝一份修改,很少想过复用。于是我便花了一年的时间,开发了一款现在看起来配色丧心病狂的“数据挖掘软件”:

它居然能在上面刷微博,能把任何一个学姐学妹在微博的蛛丝马迹全扒出来,渲染出配色更丧病的绚丽图表。实验室老师最喜欢拿这套软件给参观的领导演示了。

我多少有点偏执,想用纯图形化的方式构建数据挖掘的全部流程:从获取清洗数据,建模,训练到最后可视化。但以我当时的算法和软件水平,这样的东西根本就不可能做完善,我还意淫着能把它商业化。最终结果,是它跟着我一起毕业,除了我和几个学弟之外,没人用过。

工作后,靠业余时间维护它有很大的困难。数不清的bug和时间花销,让它成了拖后腿的包袱。一些考虑不周的接口,设计于几年之前,后来想修改却花费巨大。更重要的是,它的未来在哪里?

时值2015年,桌面软件已死,web都已过时,移动端才是兵家必争之地。这种大杂烩和复杂度,普通人不可能会用,程序员没有文档不爱用,大神不屑于用。

我也不想让它扔在历史的故纸堆里无人问津,索性就开源吧!

在开源之前,我做了一件事,将它改名为Hawk,寓意为驰骋天空的鹰;把我自己用的次数少于10次的组件全部删掉,连3D可视化,统计和预测模块也不幸免:只保留爬虫和数据清洗,因为分析和挖掘已经有其他工具做得更好了,比如Python那无比强大的工具链。我认识到,只做一件事,并将其做好是多么重要。

老司机送它上路了,那一天,它正式出现在GitHub上(此处应当有掌声^_^)

我对Hawk的评价

我就是用程序员的思路去设计Hawk的,好玩有趣是最重要的。

先说优点:起码它能用,几乎没接触过编程的人,也能在看过教程后,做出他自己的设计,熟练后效率会很高。

我最喜欢的是手气不错,升级Hawk2.0之后,绝大多数网页都可以通过一键提取数据。其实原理很简单,就是树结构的模板匹配。

其次便是那个所见即所得的数据清洗,在调试模式下快速设计任务,在执行模式下并行执行。恕我孤陋寡闻,这种基于流式管线思路,在其他软件上用的并不多。

最后便是子任务,再复杂的需求,都可以通过子任务分而治之,比如多次定向跳转。这东西让八爪鱼和火车头去试试看?

Hawk最大的价值,是将复杂的逻辑链条化和可视化了,你可以将代码变得不那么耦合,像搭积木一样方便地组合。当然这些都拜于函数式编程的思想所赐。

再说缺点:Hawk有很多的bug,没单元测试,功能不完善。但这都不是最根本的缺点,最根本是难于实现条件判断和循环,你很难写出if,switch和while。 这也是函数式语言的共同问题,你不得不逼迫自己用另外的思路去解决。虽然通过引入子任务,能“不够优雅”地解决它,但依旧要花费不少脑筋。

有的人觉得Hawk不够强,这是因为它是图形化软件。为什么具备UI的软件很难和命令行相比?因为设计UI的新功能时,不仅需要考虑它的算法,更要考虑它如何在UI上呈现。有些功能非常有用,比如爬虫常见的BFS和DFS(深度和广度优先遍历),但在UI上配置会异常繁琐,我不得不将它们抛弃掉,只保留最常用的功能。

为什么呢?轻松写BFS的人,会想用Hawk吗?应该不会,他们也许会直接敲代码。

Python版本的Hawk: etlpy

因为图形界面和C#本身的诸多不足,我开始发展了Python的Hawk,称为etlpy (Extract-Transform-Load in Python)

最初的想法,是将Hawk生成的配置文件(xml)交给etlpy去执行,初看很酷,但这种思路被证明不靠谱,两种语言,使用不同类库,对同一个任务流,就因为在底层的细微偏差,会导致结果的完全不同。我花了大量的时间在解决兼容性问题上,发现难度不小,两者互相制约牵绊。

最终,我放弃了所谓的兼容性,之后etlpy功能日新月异,甩了Hawk有10条街不止。Hawk的5分钟拖拽,在etlpy上只要一句话:


  1. url=’www.cnblogs.com/p{0}’  
  2. t=task().let(‘p’).range(‘1:20’).format(url).detect()\.let(‘dignum’).split(‘_’)[0].num().write(‘cnblogs.json’) 

介绍etlpy的语法超过了本文的范畴,但它拥有Hawk的一切优点,同时能够分布式并行抓取,任务队列,超级代理,定时更新,与任意函数库集成。执行引擎(etlpy)的全部源代码,也就1000行出头。

也许你都没有听过Lisp这门语言,不过没有关系:Hawk是用C#写的,手敲的代码大概有1万行,用Python大概是1000行左右,用Lisp只要300行就能实现它的全部功能!当然,没有图形界面。由此可见编程语言在表现力上的巨大差别。Hawk本质上是个可视化的Lisp设计器。

我喜欢语言的纯粹和精妙,用简洁的语法就能代表复杂的逻辑。Hawk其实定义了一种爬虫语言,对诸多常用操作进行了模块抽象,在拖拖拽拽中,你构建了一张图(Graph),数据在图上流动,被生成,清洗和消费。最近大热的Tensorflow不也是一样的思路吗? 这张图,既是数据,也是代码。

当然,不论是Hawk和etlpy,你都不能把它们当成厨子,给它指令,就能做出一道菜来。而应当成一套顺手的厨具,而真正做菜的那个人还是你。自动化只是解决了部分问题,而巧妙设计的源泉还是来自于操作者本人。最强大的工具,是自己。

我们用语言表达概念,模式和流程,在此之上构建抽象。我假定每个用Hawk的人都能触类旁通,因此通过一些通用的介绍,他应该就能理解绝大多数的功能。那如果还是不懂呢?那不好意思,请用八爪鱼,否则Hawk的很多设计,对他来说就变得没有意义。我自己从来不愿意把Hawk和etlpy定义为爬虫,它们提供的是一组环境,语言和工具,爬虫只是它的一个不错的应用场景而已。

为什么要开源?

有人肯定会问,为什么不把Hawk商业化,去赚一笔钱呢?

理想状态下,成立公司去完善推广和销售软件,那么应该行得通,否则单枪匹马是不可能的。那我是不是值得为这套软件成立公司呢?应该不会,因为它只是个工具,还不值得我去开一家公司去完善它。

我相信,这也是很多程序员面临的类似困境,想靠卖软件盈利,就像路上的煎饼摊一样简单朴素,问题是放在10年前还有可能(记不记得30元一套的金山词霸?)而服务化盛行的今天,可能很低。到处推广,最终只可能沦为某天我在咖啡厅里的几句谈资,不可能有什么大气候。

有朋友说,为什么你要开源,对自己来说是不是有点像代码外泄?谷歌的TensorFlow都开源了。前面的路还有很远,大家都要忙着赶路呢。保护代码最好的方式就是开源,没开源时有人还想着破解研究,开源了大家fork一下然后就没有然后了,“得不到的才是最好的”。

不得不说,开源才是最贵的。大家看到开源,欢欣雀跃,以为在路上捡到了钱,其实不是的,如果你真想用起来,一定会花更多的时间来学习它,因为开源者没有义务像商业软件那样,提供完整的支持。时间和钱总是矛盾的,既想省钱还想省时间,天下没有这样的好事。

我以前天真地以为,开源的全部就是把源代码公开在网上。之后难道不是理所应当的声望,一帮牛人帮你优化功能修复bug吗?

哈哈,开源怎么可能那么简单。

如果软件写得不错,但没有宣传,那挂在网上完全无人问津,没人知道那是什么鬼;写得足够好,宣传也到位,那也很难有人帮忙贡献开发: 往上看,大神们都忙着造轮子;往下看一大帮实用主义者,抄起轮子就上路,谁顾得上看轮子是不是圆的呢?

开源不意味着坐视不管,依旧需要大量的精力去培养完善它和它的社区环境,通过邮件和论坛方式提供一定的服务。这件事情如果不用心,则一事无成。

如果pandas和ipython不开源,我现在也可能无法进入数据分析的殿堂,没有Linux和众多开源工具,世界也不会发展成这个样子。我明白了为什么开源是一种哲学,它是一种“共赢”。对程序员来说,名誉和成长比卖软件带来的价值更大,那是认可感和成就感。对其他人来说,开源带来了时间的节省和实际的财富。这样做必然是有价值的。

请理性使用爬虫

开发完Hawk的那段时间,我也和很多人一样,看到一个网站就想去试试。以我的熟练程度,20分钟数据就都被下载下来了。然而数据保存在硬盘上,几乎不产生价值。

Google的工程师,可以下载它的全部源代码。可是为什么没有另外一家Google,甚至另外一家百度(又黑了百度)出现呢? 因为更重要的是人才,资源和商业模式,代码在这件事情中最不重要了。拿到源代码都没用,更遑论挂在网上供大众阅读的数据呢?

爬虫是灰色区域,所以大公司从来不公布任何爬虫框架,但内部用的比谁都多。两年以来,网络发生了巨大的变化,ajax化,SEO变成了关键词广告位,大量的网站开始强硬地反爬虫,之前能随便抓取的网站,现在都变得很困难。我相信这里有相当一部分是Hawk的功劳。让人郁闷的是,不少人抓数据仅仅用来玩。

可以想象,一小部分标榜大数据和AI的公司,把Hawk的代码弄下来改改,添一点数据报表功能,就可以盗走别人网站数据,自立门户,去到处忽悠。虽然Hawk开源协议是GPL(使用开源代码的必须开源),但这完全限制不了,毕竟是中国嘛。可能他们不知道,数据,工具和算法根本不值钱,理解,洞见和执行才是最重要的,可是这部分却需要真刀真枪的本事。

你肯定会问,那为什么etlpy后来不更新了?

第一它不稳定,现在释放出来可能砸招牌。其次,如果释放出etlpy,能量和Hawk完全不是一个数量级,用它五分钟写出来三行代码,就能迅速地部署在我司全国各地的千兆公网节点,上万QPS的压力瞬间就能压挂一个中小型网站。它的出现可能会让网站变本加厉地防爬虫。

总之,稍微理性一些,适可而止吧。

为什么不继续优化?

很简单,因为没有时间。爬虫本身没太多技术含量,再深入就进入了异构Web数据集成的领域,大部分人根本用不到。这是个拥有数不清trick和dirty技巧的领域,是与网站设计者的攻防战争,玩到最后,你的能力曲线就像log函数一样,被压制在一个确定的上界。

现在是人工智能和深度学习的天下,以我所在的团队为例,身边的大神们都在努力地优化Tensorflow,改造算法的底层来提升效率,在有趣的数据集上做大规模并行训练。

几年之前,如果我没有去做爬虫和Hawk,没有去设计正则解析器tnpy,而是紧跟潮流去做大规模机器学习的话,眼界和身价可能就完全不一样了呢?

当然,我不后悔去做Hawk,它是实实在在的能让大众用起来东西。或许在万里之外,有个一样戴着眼镜充满激情的和我一样的nerd,看到我的代码开心地拍了桌子,大喊“f**king nice work!”到那个时候,其他事情还重要么?

如果说我后悔没做什么,是我没有把软件做成英文,曾经有一段时间我个人非常崇尚中文编程,从而酿成了现在软件国际化异常困难的后果;再者,没有直接开发Python或者js这种能跨平台语言的版本,Hawk只能局限于Windows桌面应用,而不同的社群就风气又不一样了。

它的设计有不少问题,不过更多来自于多种因素的妥协。它注定是不完美的。因为职业生涯的关系,我无法像前几年那样,花大把的时间去优化它。既然开源了,我希望有人能把它做得更好。

其实我还是个程序员

我之前从来没想过自己会成为一名程序员。

高中时候理科不错,语文巨差。高考完,老妈扯着嗓子问我,报哪所学校什么专业吧? 正在打游戏的我根本无暇顾及,不耐烦地说,随便你们吧! 糊里糊涂地进了通信工程,几年后通信稍显疲软,就自学计算机,然后一点都不偶然地成了一名程序员。

网上黑程序员的段子太多了。我都一笑而过。但最近几年我坚决不买任何尺寸和颜色的格子衫。如果看到我穿,好吧,那一定是我本科时候买的。

你知道那帮每天不苟言笑,整天盯着显示屏的怪人每天在想什么吗?

敲完这些文字的时候,2017年的九点半我还在杭州的酒店里睡眼惺忪,谁让昨天夜里11点才回来的呢?让我开心的,是Hawk的star接近800,有点担忧的,是公司的新产品马上要上线,会不会出什么状况呢?

本文作者:五年之痒

来源:51CTO

时间: 2024-08-02 18:46:58

设计爬虫Hawk背后的故事的相关文章

SQL Server 2012研发团队背后的故事

本文讲的是SQL Server 2012研发团队背后的故事,在切入正题之前,就让浸泡在数据海洋里的我们,看几个并不陌生的场景吧. 场景一:痛苦的升级 三十六岁的吴桐坡是一个电商网站的首席技术官,最近有点头疼:业务旺季就在眼前,现在的内存.盘阵.操作系统和应用平台已经有点扛不住.老板却已发话,今年要基于用户消费行为的统计与分析,上线更多的新品类.唉,又要和部门里的兄弟们熬夜了.好在之前做了不少准备工作,对这次升级的成本和问题心里大概有底."但过去几年,哪次硬件变更和软件升级没出过岔子?我怎么敢跟老

LLVM和Clang背后的故事

LLVM是Apple官方支持的编译器,而该编译器的前端是Clang,这两个工具都被集成到了Xcode里面.在这篇文章中,我们来了解一下LLVM和Clang背后的故事. 在很长一段时间里,Apple一直使用GCC作为官方的编译器.GCC作为开源世界的编译器标准一直做得不错,但Apple对编译工具提出了更高的要求. 仗着自己在开源社区的地位,GCC 开发者对Apple的Objective-C语言新增的很多特性不予理睬,甚至当Apple想做的很多功能需要用模块化的方式来调用 GCC时,GCC却一直不给

阿里巴巴开源Java编码规范背后的故事

(作者:无独 | 校对:孤尽) <阿里巴巴Java开发手册>(下称<手册>)凝聚了阿里集团很多同学的知识智慧和经验,这些经验甚至是用血淋淋的故障换来的,希望前车之鉴,后车之师,能够帮助更多的开发者少踩坑,杜绝踩重复的坑.  手册下载:https://yq.aliyun.com/articles/69327 此手册从构思到现在的最新版本,历时一年半,历经无数次内部针锋相对的讨论,迭代105次.可以说手册中每一个条目的背后,都有一个很长.很精彩的故事.为了让广大开发者更加深入地了解到项

十三种编程语言和它们名称背后的故事

如果玫瑰不叫玫瑰,芳香是否如故? 程序员们普遍认为,软件开发工作当中难度最高的一项任务就是为成果命名.尽管这种情况并不多见,但命名过程中尤其令人头大的就是面对着一种新型编程语言. 在一种新型语言的设计工作宣告结束后,随之而来的命名过程往往遵循以下几个步骤:以语言本身的特性或者描述为名,采取首字母或者缩写形式(例如BASIC.COBOL.TCL以及LISP);从现有语言当中派生而来的新名称(例如C++.C#以及CoffeeScript);又或者直接取自某位对数学或者计算科学作出卓越贡献的伟人(例如

脸萌爆红和安静,在这背后的故事

简直可以说是忽如一夜春风来,满屏都刷萌系图.于是,是不是你也在脑海中,正在构思着自己的样子,然后跟风换上了卡通头像.于是一时间,就感觉到自己,萌萌哒. 而对于很多90后而言,也许这样的场景或许并不陌生.因为正是在他们的使用和分享下,脸萌在短时间内迅速就充斥在微博和朋友圈之中,然后火速占据了APP Store榜首位置,搜索指数也是从一路平川狂奔到巅峰. 在经历过爆红后,现在的脸萌目前已经安静下来.而社交平台上,似乎再难见到刷屏的画面,在媒体上也很少看见踪影.也许很多人说,她的生命周期其实也不过几天

脸萌App和安静背后不为人知的故事

忽如一夜春风来,满屏皆是萌系图.于是,你也在脑海中,构思着自己的样子,跟风换上了卡通头像.一时间,感觉到自己萌萌哒. 对于很多90后而言,这样的场景或许并不陌生.正是在他们的使用和分享下,脸萌在短时间内充斥着微博和朋友圈,占据了APP Store榜首位置,搜索指数也从一路平川突升至巅峰. 在经历爆红过后,现在的脸萌已经安静了下来.社交平台上再难见到刷屏的画面,媒体上也少见了踪影.很多人说,她的生命周期也不过几天到数月,又是个现象级应用,俗称"月抛"产品. 脸萌现在怎么样了?未来该走向哪

简约有个性,ColorOS系统设计团队背后的故事

说到手机操作系统UI设计,比较经典是主打简约风格的苹果IOS,突出信息本身的微软WP8系统,另外谷歌的Android L新的Material Design设计语言也简化了设计元素变得更简约更直观.那么,哪一种设计才是好的,并没有统一的答案.因为每一种设计风格都各有所长,大众的审美也因人而异,但整体都趋向更简约更美观的路线. ColorOS从诞生到目前的2.0版本,界面设计一直有自己的个性风格,精致唯美的UI界面,人性化的交互效果,用更直观简约的视觉效果加上鲜明的个性获得了用户的喜爱. 究竟Col

手机游戏《水果忍者》背后的故事

几年前,当 Halfbrick Studios 的 CEO Shainiel Deo 把 Fruit Ninja (水果忍者)的第一版作品拿到他的妻子身边的时候,他惊讶地发现自己那平时异常"憎恨"电子游戏的妻子居然对这款 Slice-em-up 形式的休闲小游戏爱不释手. "我专注于观察她的脸庞.当我看到她的注意力前所未有地集中在屏幕上,脸上尽是较真的神情的时候,我就知道,这款游戏有戏了." 上周六,Shainiel Deo 受国内一些合作伙伴的邀请首次来华,参加了

黑客精神祭 挖掘神秘黑客背后的故事

无论媒体如何渴望挖掘黑客背后的故事.黑客始终是一群神秘的存在.于是乎,笔者的这篇黑客精神祭的直接叙述对象也就指向了更为人们所知的"病毒". 病毒诞生之初--严谨之美 当你看着爱机被病毒蹂躏的时候,或许你根本无从感觉病毒之美.但是,如果你愿意纯粹以技术角度评判病毒的话,或许你能在病毒诞生之初,发现它的美.那是一种精密逻辑思维构筑下的严谨之美. 1986年,大脑病毒面世.它是世界上第一个DOS病毒,同时也开创了引导区病毒的先河.它用汇编语言写成,代码精简,有很高的编程技术.大脑病毒是用极其