异步爬虫学习


异步爬虫

相关库

  • asyncio: 实现协程的库
  • aiohttp: 发送请求的第三方库,和requests,urllib这些爬虫库的区别是该库的请求方法都是异步请求方法

    协程知识

    协程和多线程类似,对于共用数据的使用也需要加锁等待,具体细节参照多线程.

asyncio的使用

概念

  • event_loop:事件循环,相当于无限循环,我们可以把一些函数注册到上面,当满足发生条件时,则调用对应的处理方法.
  • coroutine: 协程,指python中的协程对象,该协程对象通过注册到事件循环中调用.
  • task:对协程对象的进一步封装,增加了协程对象的状态
  • future:代表未来执行或者没有执行的任务的结果,和task没有区别.

    新加关键字

    asyncio新增了几个关键字,下面分别解释.
  • async:对方法或者协程对象使用,使用该方法定义的方法无法直接执行,而是返回一个协程对象,该对象必须注册到事件循环中执行(类似javaThread需要start)
    async def getResponse():
        pass
  • await: 将耗时等待的操作挂机,让出控制权,类似java中的wait方法.
    async def getResponse(url):
        response = await get(url)
    async def get(url):
        session = aiohttp.ClientSession()
        response = await session.get(url)
        await response.text()
        await session.close()
        return response

    使用方法

    代码样例:
    import asyncio
    import aiohttp
    
    async def getResponse(url):
        response = await get(url)
    
    async def get(url):
        session = aiohttp.ClientSession()
        response = await session.get(url)
        await response.text()
        await session.close()
        return response
    
    url = ""
    tasks = [asyncio.ensure_future(getResponse(url)) for _ in range(10)] ## 创建协程对象的列表,其中ensure_future方法和creat_task方法可以混用
    loop = asyncio.get_envent_loop() ## 创建事件循环
    loop.run_until_complete(asyncio.wait(tasks)) ## 调用tasks

aiohttp的使用

aiohttp是实现异步http协议操作的模块.该模块基于asyncio的异步http网络模块,既提供了服务端,也提供了客户端.服务端主要是用于处理请求与返回请求.客户端主要用于发起异步请求.爬虫只需要客户端就行.

样例代码

import aiohttp
import asyncio

async def fetch(session,url):
    async with session.get(url,params = params) as response: ## with as用于python增加一个上下文管理器,自动分配和管理资源
        return await response.text(),response.status          ## params 用于设置URL参数,和requests类似

async def main(url:str):
    async with aiohttp.ClientSession() as session:
        html,status = await fetch(url)
        print(html)
        print(status)

if __name__ == "__main__":
    url = ''
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(url) for _ in range(10))

aiohttp同样支持post请求等,和requests请求类似,就不赘述了

并发限制

使用asyncioSemaphore控制并发量,防止网站崩掉
类似于P/V原语,Semaphore定义的信号量需要自己手动管理,这个时候就展示出with的妙用了

import asyncio
CONCURRENCE = 10
semaphore = asyncio.Semaphore(CONCURRENCE)

async def getURL(URL):
    async with semaphore: ##相当于在开头结尾增加 P(semaphore)  V(semaphore)
        pass

Author: Dovahkiin
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Dovahkiin !
  TOC