python 爬虫之协程的使用

python 爬虫之协程的使用,第1张

python 爬虫之协程的使用

- 单线程+多任务异步协程:pip install asyncio
    - 特殊的函数
        - 如果一个函数的定义被async修饰后,则该函数就变成了一个特殊的函数
        - 特殊之处:
            - 该特殊的函数调用后,函数内部的实现语句不会被立即执行
            - 该特殊函数被调用后会返回一个协程对象
    - 协程对象
        - 对象。通过特殊函数的调用返回一个协程对象。
        - 协程 == 特殊函数 == 一组指定的 *** 作
        - 协程 == 一组指定的 *** 作
    - 任务对象
        - 任务对象就是一个高级的协程对象。(任务对象就是对协程对象的进一步封装)
        - 任务 == 协程 == 特殊函数 == 一组指定 *** 作
        - 任务 == 一组指定的 *** 作
        - 如何创建一个任务对象:
            - asyncio.ensure_future(协程对象)
        - 任务对象的高级之处:
            - 可以给任务对象绑定回调:
                - task.add_done_callback(task_callback)
                - 回调函数的调用时机:
                    - 任务被执行结束后,才可以调用回调函数
                - 回调函数的参数只可以有一个:表示的就是该回调函数的调用者(任务对象)
                - 使用回调函数的参数调用result()返回的就是任务对象表示的特殊函数return的结果
    - 事件循环对象
        - 对象。
        - 作用:
            - 可以将多个任务对象注册/装载到事件循环对象中
            - 如果开启了事件循环后,则其内部注册/装载的任务对象表示的指定 *** 作就会被基于异步的被执行
        - 创建方式:
            - loop = asyncio.get_event_loop()
        - 注册且启动方式:
            - loop.run_until_complete(task)

    - wait方法的作用:
        - 将任务列表中的任务对象赋予可被挂起的权限。只有任务对象被赋予了可被挂起的权限后,该
            任务对象才可以被挂起
            - 挂起:将当前的任务对象交出cpu的使用权。
    - 注意事项【重要】:
        - 在特殊函数内部不可以出现不支持异步模块对应的代码,否则会中断整个异步效果

    - await关键字
        - 在特殊函数内部,凡是阻塞 *** 作前都必须使用await进行修饰。await就可以保证
        阻塞 *** 作在异步执行的过程中不会被跳过!

- aiohttp
    - 是一个支持异步的网络请求模块。
    - pip install aiohttp
    - 使用代码:
        - 1.写出一个大致的架构
            async def get_request(url):
            #实例化好了一个请求对象
            with aiohttp.ClientSession() as sess:
                #调用get发起请求,返回一个响应对象
                #get/post(url,headers,params/data,proxy="http://ip:port")
                with sess.get(url=url) as response:
                    #获取了字符串形式的响应数据
                    page_text = response.text()
                    return page_text
        - 2.补充细节
            - 在阻塞 *** 作前加上await关键字
            - 在每一个with前加上async关键字
        - 完整代码:
            async def get_request(url):
                #实例化好了一个请求对象
                with aiohttp.ClientSession() as sess:
                    #调用get发起请求,返回一个响应对象
                    #get/post(url,headers,params/data,proxy="http://ip:port")
                    with await sess.get(url=url) as response:
                        #text()获取了字符串形式的响应数据
                        #read()获取byte类型的响应数据
                        page_text = await response.text()
                        return page_text
    - 多任务爬虫的数据解析
        - 一定要使用任务对象的回调函数实现数据解析
        - why:
            - 多任务的架构中数据的爬取是封装在特殊函数中,我们一定要保证数据请求结束后,
                在实现数据解析。
                
    - 使用多任务的异步协程爬取数据实现套路:
        - 可以先使用requests模块将待请求数据对应的url封装到有个列表中(同步)
        - 可以使用aiohttp模式将列表中的url进行异步的请求和数据解析(异步)

 

import requests
import asyncio
import time
import aiohttp
from lxml import etree
urls = [
    'cc',
    'bb',
    'aa'
]
# 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 sess:
        #调用get发起请求,返回一个响应对象
        #get/post(url,headers,params/data,proxy="http://ip:port")
        async with await sess.get(url=url) as response:
            #text()获取了字符串形式的响应数据
            #read()获取byte类型的响应数据
            page_text = await response.text()
            return page_text

#解析函数的封装
def parse(t):
    #获取请求到页面源码数据
    page_text = t.result()
    tree = etree.HTML(page_text)
    parse_text = tree.xpath('//a[@id="feng"]/text()')[0]
    print(parse_text)

if __name__ == "__main__":
    start = time.time()
    tasks = []  # 多任务列表
    # 创建协程对象
    for url in urls:
        c = get_request(url)   #  创建一个协程对象
        # 创建任务对象
        task = asyncio.ensure_future(c)   # 任务对象就是对协程对象的进一步封装
        task.add_done_callback(parse)   # 给task绑定一个回调函数
        tasks.append(task)
    loop = asyncio.get_event_loop()   # 创建事件循环对象
    # 必须使用wait方法对tasks进行封装才可
    loop.run_until_complete(asyncio.wait(tasks))   3 将任务对象注册到事件循环中且开启事件循环
    print('总耗时:',time.time()-start)

# pip install aiohttp
import aiohttp  # 使用该模块中的ClientSession
import asyncio


header={
    'User-agent':'aaaaa'
}
async def test_header():
    async with aiohttp.ClientSession(headers=header,cookies={'token':'123sd'}) as session:
        async with session.get('url',params={'name':'bjsxt'},proxy='http://name:pwd@ip:port') as resp:
            # text() 返回字符串形式的相应数据
            # read() 返回的二进制形式的响应数据
            # json() 返回的就是json对象
            rs = await resp.text()
            print(rs) 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5658318.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存