Trip: 給Requests加上協程,一百份網絡請求一份時間

Trip 是一個協程的網絡庫,如 Requests 一般簡單的操作,程序不再被網絡阻塞。

項目主頁見這里:github

兼容 Python 2.7+ 的所有版本,主流三大操作系統。

基于兩大依賴包:TRIP: Tornado & Requests In Pair

感謝Tornado與Requests讓想法可以快速變成現實,坦誠的說,這個項目我只做了一些簡單的工作。

讓協程變的簡單

這是一個讓協程變的簡單的項目,你只需要這樣:

import trip

@trip.coroutine
def main():
    r = yield trip.get('https://httpbin.org/get', auth=('user', 'pass'))
    print(r.content)

trip.run(main)

一百份請求一份時間

基于 Tornado 的協程讓網絡阻塞不再成為問題:(這里演示兼容用法)

import time, functools

import requests, trip

def timeit(fn):
    start_time = time.time()
    fn()
    return time.time() - start_time

url = 'http://httpbin.org/get'
times = 10 # 100 changed for inland network delay

def fetch():
    r = [requests.get(url) for i in range(times)]
    return r

@trip.coroutine
def async_fetch():
    r = yield [trip.get(url) for i in range(times)]
    raise trip.Return(r)

print('Non-trip cost: %ss' % timeit(fetch))
print('Trip cost: %ss' % timeit(functools.partial(trip.run, async_fetch)))

# Result:
# Non-trip cost: 17.90799999237s
# Trip cost: 0.172300004959s

由于協程的特性,所有的等待時間重合在了一起。

你不需要每個請求開一個線程,主線程中一切也可以井然有序的進行。

可以想象如果你在寫一個爬蟲,這將節省多少時間!

讓協程服務人類

基于 Requests 的操作方式讓協程 HTTP 從未如此簡單:(這里使用 Python3 演示async/await)

>>> async def main():
...     global r
...     r = await trip.get('https://httpbin.org/basic-auth/user/pass', auth=('user', 'pass'))
...
>>> trip.run(main)
>>> r.status_code
200
>>> r.headers['content-type']
'application/json'
>>> r.encoding
None
>>> r.text
u'{"authenticated": true,...'
>>> r.json()
{u'authenticated': True, u'user': u'user'}

只要你有一些 Requests 基礎就可以輕松使用 Trip,協程不再遙不可及。

重現了幾乎所有 Requests 的操作,最大限度的減少了你的學習成本。

以一個爬蟲為例

為了不打擾正常網站的運行,這里以httpbin.org作為目標網站。
設置 Cookies 模擬登陸,get 請求模擬爬取內容。

那么普通 Requests 是這樣的:

import requests

url = 'http://httpbin.org'
s = requests.Session()

def fetch(times=10):
    s.get('%s/cookies/set?name=value' % url)
    r = [s.get('%s/get' % url) for i in range(times)]
    print r

fetch()

使用 Trip 以后就會變成這樣:

import trip

url = 'http://httpbin.org'
s = trip.Session()

@trip.coroutine
def fetch(times=10):
    yield s.get('%s/cookies/set?name=value' % url)
    r = yield [s.get('%s/get' % url) for i in range(times)]
    print r

trip.run(fetch)

幾乎不需要修改代碼,爬蟲就獲得了協程的特性!

最后

爬蟲耗時太久優化困難嗎?
各種協程網絡框架難以使用嗎?
大型爬蟲框架臃腫無法靈活定制嗎?

試試Trip,你不會后悔的!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容