Skip to content

Abrahum Link

asyncio的学习与应用

一直在制作完善pixiv的爬虫,最近遇到了一个问题,学校的网络环境太差了,导致了IO阻塞时间过长,常常出现线程长时间阻塞,占用了时间和内存。

为了解决这个问题,我决定尝试制定一个超时的图片删除重新爬取的过程,三次爬取不全则log报错不再爬取。

同时将整个脚本搬运至3.5版本,重新用asyncio异步编写,减少线程使用。

首先上一个asyncio的例子:

1import asyncio
2
3@asyncio.coroutine
4def hello():
5 print("Hello world!")
6 # 异步调用asyncio.sleep(1):
7 r = yield from asyncio.sleep(1)
8 print("Hello again!")
9
10# 获取EventLoop:
11loop = asyncio.get_event_loop()
12# 执行coroutine
13loop.run_until_complete(hello())
14loop.close()

@asyncio.coroutine把一个generator标记为coroutine类型,然后把这个coroutine放入EventLoop中执行。

2017年更新

经过测试,协程的大数据IO使用协程爬取效率并没有想象的高,考虑到这一丢丢的进程不会达到吃电脑性能的程度,不再全面使用协程。这里仅记录下一些代码,一便下次查阅:

1loop = asyncio.get_event_loop()
2s = requests.session()
3s.headers = headers1
4
5
6def get(url, asession=s):
7 return loop.run_in_executor(None, asession.get, url)
8
9
10def async_save(dataids, cookies, path):
11 s.cookies = requests.utils.cookiejar_from_dict(cookies)
12 tasks = []
13 for i in dataids:
14 tasks.append(simgle_async_save(i, path))
15 loop.run_until_complete(asyncio.wait(tasks))
16 loop.close()
17 return 0
18
19
20async def simgle_async_save(i, path, ceiling=4):
21 b = 0
22 ·······
23 if not is_exists:
24 pic = await get(originaltu)
25 fp = open(path, 'wb')
26 fp.write(pic.content)
27 fp.close() # 保存图片
28 '''print(i+'-'+str(b) + ' download is Success')'''