Cola:一个分布式爬虫框架

Star

由于早先写的WeiboCrawler问题很多,而且当时我有提到,其实可以实现一个通用的爬虫框架。最近由于要抓取新的数据,于是我就写了这个cola。下面的文字来自wiki

Cola是一个分布式的爬虫框架,用户只需编写几个特定的函数,而无需关注分布式运行的细节。任务会自动分配到多台机器上,整个过程对用户是透明的。

依赖

由于Cola配置文件使用的yaml,所以Cola只依赖于pyyaml,安装easy_install或者pip工具后,则可以:

pip install pyyaml

安装

下载或者用git clone源码,假设在目录/to/pth/cola,将该路径添加到Python path中。

一种简单的方法是在site-packages中添加pth文件。site-packages因系统而异,如果是windows,假设python装在C:\python27,那么就是C:\python27\Lib\site-packages;如果是linux,那么应该是/usr/local/lib/pythonX.X/dist-packages。

在site-packages下新建一个cola.pth文件,里面写上路径:/to/path/cola。

运行

Cola集群需要一个master和若干个worker,对于每台机器,只能启动一个worker。但是,集群不是必须的,在单机模式下亦可以运行。

Cola目前自带了两个爬虫,分别是维基百科和新浪微博。在项目根目录下的contrib中。

下面就wiki为例,分别说明如何在单机和分布式环境下运行。

依赖

无论是维基百科还是新浪微博的实现,数据都存放在MongoDB中,所以要确保MongoDB的安装。

在wiki下的wiki.yaml和sina下的sina.yaml中可以配置MongoDB的主机和端口。

维基百科和新浪微博实现依赖于下面的几个包:

  • mechanize
  • python-dateutil
  • BeautifulSoup4
  • mongoengine
  • rsa(仅新浪微博需要)

可以使用pip或者easy_install来安装。

单机模式

单机模式非常简单,只需运行contrib/wiki/__init__.py即可。

cd /to/path/cola/contrib/wiki
python __init__.py

要运行新浪微博的爬虫,需要在sina.yaml中配置登录的用户名和密码。这里要注意,要保证这个用户名和密码在登录时不需要验证码。

分布式模式

首先需要启动cola master和cola workers。分别运行根目录下bin中的start_master.py和start_worker.py

启动cola master:

cd /to/path/cola 
python bin/start_master.py --data /my/path/data

如果不指定--data,那么数据文件会防止在项目根目录下的data文件夹中。

启动cola worker:

python bin/start_worker.py --master  --data /my/path/data

--data选项同master。如果不指定master,会询问是否连接到本机master,输入yes连接。

最后使用bin下的coca.py来运行指定的Cola job:

python bin/coca.py -m  -runLocalJob /to/path/cola/contrib/wiki

-runLocalJob选项是要运行的job所在文件夹的绝对路径。输入命令后,该job会被提交到Cola集群来运行。

停止Cola Job或集群

停止整个集群,则可以运行:

python bin/coca.py -stopAll

而停止一个Job,则需要查询得到Job的名称:

python bin/coca.py -showRunningJobsNames

得到名称后,再运行:

python bin/coca.py -stopRunningJobByName [job name]

编写自定义Cola Job

见wiki编写自定义Cola Job

问题

Cola还不够稳定,目前会处于持续改进的状态。且Cola还没有在较大规模的集群上测试,但是接下来我会把Cola应用到新项目中,并逐步完善。也希望大家也能给我反馈,并帮助改进。

Todo

  • 实现一个web接口,可以查看运行的cola job以及运行情况
  • 实现一个opener能够运行JS代码和执行AJAX请求。
  • 支持增量抓取机制。
  • 简化安装,支持easy_install或者pip安装。增加解决依赖库安装的机制。

Neo4j简介

现实中很多数据都是用图来表达的,比如社交网络中人与人的关系、地图数据、或是基因信息等等。RDBMS并不适合表达这类数据,而且由于海量数据的存在,让其显得捉襟见肘。NoSQL数据库的兴起,很好地解决了海量数据的存放问题,图数据库也是NoSQL的一个分支,相比于NoSQL中的其他分支,它很适合用来原生表达图结构的数据。

下面一张图说明,相比于其他NoSQL,图数据库存放的数据规模有所下降,但是更能够表达复杂的数据。

通常来说,一个图数据库存储的结构就如同数据结构中的图,由顶点和边组成。

Neo4j是图数据库中一个主要代表,其开源,且用Java实现。经过几年的发展,已经可以用于生产环境。其有两种运行方式,一种是服务的方式,对外提供REST接口;另外一种是嵌入式模式,数据以文件的形式存放在本地,可以直接对本地文件进行操作。

Neo4j分三个版本:社区版(community)、高级版(advanced)和企业版(enterprise)。社区版是基础,本文主要对其作出介绍,它使用的是GPLv3协议,这意味着修改和使用其代码都需要开源,但是这是建立在软件分发的基础上,如果使用Neo4j作为服务提供,而不分发软件,则不需要开源。这实际上是GPL协议本身的缺陷。高级版和企业版建立在社区版的基础上,但多出一些高级特性。高级版包括一些高级监控特性,而企业版则包括在线备份、高可用集群以及高级监控特性。要注意它们使用了AGPLv3协议,也就是说,除非获得商业授权,否则无论以何种方式修改或者使用Neo4j,都需要开源。

接下来就从Neo4j的几个主要特性出发,结合代码逐一作出介绍。它们包括:数据模型、索引、事务、遍历和查询、以及图算法。

用tornado搭建日志服务器

对于一个分布式应用,一个计算节点上可能产生一些日志,而为了便于将这些节点日志收集并分析,我们可以选择除了在本地生成日志外,还将某些级别的日志发送到日志服务器。

Python的logging模块可以用来对日志进行一些操作,其接口和著名的Java日志库log4j类似。logging.handlers支持一系列的日志处理方式,其中发送到日志服务器可以通过SocketHandler或者HttpHandler,不过本文既然选择了tornado,还是使用HttpHandler的方式。

首先,是分布式节点的部分。首先,我们通过get_logger方法得到logger对象,并向其添加HttpHandler。

import logging

logging_host = '127.0.0.1'
logging_port = 8888
logging_add_url = '/log/add/'

def get_logger():
    logger = logging.getLogger()
    
    http_handler = logging.handlers.HTTPHandler(
        '%s:%s' % (logging_host, logging_port),
        logging_add_url,
        method='POST'
    )
    http_handler.setLevel(logging.ERROR)
    logger.addHandler(http_handler)
    
    return logger

代码还是很简单的,HTTPHandler接受三个参数,一个是服务器的host,日志发送到的url,以及是GET还是POST方式。这里,省去了添加本地日志的过程。

一个简单的分布式新浪微博爬虫

Update 2013/6/17:WeiboCrawler之前已经说过不再维护了,现在请大家关注我的新项目——cola。Cola是一个分布式的爬虫框架,支持包括新浪微博(网页版)的抓取。而且目前实验下来,长时间抓取也不会被封锁。项目地址:https://github.com/chineking/cola

由于实验室实验需要,我写了个简单的新浪微博爬虫,来从新浪微博上获取一些实验所需要的数据。现在实验数据抓取部分已经比较稳定,所以我把这些代码放出来,说不定会对一些同学有帮助吧。

至于为什么不用新浪微博API,以及整个分布式爬虫的架构、安装和部署、以及缺陷等等都已经在wiki中进行了解释。

以后,这个程序应该不会再去维护和更新了,但是,我觉得这个程序稍作修改,还是可以适用于其他的特定目标的爬虫的,所以如果有同学需要修改这个项目,可以fork代码,或者联系我成为项目的contributor。

项目地址在BitBucket上——https://bitbucket.org/chineking/weibocrawler

Update(2013/1/21):最新的weibo.cn抓取不了数据了,改动已经提交,请大家pull最新代码。

说说成绩

博客因为备案的事情被断了一个礼拜多的时间,今天终于得以恢复。但,今天要说的重点显然不是这个。

我不是一个爱牢骚的人,可是有那么些话,憋了太久太久,忍不住要说出。研究生读了已经有一年半的时间,在第一年的时间里,绝大多数的时间用来上课。在交大,有两种课程,一种是学位课,这种课是必须要修够一定学分,并且成绩纳入绩点的计算;另一种就是非学位课,只要修够学分即可。

重点是,有太多的学位课,索然无味,我丝毫没有兴趣。一直以来我就是以兴趣为导向的,对这种课,我不是不够认真,只是我不愿意在上面花更多时间。相反,我对一些非学位课很感兴趣,而这些课,往往会有一些实践性很强的项目。问题就在这里,因为非学位课根本就不会被纳入绩点,纵然分数再高,“看起来”也毫无用处,只要过就行了,所以,有很多人就根本就不在意这些课程,他们觉得花太多时间也是枉然。而我不一样,我觉得只要是我感兴趣,就会竭力去把它做到最好。

最让我不满的就是算法这门课,照理说,对于计算机的学生,算法是极其重要的一门课。但是这门课,讲的问题大部分不是基本的算法问题,而是一些NP问题等等,我不认为他们没有用,只是觉得这些内容被用上的概率太低了。甚至,在这门课从头至尾,都没有要求写过一行代码。最后的考试,不知道是不是我对往年题型的掌握不够还是什么原因,考得特别差,我也因此找过老师,除了一题没讲过的我做得很不错外,其他的都很糟糕。我想,这可能是我的错,我复习的方式不对。但是,从内心里说,我觉得这门课真的没学到什么东西。

相反的是,非学位课有几门我很感兴趣。首先是我的导师讲的《海量数据分析》,课程有四个基于Hadoop的实验,第一个实验行索引(Line Indexer)比较简单;第二个实验反向倒排索引(Inverted Index),我在其中实现了简单的中文分词,并除了支持倒排索引,还支持搜索和结果的高亮;第三个PageRank,我在极大数据量的wiki语料上算出了结果;第四个实验Kmeans,也是独立完成。这些项目从源码到wiki,都托管了出来:分别在地址InvertedIndexPageRankKmeans。甚至在InvertedIndex实验的过程中,我发现操作HDFS中的文件比较麻烦,所以特地写了个在线的操作HDFS文件的web服务器,在InvertedIndex项目下py_server中。后来我想把它单独分出来做一个独立项目:HadoopWebManager,可惜后来写一半就各种原因没能写下去。

另外一门是《分布式计算》的课程写一个云备份的工具,支持文件备份到多种云里,我完成主要设计,并实现了支持S3、微盘和Google Cloud Storage API。项目在GitHub上

最后我的非学位课都是A,A+和A-的成绩。可是,这有什么用呢?我常常告诉自己,我问心无愧。可是,当看到最后的成绩时,我还是觉得低落到难过。记得有一次和涛军聊天,我说我的成绩发挥很不好,他毫不犹豫地说:成绩有什么用啊。可是,成绩意味着奖学金,更少的学费,还有相信还是有企业会看成绩的。我觉得成绩是过眼云烟,别人可能觉得如果我最后成绩优秀了,就不会这么说了。或许吧。

把这些都说了,会感觉到好很多。我一直觉得做人的标准就是光明磊落,我做到了所以我不遗憾。只是不吐不快。

夕阳照常从西边落下,只是,残照里,断弦有谁听?

关于作者

残阳似血(@秦续业),程序猿一枚,把梦想揣进口袋的挨踢工作者。现加入阿里云,研究僧毕业于上海交通大学软件学院ADC实验室。熟悉分布式数据分析(DataFrame并行化框架)、基于图模型的分布式数据库和并行计算、Dpark/Spark以及Python web开发(Django、tornado)等。

博客分类

点击排行

标签云

扫描访问

主题

残阳似血的微博