python用gevent实现异步

实际工作中,往往会使用碰到文件io或者网络io。
批处理大量文件或者做爬虫,如果使用同步的方式,大量时间都会消耗在io的等待上,尤其是网络IO,包括建立socket,下载,这个很大程度上取决于网络环境,比如我们去网上爬取一些图片做一些图像处理的训练啊等等。爬取后执行的动作耗时其实很短,90%的时间都耗在网络IO上了,我们就要考虑异步了。
比如我们爬取人人网,微博等平台的资料,因为大家的首页都是固定的url+id,
比如微博
https://weibo.com/u/1669879400?is_hot=1这个是迪丽热巴的微博首页
https://weibo.com/u/1669879410?is_hot=1这是某未知用户的微博首页
首页有粉丝和关注数,比如我要获取大量样本的粉丝和关注数,我可以遍历id去拿数据。当然微博这种平台肯定做了反爬取的,下面的代码也没带session,是访问不通的。这里只是做个例子,大家千万不要尝试,要查水表的。
最简单的异步就是使用gevent, 这里的monkey是用来改变标准socket库的。当一个库需要修改Python本身 的基础行为的时候,monkey就派上用场了。gevent能够 修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协程。但使用使用要注意多进程和gevent并用时,dns解析有一定限制,详见解决多进程+gevent的dns问题

import gevent import monkey
monkey.patch_socket
from gevent.coros import Semaphore
import urlib2

def generate_url(tmpl, ids):
    for i in xrange(ids):
        yield tmpl.format(id=i*10 + 1669879400)

def chunk_requests(urls, size=100):
    semaphore = Semaphore(size)
    requests = [gevent.spawn(download, url, semaphore) for url in urls]
    for responese in gevent.iwait(requests):
        yield response

def download(url, semaphore):
    with semaphore:
        data = urllib2.urlopen(url)
        return data.read()

delay = 100
num_iter = 500
url_tmpl = 'https://weibo.com/u/{id}?is_hot=1'
urls = generate_urls(url_tmpl, num_iter)
response_futures = check_request(urls, 100)
# 写方法处理response_futures,会在异步调用完成后继续执行处理方法

猜你喜欢

转载自blog.csdn.net/weixin_41571449/article/details/80156066