欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python用gevent实现异步

程序员文章站 2024-01-28 11:34:46
...

实际工作中,往往会使用碰到文件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,会在异步调用完成后继续执行处理方法