Featured image of post 初试python黑魔法asyncio

初试python黑魔法asyncio

前言

本篇要从小7的朋友说起。数据组的他收到业务提交的三个excel。要求将其中的地址转成经纬度,然后匹配最近的银行网点。现用的转换程序约二秒出一条记录,三个excel总数据量约十几万。这也难怪会愁了。

正文

0x01使用scrapy爬虫框架处理。

原因有以下几点:

  1. 上次使用scrapy爬携程评论现在还是比较熟悉
  2. scrapy使用的是异步请求(重点)
  3. 框架设计有数据持久化 但在程序中,速度任然很慢。没去深究原因,转面使用aiohttp+asyncio处理。

0x02试用asyncio

asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。 asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO

asyncio代码,40个并发跑起真的非常快。7万的数据,半个小时搞定。

import time
import asyncio
from aiohttp import ClientSession

i = 0
max = 40
addrs = []
tasks = []
url = "http://api.map.baidu.com/geocoder/v2/?address={}&output=json&ak=你的百度AK"

async def getInfo(url):
    async with ClientSession() as session:
        async with session.get(url) as response:
            return await response.read()

def run():
    #读取地址文件
    with open('a.txt', 'r', encoding='utf8') as f:
        lines = f.readlines()
        for line in lines:
            line = line.strip('\n')
            task = asyncio.ensure_future(getInfo(url.format(line)))
            tasks.append(task)
            addrs.append(line)
            global i, max
            i = i + 1
            if i >= max: # 40个一并发
                t = 0
                results = loop.run_until_complete(asyncio.gather(*tasks))
                #写入响应信息
                with open('a_dst.txt', 'a', encoding='utf8') as dstfile:
                    for r in results:
                        dstfile.writelines(addrs[t] + r.decode() + '\n')
                        t = t + 1
                i = 0
                tasks.clear()
                addrs.clear()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    run()

0x03处理后续结果

处理下结果文件,最后转成excel,十几万的数据处理完成。

结束语

使用asyncio上手还是比较简单。主要是理解事件循环,协程和任务,future的关系。

参考:

Python黑魔法 — 异步IO( asyncio) 协程 python异步编程之asyncio(百万并发)