python分布式
① python如何搭建分布式爬虫呀
爬虫本质上不需要分布式。因为你要爬一个网站通常5-10个线程足够了,再多就是对网站压力测试了。
你只需要将任务分配到不同的机器上,然后各运行各自己的,结果合并一下就可以。 这个与nutch人map, rese也没有什么差别。只是手工分,手工合并。当然也可以用脚本分,脚本合并,脚本远程启动。有一个远程控制模块,似乎叫rpy。很简单,很容易上手。可以远程控制一个模块。
数据库用postgresql不是很好。因为爬行结果放在关系型数据库里太吃力。特别是网页内容。通常是URL放在redis里。 内容放在文件系统里,你可以用hadoop+hdfs+thrift方案放在hadoop里。
如果使用了hadoop,就干脆模仿nutch的流程,把python脚本也交给hadoop去管理好了。
至于控制与通信这个都让hadoop来处理好了。
当然我个人觉着rpy方式更简单。 里面控制与通信都是现成的。10分钟就学会了。
还是回到原来的说法,大部分情况下,单机多线程跑爬虫足够用了。 不需要分布式。而且效率甚至比分布式更高。
② 如何用 python 构建一个简单的分布式系统
从GitHub中整理出的15个最受欢迎的Python开源框架。这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等。
Django: Python Web应用开发框架
Django 应该是最出名的Python框架,GAE甚至Erlang都有框架受它影响。Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。
Diesel:基于Greenlet的事件I/O框架
Diesel提供一个整洁的API来编写网络客户端和服务器。支持TCP和UDP。
Flask:一个用Python编写的轻量级Web应用框架
Flask是一个使用Python编写的轻量级Web应用框架。基于Werkzeug WSGI工具箱和Jinja2
模板引擎。Flask也被称为“microframework”,因为它使用简单的核心,用extension增加其他功能。Flask没有默认使用的数
据库、窗体验证工具。
Cubes:轻量级Python OLAP框架
Cubes是一个轻量级Python框架,包含OLAP、多维数据分析和浏览聚合数据(aggregated data)等工具。
Kartograph.py:创造矢量地图的轻量级Python框架
Kartograph是一个Python库,用来为ESRI生成SVG地图。Kartograph.py目前仍处于beta阶段,你可以在virtualenv环境下来测试。
Pulsar:Python的事件驱动并发框架
Pulsar是一个事件驱动的并发框架,有了pulsar,你可以写出在不同进程或线程中运行一个或多个活动的异步服务器。
Web2py:全栈式Web框架
Web2py是一个为Python语言提供的全功能Web应用框架,旨在敏捷快速的开发Web应用,具有快速、安全以及可移植的数据库驱动的应用,兼容Google App Engine。
Falcon:构建云API和网络应用后端的高性能Python框架
Falcon是一个构建云API的高性能Python框架,它鼓励使用REST架构风格,尽可能以最少的力气做最多的事情。
Dpark:Python版的Spark
DPark是Spark的Python克隆,是一个Python实现的分布式计算框架,可以非常方便地实现大规模数据处理和迭代计算。DPark由豆瓣实现,目前豆瓣内部的绝大多数数据分析都使用DPark完成,正日趋完善。
Buildbot:基于Python的持续集成测试框架
Buildbot是一个开源框架,可以自动化软件构建、测试和发布等过程。每当代码有改变,服务器要求不同平台上的客户端立即进行代码构建和测试,收集并报告不同平台的构建和测试结果。
Zerorpc:基于ZeroMQ的高性能分布式RPC框架
Zerorpc是一个基于ZeroMQ和MessagePack开发的远程过程调用协议(RPC)实现。和 Zerorpc 一起使用的 Service API 被称为 zeroservice。Zerorpc 可以通过编程或命令行方式调用。
Bottle: 微型Python Web框架
Bottle是一个简单高效的遵循WSGI的微型python Web框架。说微型,是因为它只有一个文件,除Python标准库外,它不依赖于任何第三方模块。
Tornado:异步非阻塞IO的Python Web框架
Tornado的全称是Torado Web Server,从名字上看就可知道它可以用作Web服务器,但同时它也是一个Python Web的开发框架。最初是在FriendFeed公司的网站上使用,FaceBook收购了之后便开源了出来。
webpy: 轻量级的Python Web框架
webpy的设计理念力求精简(Keep it simple and powerful),源码很简短,只提供一个框架所必须的东西,不依赖大量的第三方模块,它没有URL路由、没有模板也没有数据库的访问。
Scrapy:Python的爬虫框架
Scrapy是一个使用Python编写的,轻量级的,简单轻巧,并且使用起来非常的方便。
③ python 分布式进程用的多吗
Python提供了非常好用的多进程包multiprocessing,你只需要定义一个函数,Python会替你完成其他所有事情。
借助这个包,可以轻松完成从单进程到并发执行的转换。
1、新建单一进程
如果我们新建少量进程,可以如下:
import multiprocessing
import time
def func(msg):
for i in xrange(3):
print msg
time.sleep(1)
if __name__ == "__main__":
p = multiprocessing.Process(target=func, args=("hello", ))
p.start()
p.join()
print "Sub-process done."12345678910111213
2、使用进程池
是的,你没有看错,不是线程池。它可以让你跑满多核CPU,而且使用方法非常简单。
注意要用apply_async,如果落下async,就变成阻塞版本了。
processes=4是最多并发进程数量。
import multiprocessing
import time
def func(msg):
for i in xrange(3):
print msg
time.sleep(1)
if __name__ == "__main__":
pool = multiprocessing.Pool(processes=4)
for i in xrange(10):
msg = "hello %d" %(i)
pool.apply_async(func, (msg, ))
pool.close()
pool.join()
print "Sub-process(es) done."12345678910111213141516
3、使用Pool,并需要关注结果
更多的时候,我们不仅需要多进程执行,还需要关注每个进程的执行结果,如下:
import multiprocessing
import time
def func(msg):
for i in xrange(3):
print msg
time.sleep(1)
return "done " + msg
if __name__ == "__main__":
pool = multiprocessing.Pool(processes=4)
result = []
for i in xrange(10):
msg = "hello %d" %(i)
result.append(pool.apply_async(func, (msg, )))
pool.close()
pool.join()
for res in result:
print res.get()
print "Sub-process(es) done."
2014.12.25更新
根据网友评论中的反馈,在Windows下运行有可能崩溃(开启了一大堆新窗口、进程),可以通过如下调用来解决:
multiprocessing.freeze_support()1
附录(自己的脚本):
#!/usr/bin/python
import threading
import subprocess
import datetime
import multiprocessing
def dd_test(round, th):
test_file_arg = 'of=/zbkc/test_mds_crash/1m_%s_%s_{}' %(round, th)
command = "seq 100 | xargs -i dd if=/dev/zero %s bs=1M count=1" %test_file_arg
print command
subprocess.call(command,shell=True,stdout=open('/dev/null','w'),stderr=subprocess.STDOUT)
def mds_stat(round):
p = subprocess.Popen("zbkc mds stat", shell = True, stdout = subprocess.PIPE)
out = p.stdout.readlines()
if out[0].find('active') != -1:
command = "echo '0205pm %s round mds status OK, %s' >> /round_record" %(round, datetime.datetime.now())
command_2 = "time (ls /zbkc/test_mds_crash/) 2>>/round_record"
command_3 = "ls /zbkc/test_mds_crash | wc -l >> /round_record"
subprocess.call(command,shell=True)
subprocess.call(command_2,shell=True)
subprocess.call(command_3,shell=True)
return 1
else:
command = "echo '0205 %s round mds status abnormal, %s, %s' >> /round_record" %(round, out[0], datetime.datetime.now())
subprocess.call(command,shell=True)
return 0
#threads = []
for round in range(1, 1600):
pool = multiprocessing.Pool(processes = 10) #使用进程池
for th in range(10):
# th_name = "thread-" + str(th)
# threads.append(th_name) #添加线程到线程列表
# threading.Thread(target = dd_test, args = (round, th), name = th_name).start() #创建多线程任务
pool.apply_async(dd_test, (round, th))
pool.close()
pool.join()
#等待线程完成
# for t in threads:
# t.join()
if mds_stat(round) == 0:
subprocess.call("zbkc -s",shell=True)
break
④ python分布式爬虫是什么意思
一、分布式爬虫架构
在了解分布式爬虫架构之前,首先回顾一下Scrapy的架构,如下图所示。
我们需要做的就是在多台主机上同时运行爬虫任务协同爬取,而协同爬取的前提就是共享爬取队列。这样各台主机就不需要各自维护爬取队列,而是从共享爬取队列存取Request。但是各台主机还是有各自的Scheler和Downloader,所以调度和下载功能分别完成。如果不考虑队列存取性能消耗,爬取效率还是会成倍提高。
二、维护爬取队列
那么这个队列用什么来维护?首先需要考虑的就是性能问题。我们自然想到的是基于内存存储的Redis,它支持多种数据结构,例如列表(List)、集合(Set)、有序集合(Sorted Set)等,存取的操作也非常简单。
Redis支持的这几种数据结构存储各有优点。
列表有lpush()、lpop()、rpush()、rpop()方法,我们可以用它来实现先进先出式爬取队列,也可以实现先进后出栈式爬取队列。
集合的元素是无序的且不重复的,这样我们可以非常方便地实现随机排序且不重复的爬取队列。
有序集合带有分数表示,而Scrapy的Request也有优先级的控制,我们可以用它来实现带优先级调度的队列。
我们需要根据具体爬虫的需求来灵活选择不同的队列。
三、如何去重
Scrapy有自动去重,它的去重使用了Python中的集合。这个集合记录了Scrapy中每个Request的指纹,这个指纹实际上就是Request的散列值。我们可以看看Scrapy的源代码,如下所示:
importhashlib
defrequest_fingerprint(request, include_headers=None):
ifinclude_headers:
include_headers = tuple(to_bytes(h.lower())
forhinsorted(include_headers))
cache = _fingerprint_cache.setdefault(request, {})
ifinclude_headersnotincache:
fp = hashlib.sha1()
fp.update(to_bytes(request.method))
fp.update(to_bytes(canonicalize_url(request.url)))
fp.update(request.bodyorb'')
ifinclude_headers:
forhdrininclude_headers:
ifhdrinrequest.headers:
fp.update(hdr)
forvinrequest.headers.getlist(hdr):
fp.update(v)
cache[include_headers] = fp.hexdigest()
returncache[include_headers]
request_fingerprint()就是计算Request指纹的方法,其方法内部使用的是hashlib的sha1()方法。计算的字段包括Request的Method、URL、Body、Headers这几部分内容,这里只要有一点不同,那么计算的结果就不同。计算得到的结果是加密后的字符串,也就是指纹。每个Request都有独有的指纹,指纹就是一个字符串,判定字符串是否重复比判定Request对象是否重复容易得多,所以指纹可以作为判定Request是否重复的依据。
那么我们如何判定重复呢?Scrapy是这样实现的,如下所示:
def__init__(self):
self.fingerprints = set()
defrequest_seen(self, request):
fp = self.request_fingerprint(request)
iffpinself.fingerprints:
returnTrue
self.fingerprints.add(fp)
在去重的类RFPDupeFilter中,有一个request_seen()方法,这个方法有一个参数request,它的作用就是检测该Request对象是否重复。这个方法调用request_fingerprint()获取该Request的指纹,检测这个指纹是否存在于fingerprints变量中,而fingerprints是一个集合,集合的元素都是不重复的。如果指纹存在,那么就返回True,说明该Request是重复的,否则这个指纹加入到集合中。如果下次还有相同的Request传递过来,指纹也是相同的,那么这时指纹就已经存在于集合中,Request对象就会直接判定为重复。这样去重的目的就实现了。
Scrapy的去重过程就是,利用集合元素的不重复特性来实现Request的去重。
对于分布式爬虫来说,我们肯定不能再用每个爬虫各自的集合来去重了。因为这样还是每个主机单独维护自己的集合,不能做到共享。多台主机如果生成了相同的Request,只能各自去重,各个主机之间就无法做到去重了。
那么要实现去重,这个指纹集合也需要是共享的,Redis正好有集合的存储数据结构,我们可以利用Redis的集合作为指纹集合,那么这样去重集合也是利用Redis共享的。每台主机新生成Request之后,把该Request的指纹与集合比对,如果指纹已经存在,说明该Request是重复的,否则将Request的指纹加入到这个集合中即可。利用同样的原理不同的存储结构我们也实现了分布式Reqeust的去重。
四、防止中断
在Scrapy中,爬虫运行时的Request队列放在内存中。爬虫运行中断后,这个队列的空间就被释放,此队列就被销毁了。所以一旦爬虫运行中断,爬虫再次运行就相当于全新的爬取过程。
要做到中断后继续爬取,我们可以将队列中的Request保存起来,下次爬取直接读取保存数据即可获取上次爬取的队列。我们在Scrapy中指定一个爬取队列的存储路径即可,这个路径使用JOB_DIR变量来标识,我们可以用如下命令来实现:
scrapy crawl spider -s JOB_DIR=crawls/spider
更加详细的使用方法可以参见官方文档,链接为:https://doc.scrapy.org/en/latest/topics/jobs.html。
在Scrapy中,我们实际是把爬取队列保存到本地,第二次爬取直接读取并恢复队列即可。那么在分布式架构中我们还用担心这个问题吗?不需要。因为爬取队列本身就是用数据库保存的,如果爬虫中断了,数据库中的Request依然是存在的,下次启动就会接着上次中断的地方继续爬取。
所以,当Redis的队列为空时,爬虫会重新爬取;当Redis的队列不为空时,爬虫便会接着上次中断之处继续爬取。
五、架构实现
我们接下来就需要在程序中实现这个架构了。首先实现一个共享的爬取队列,还要实现去重的功能。另外,重写一个Scheer的实现,使之可以从共享的爬取队列存取Request。
幸运的是,已经有人实现了这些逻辑和架构,并发布成叫Scrapy-Redis的Python包。接下来,我们看看Scrapy-Redis的源码实现,以及它的详细工作原理
⑤ 哪些分布式文件系统是由Python编写的呢
我知道分布式文件系统完全用Python 写的只有openstack 的swift。
其他还有一些不知名的分布式文件系统用python 写的如:
NCFS(基于多个云存储的分布式文件系统)
一般考虑性能都不会采用python 作为分布式文件系统的开发语言
⑥ 一般Python的分布式计算用什么框架
(1) 用什么语言都不能证明逼格,包括汇编,也包括lisp/haskell。
(2) 在适当的场合用适当的工具,解除耦合、减少重复、易于扩展才是对逼格的更高挑战。
比如有一组件对数据库有大量操作,我同事认为他要用C++模板元编程加上一些巧妙的设计模式来生成sql是逼格高的体现,我认为在这样的场景下至少要用上orm才能谈得上对逼格有要求。
⑦ grpc使用python时,想做分布式部署,实现负载平衡,求详细方案
⑧ 如何设计一个python分布式爬虫系统
你都没想明白为什么要分布式
========================
我还是认真答一下吧,爬虫这种东西在大批量抓去时主要有下面几个量变引发质变的挑战:
1. 出口IP数量,主要是考虑防止被封禁,带宽反而不是大问题,这个问题可以通过搭建NAT出口集群,或者单机多IP的方式实现
2. 本地端口号耗尽,由于爬虫是服务端编程不太常见的主动发起连接的应用,在普通只有一个IP绑定的机器上会受到65535的限制(一般在50000多就会受到限制)
3. 大容量存储的需求,一般都是通过开源或者自己研发的分布式存储系统来实现,像谷歌(GFS)和网络(百灵)都是自研,这里就不展开说了
4. 动态网页的支持,像京东这种网站,内容都是通过类似Facebook的bigpipe一样动态加载的,直接像curl这样抓取看到的页面几乎是空白的,这就要求爬虫能模拟JS的运行,这方面有很多基于v8引擎的开源项目:
CasperJS, a navigation scripting and testing utility for PhantomJS and SlimerJS
PhantomJS | PhantomJS
由于这个需求,爬虫成了CPU密集型的应用了,分布式的需求也就有了
单机爬虫的主要难点在的异步非阻塞网络编程,老生常谈了。先暂时写这么多吧
⑨ 如何用Python写一个分布式爬虫
学习 基本的爬虫工作原理 基本的http抓取工具,scrapy Bloom Filter: Bloom Filters by Example 如果需要大规模网页抓取,你需要学习分布式爬虫的概念。其实没那么玄乎,你只要学会怎样维护一个所有集群机器能够有效分享的分布式队列就好