1、异步爬虫

高性能异步爬虫

目的:在爬虫中使用异步实现高性能的数据爬取操作。

2、多进程和多线程(不建议大家使用)

  • 好处:可以为相关阻塞的操作单独开启线程或者进程,阻塞操作就可以异步执行


  • 弊端:无法无限制的开启多线程或者多进程。

    3、进程池和线程池(适当的使用)

  • 好处:我们可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销。


  • 弊端:池中线程或进程的数量是有上限的。


  • 原则:线程池处理的是阻塞且耗时的操作。

    4、单线程+异步协程(推荐使用)

  • event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件时,函数就会被循环执行


  • coroutinne:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用。
    • 我们可以使用async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。


  • task:任务,他是对协程对象的进一步封装,包含了任务的各个状态


  • future:代表将来执行或还没有执行的任务,实际上和task没有本质区别


  • async:定义一个协程


  • await:用来挂起阻塞方法的执行

在异步协程中如果出现了同步模块相关的代码,那么就无法实现异步

requests模块就是同步模块,所以就要换成aiohttp 模块来发请求 【不然实现不了异步】**

5、aiohttp 异步请求模块

pip install aiohttp 下载模块

  1. # 定义一个函数
  2. async def get_page(url):
  3. async with aiohttp.ClientSession() as session:
  4. async with await session.get/post(url) as response:
  5. # 注意在获取响应数据操作之前 一定要使用 await 手动挂起
  6. page_text = await reponse.text()
  7. # text()方法返回字符串响应数据 和requests模块不同
  8. # read()方法 返回二进制形式的响应数据
  9. # json() 方法 返回json对象

6、多任务协程

  1. import asyncio
  2. import time
  3. async def request(url):
  4. print("正在下载", url)
  5. # 在异步协程中如果出现了同步模块相关的代码,那么就无法实现异步
  6. await asyncio.sleep(2)
  7. print("下载完毕", url)
  8. start = time.time()
  9. urls = {
  10. "www.baidu.com",
  11. "www.vip.com",
  12. "www.jd.com"
  13. }
  14. # 任务列表:存放多个任务对象
  15. stasks = []
  16. for url in urls:
  17. c = request(url)
  18. task = asyncio.ensure_future(c)
  19. stasks.append(task)
  20. loop = asyncio.get_event_loop()
  21. # 需要将任务列表封装到wait中
  22. loop.run_until_complete(asyncio.wait(stasks))
  23. print(time.time() - start)
  24. -----------------------------------------------------------------------------
  25. import asyncio
  26. async def request(url):
  27. print("正在请求的url是:", url)
  28. print("请求成功", url)
  29. # async 修饰的函数,在调用后返回一个协程对象,不会立即执行
  30. c = request("www.baidu.com")
  31. # # 创建一个事件循环对象
  32. # loop = asyncio.get_event_loop()
  33. #
  34. # # 将协程对象注册到loop中,然后启动loop
  35. # loop.run_until_complete(c)
  36. # -----------------------------------------------------------
  37. # # task的使用 对协程的进一步封装
  38. # # 将协程对象封装到任务对象
  39. # loop = asyncio.get_event_loop()
  40. # # 基于loop创建了一个task对象
  41. # task = loop.create_task(c)
  42. # # 注册task
  43. # loop.run_until_complete(task)
  44. # -----------------------------------------------------------
  45. # -----------------------------------------------------------
  46. # future的使用
  47. loop = asyncio.get_event_loop()
  48. future = asyncio.ensure_future(c)
  49. # 注册future 执行future
  50. loop.run_until_complete(future)
  51. # -----------------------------------------------------------