前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实战:异步爬取之异步的简单使用

实战:异步爬取之异步的简单使用

作者头像
渔父歌
发布于 2018-09-26 10:43:31
发布于 2018-09-26 10:43:31
72400
代码可运行
举报
文章被收录于专栏:数据结构笔记数据结构笔记
运行总次数:0
代码可运行

一、使用异步的注意事项

  1. 异步代码中不能有耗时的 I/O操作,像文件读写、网络请求、数据库读写等操作都需要使用对应的异步库来代替。
  2. 异步代码要尽可能短小,短小的意思就是功能要尽可能细分,前面讲过异步在任务量较少的时候性能并不能达到最优,我们可以通过合理地拆分代码来增加任务量,从而达到提高性能的目的。

二、使用异步需要了解的两个重要的类

  1. AbstractEventLoop,我们可以把它简称为 EventLoop类或者事件循环。事件循环是整个异步的基础,所有的异步操作都在事件循环里完成。 这里我们需要了解并学会使用它的如下几个方法:
    • run_until_complete(Future) 该方法接受一个或多个 Future对象作为参数,然后运行这些对象直到全部完成并返回它们的结果
    • run_forever() 让事件循环一直运行下去,直到 stop() 方法被调用,当 stop() 方法被调用时,会继续执行完正在执行的任务,但是这些任务的回调和未被执行的任务将不再执行。
    • create_task()create_future() 光看名字可能大家会误以为这两个方法的功能是创建一个 Task类或者 Future类并将其返回,事实上这两个方法的功能确实包括这个,但是除此之外它们还会将创建的对象添加到事件循环中去。
  2. Future,Future对象类似于 JavaScript里的 Promise对象,简单来说就是该对象承诺未来的某个时候会返回一个结果,但是具体的时间是不确定的。 所以我们一般在回调函数里使用 Feture对象,因为这时候 Feture对象一定有返回结果。
    • add_done_callback(func) 这个方法为 Future对象添加一个回调函数,该函数接收一个 Future对象作为第一个参数,在函数里我们可以通过这个对象来取得其执行结果。
  3. 使用过 asyncio库的朋友可能会疑惑为什么没有 Task类,这是因为 Task 类是 Future 类的子类,我们可以将它们视作具有相同功能的两个类

三、使用异步的基本方法

首先,对于少量的请求(几百)我们不推荐使用异步,一般是成千上万的请求我们才使用异步,比如说爬取全站。

在同步代码中我们爬取的一般步骤是:请求页面---->解析页面---->获取结果---->保存结果

异步中也是类似的顺序,不过我们需要使用回调来确保它们按顺序执行,像下面这样:

请求页面---->回调:解析页面---->获取结果---->保存页面(异步)

比如我们要获取简书用户的关注列表,我们的代码顺序应该是:

请求页面---->回调:处理页面---->获取结果并打印,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#-*- coding: utf-8 -*
import asyncio
import aiohttp
import random

from lxml import etree


PER_NUM = 9

async def get_response(url, **kwargs):
    if 'headers' not in kwargs:
        kwargs['headers'] = {
            'User-Agent': "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10",
        }

    async with session.get(url, **kwargs) as response:
        print(response.status)
        return await response.read()

def process_response(future):
    dom = etree.HTML(future.result())

    items = dom.xpath('//ul/li//div[@class="info"]')

    for item in items:
        user = {}

        user['uid'] = item.xpath('./a/@href')[0].split('/')[2]
        user['follow_num'] = int(item.xpath('./div/span[1]/text()')[0].replace('关注', '').strip())
        user['fans_num'] = int(item.xpath('./div/span[2]/text()')[0].replace('粉丝', '').strip())
        user['article_num'] = int(item.xpath('./div/span[3]/text()')[0].replace('文章', '').strip())

def entry_point(param):
    if isinstance(param, asyncio.Future):
        users = param.result()
    else:
        users = param

    for user in users:
        uid = user['uid']
        follow_num = user['follow_num']
        max_page = int(follow_num / PER_NUM) if (follow_num % PER_NUM) == 0 else int(follow_num / PER_NUM)+1
        following_urls = ['https://www.jianshu.com/users/{}/following?page={}'.format(uid, i) for i in
                          range(1, max_page+1)]

        for following_url in following_urls:
            task = loop.create_task(get_response(following_url))
            task.add_done_callback(process_response)


loop = asyncio.get_event_loop()
session = aiohttp.ClientSession(loop=loop)

users = [{'uid': 'a3ea268aeb60', 'follow_num': 525, 'fans_num': 2521, 'article_num': 118}]

entry_point(users)

loop.run_forever()

在段代码中我们通过 entry_point 函数来将所有的请求添加到事件循环中,并且为每个请求添加了一个回调函数来获取关注者的信息,示意图如下:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.08.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
为了带你搞懂RPC,我们手写了一个RPC框架
远程服务调用(Remote procedure call)的概念历史已久,1981年就已经被提出,最初的目的就是为了调用远程方法像调用本地方法一样简单,经历了四十多年的更新与迭代,RPC 的大体思路已经趋于稳定,如今百家争鸣的 RPC 协议和框架,诸如 Dubbo (阿里)、Thrift(FaceBook)、gRpc(Google)、brpc (百度)等都在不同侧重点去解决最初的目的,有的想极致完美,有的追求极致性能,有的偏向极致简单。
Rude3Knife的公众号
2022/04/28
4010
为了带你搞懂RPC,我们手写了一个RPC框架
徒手撸框架--实现 RPC 远程调用
微服务已经是每个互联网开发者必须掌握的一项技术。而 RPC 框架,是构成微服务最重要的组成部分之一。趁最近有时间。又看了看 dubbo 的源码。dubbo 为了做到灵活和解耦,使用了大量的设计模式和 SPI机制,要看懂 dubbo 的代码也不太容易。
用户2060079
2018/10/11
7690
RPC框架原理与实现
RPC,全称 Remote Procedure Call(远程过程调用),即调用远程计算机上的服务,就像调用本地服务一样。那么RPC的原理是什么呢?了解一个技术最好的思路就是寻找一个该类型麻雀虽小五脏俱全的开源项目,不负所期,找到一个轻量级分布式 RPC 框架,本文从这个项目入手来解读RPC的原理及其实现。 其实说到RPC,大家应该不会陌生才是,以往流行的Web Service就是一种RPC,一般来说RPC 可基于 HTTP 或 TCP 协议,因为Web Service 基于HTTP,所以具有良好的跨平台性
JadePeng
2018/03/12
2.3K0
RPC框架原理与实现
解密Dubbo:自己动手编写一个较为完善的RPC框架(两万字干货)
现在很多企业都在使用Dubbo或者Spring Cloud做企业的微服务架构,其实对于Dubbo最核心的技术就是RPC调用,现在我们就来动手自己编写一个RPC框架,通过这篇文章的学习,你将学习到
java进阶架构师
2018/12/10
1.3K0
解密Dubbo:自己动手编写一个较为完善的RPC框架(两万字干货)
我开源了一套 RPC 框架,学爆它!
呼吸不停,新项目不止!前段时间开始带大家做的新项目《从 0 到 1 开发 RPC 框架》已经完成,教程也已经写完了~
程序员鱼皮
2024/07/31
6520
我开源了一套 RPC 框架,学爆它!
花了一星期,自己写了个简单的RPC框架
学了netty框架以及看了一下一小部分的netty框架的源码,听说dubbo是基于netty框架的一个优秀的落地实现,所以看了一小部分dubbo的源码,感觉学习netty总要有一个方式证明自己曾经学过,所以写下这一篇小笔记,写给自己看。
CBeann
2023/12/25
2160
花了一星期,自己写了个简单的RPC框架
你说说RPC的一个请求的流程是怎么样的?
面试的时候经常被问到RPC相关的问题,例如:你说说RPC实现原理、让你实现一个RPC框架应该考虑哪些地方、RPC框架基础上发起一个请求是怎样一个流程等等。所以这次我就总结一波RPC的相关知识点,提前说明一下,本篇文章只是为了回答一些面试问题,所以只是解释原理,并不会深入挖掘细节。
纪莫
2021/11/10
1.8K0
rpc系列1-10 minute Tutorial
最近在网上看到阿里巴巴2015年的中间件性能挑战赛的一个题目,实现一个简单的RPC框架,于是乎有一种冲动实现一个简单的rpc,要求基本按照竞赛题目的要求,具体如下:
topgunviper
2022/05/12
2330
rpc系列1-10 minute Tutorial
造个轮子之基于 Netty 实现自己的 RPC 框架
服务端开发都会或多或少的涉及到 RPC 的使用,当然如果止步于会用,对自己的成长很是不利,所以楼主今天本着知其然,且知其所以然的精神来探讨一下 RPC 这个东西。
haifeiWu
2018/09/11
5150
造个轮子之基于 Netty 实现自己的 RPC 框架
手写RPC框架(二)--手写客户端和服务端源码
在 RPC 框架中,最关键的就是理解“桩”的实现原理,桩是 RPC 框架在客户端的服
小时的棒棒糖
2023/11/30
3440
卷起来了!手把手带你写一个中高级程序员必会的分布式RPC框架
◆ 一.概述 什么是RPC? 远程服务调用 官方:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想 通俗一点:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样。 市面上常见的rpc框架:dobbo,springCloud,gRPC... 那为什么要有 RPC,HTTP 不好么? 因为 RPC 和 HTTP 就不是一个层级的东西,所以严格意义上这两个没有可比性,也不应该来作比较。 HTTP 只是传输协议,协议只是规范了一定的交流格式 R
IT大咖说
2022/03/04
2840
手写类似dubbo的rpc框架第三章《rpc框架》
案例介绍 结合上面两章节,本章将实现rpc的基础功能;提供一给rpc中间件jar给生产端和服务端。 技术点; 1、注册中心,生产者在启动的时候需要将本地接口发布到注册中心,我们这里采用redis作为注册中心,随机取数模拟权重。 2、客户端在启动的时候,连接到注册中心,也就是我们的redis。连接成功后将配置的生产者方法发布到注册中心{接口+别名}。 3、服务端配置生产者的信息后,在加载xml时候由中间件生成动态代理类,当发生发放调用时实际则调用了我们代理类的方法,代理里会通过netty的futuer通信方式进行数据交互。
小傅哥
2020/07/14
5700
手写类似dubbo的rpc框架第三章《rpc框架》
阿里面试官:你给我手写个RPC框架看看
今天,就来聊聊“RPC 实现原理”(其他相关如何设计一个XX系列,已发布到知识星球中了)
田维常
2022/06/13
5070
阿里面试官:你给我手写个RPC框架看看
RPC项目记录二期 - Netty替换socket,实现网络传输,解编码器,序列化器
需要实现commonEncoder,CommonDecoder,NettyClientHandler。
宇宙无敌暴龙战士之心悦大王
2022/02/17
5520
RPC项目记录二期 - Netty替换socket,实现网络传输,解编码器,序列化器
你管这个叫Dubbo?
又到年初了,大家又要开始准备面试了。为了方便大家,我就写几篇面试相关的文章吧,这次是Dubbo
Java识堂
2022/04/06
3500
你管这个叫Dubbo?
从0.5到1写个rpc框架 - 5:服务监控和管理(actuator)
springboot项目中只要引入spring-boot-starter-actuator就可以得到一些管理服务的接口,比如停止服务,获取服务信息等。他用的并不是controller,而是Endpoint,不过主要功能差不多。
acupt
2019/08/26
5980
手写了一个RPC框架
当开发一个单体项目的时候,大家肯定都写过类似的代码。即服务提供方和服务调用方在一个服务中
Java识堂
2020/11/03
4510
Spring集成RabbitMQ简单实现RPC
spring整合Rabbit MQ提供了Reply来实现RPC,AMQP协议定义了14中消息的属性,其中两项,一项是Replyto,表示返回消息的队列,一个是correlationId 用来表示发送消息和返回消息的标志,来区分是否是一个调用
java进阶架构师
2020/12/03
7030
Spring集成RabbitMQ简单实现RPC
手撕RPC实现基于TCP的仿Dubbo简单实现
文章目录 手撕RPC实现基于TCP的仿Dubbo实现 方法调用效果实现 分模块 写接口 通过代理写好了客户端 写服务端,并联调rpc 代码实现 myRpc rpc-client rpc-interface rpc-server 源码 手撕RPC实现基于TCP的仿Dubbo实现 还记得第一次听到这词是在别人的面试视频里,简单了解了一下只知道是远程调用。 万万没想到我的第一次面试的第一个问题就是与此相关,希望认真准备每一次面试,及时查漏补缺,谨以此文,代表诚意~奥利给! 思路: my-rpc通过cl
瑞新
2020/07/07
7450
框架扩展:注解 RPC Consumer属性动态注入
分布式系统架构时代,RPC框架你一定不会陌生。目前主流的RPC框架有 dubbo、thrift、motan、grpc等。
微观技术
2021/01/21
1.3K0
推荐阅读
相关推荐
为了带你搞懂RPC,我们手写了一个RPC框架
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验