爬虫
协程
- 特殊的函数:
- 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数。
- 协程:
- 对象。特殊函数被调用后,函数内部的实现语句不会被立即执行,然后该函数
调用会返回一个协程对象。
- 结论:协程对象==特殊的函数调用
- 任务对象
- 起始就是对协程对象的进一步封装。
- 结论:任务对象==高级的协程对象==特殊的函数调用
- 绑定回调:
- 回调函数什么时候被执行?
- 任务对象执行结束后执行回调函数
- task.add_done_callback(func)
- func必须要有一个参数,该参数表示的是该回调函数对应的任务对象
- 回调函数的参数.result():任务对象对应特殊函数内部的返回值
- 事件循环对象
- 作用:将其内部注册的任务对象进行异步执行。
- 编码流程:
- 定义特殊函数
- 创建协程对象
- 封装任务对象
- 创建事件循环对象
- 将任务对象注册到事件循环中且开启事件循环对象
- 注意:在特殊函数内部的实现语句中不可以出现不支持异步的模块对应的代码,否则
就是终止多任务异步协程的异步效果
单协程
import asyncio from time import sleep #函数的定义 async def get_request(url): print('正在请求:',url) sleep(1) print('请求结束:',url) #函数调用:返回的就是一个协程对象 c = get_request('www.1.com') #创建一个任务对象:基于协程对象创建 task = asyncio.ensure_future(c) #创建一个事件循环对象 loop = asyncio.get_event_loop() #将任务对象注册到事件循环对象中并且开启事件循环 loop.run_until_complete(task)
多任务异步协程
import asyncio from time import sleep import time #函数的定义 async def get_request(url): print('正在请求:',url) await asyncio.sleep(1) print('请求结束:',url) #创建3个协程对象 urls = [ '1.com','2.com','3.com' ] start = time.time() #任务列表:存储的是多个任务对象 tasks = [] for url in urls: c = get_request(url) # 创建一个任务对象:基于协程对象创建 task = asyncio.ensure_future(c) tasks.append(task) #创建一个事件循环对象 loop = asyncio.get_event_loop() #将任务对象注册到事件循环对象中并且开启事件循环 loop.run_until_complete(asyncio.wait(tasks)) # 放入的如果是列表要加asyncio.wait() print('总耗时:',time.time()-start)
import asyncio from time import sleep import time #函数的定义 async def get_request(url): print('正在请求:',url) await asyncio.sleep(1) print('请求结束:',url) #创建3个协程对象 urls = [ '1.com','2.com','3.com' ] start = time.time() #任务列表:存储的是多个任务对象 tasks = [] for url in urls: c = get_request(url) # 创建一个任务对象:基于协程对象创建 task = asyncio.ensure_future(c) tasks.append(task) #创建一个事件循环对象 loop = asyncio.get_event_loop() #将任务对象注册到事件循环对象中并且开启事件循环 loop.run_until_complete(asyncio.wait(tasks)) # 放入的如果是列表要加asyncio.wait() print('总耗时:',time.time()-start)
给任务对象绑定回调
func必须要有一个参数,该参数表示的是该回调函数对应的任务对象
回调函数的参数.result():任务对象对应特殊函数内部的返回值
task.add_done_callback(parse)
import asyncio from time import sleep import time #函数的定义 async def get_request(url): print('正在请求:',url) await asyncio.sleep(3) print('请求结束:',url) return 'bobo' def parse(task): print('i am task callback()!!!=----',task.result()) #创建3个协程对象 urls = [ '1.com','2.com','3.com' ] start = time.time() #任务列表:存储的是多个任务对象 tasks = [] for url in urls: c = get_request(url) task = asyncio.ensure_future(c) #绑定回调 task.add_done_callback(parse) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start)
import asyncio from time import sleep import time #函数的定义 async def get_request(url): print('正在请求:',url) await asyncio.sleep(3) print('请求结束:',url) return 'bobo' def parse(task): print('i am task callback()!!!=----',task.result()) #创建3个协程对象 urls = [ '1.com','2.com','3.com' ] start = time.time() #任务列表:存储的是多个任务对象 tasks = [] for url in urls: c = get_request(url) task = asyncio.ensure_future(c) #绑定回调 task.add_done_callback(parse) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start)
多任务的异步爬虫(重点)
- 注意重点:requests模块不支持异步,在多任务的异步协程中不可以使用requests
- aiohttp
- 概念:支持异步的网络请求模块
- 编码流程:
- 写基本架构:
with aiohttp.ClientSession() as s:
with s.get(url) as response:
page_text = response.text()
return page_text
- 补充细节:
- 添加async关键字
- 每一个with前加上async
- 添加await关键字
- 加载每一步的阻塞操作前加上await
- 请求
- 获取响应数据
import asyncio import requests import time import aiohttp from lxml import etree #特殊函数:发起请求获取页面源码数据 # async def get_request(url): # #requests是一个不支持异步的模块 # page_text = requests.get(url).text # return page_text async def get_request(url): async with aiohttp.ClientSession() as s: #get/post:proxy = 'http://ip:port' #url,headers,data/prames跟requests一直 async with await s.get(url) as response: page_text = await response.text()#text()字符串形式的响应数据。read()二进制的响应数据 return page_text def parse(task): page_text = task.result() tree = etree.HTML(page_text) print(tree.xpath('/html/body/div[2]/div[3]/div[3]/h3/a/@href')) urls = [ 'https://www.huya.com/?ptag=gouzai&rso=huya_h5_395', ] start = time.time() tasks = [] #任务列表 for url in urls: c = get_request(url) task = asyncio.ensure_future(c) #绑定回调:用作于数据解析 task.add_done_callback(parse) tasks.append(task) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start)
selenium
- 概念:基于浏览器自动化的一个模块。 - Appium是基于手机的自动化的模块。 - selenium和爬虫之间的关联 - 便捷的爬取到动态加载的数据 - 可见即可得 - 便捷的实 现模拟登陆 - 基本使用: - 环境安装 - pip install selenium - 下载浏览器的驱动程序 - http://chromedriver.storage.googleapis.com/index.html - 浏览器版本和驱动程序的映射关系:https://blog.csdn.net/huilan_same/article/details/51896672
xxx就是我的个性签名