技巧:用 PyQt5 写一个傻瓜式的一键数据采集软件

优采云 发布时间: 2022-10-12 10:22

  技巧:用 PyQt5 写一个傻瓜式的一键数据采集软件

  数据采集越来越成为互联网从业者的刚需。

  从内部报告到外部市场动态,需要采集大大小小的信息和数据。爬虫无疑是最快最高效的常规数据采集的方法。但是,要写爬虫,必须有一定的编程基础,谁能受得了。市面上也有一些自助数据采集工具,如:优采云、优采云等,确实是在降低数据采集和门槛和方便数据采集的操作。但这些工具或多或少还是需要手动定义和选择规则。在State先生的“前爬虫生涯”中,遇到过很多生意人,有一个要求:直接把数据给我。如果答案是否定的,它会说:你给我一个工具,让我点击数据,它就会出来。其实我们可以使用PyQt5对爬虫程序进行封装打包,实现傻瓜式,一键式采集软件。这个特别适合普通商务人士,实时数据性能不高,但需要登录。网站。下面,我们以采集微信公众号后台数据为例,介绍使用PyQt5开发一键傻瓜式数据采集工具。核心采集代码就到这里了,我们只用采集微信公众号后台“整体账号状态”的数据作为演示:这个特别适合普通商务人士,实时数据性能不高,但需要登录。网站。下面,我们以采集微信公众号后台数据为例,介绍使用PyQt5开发一键傻瓜式数据采集工具。核心采集代码就到这里了,我们只用采集微信公众号后台“整体账号状态”的数据作为演示:这个特别适合普通商务人士,实时数据性能不高,但需要登录。网站。下面,我们以采集微信公众号后台数据为例,介绍使用PyQt5开发一键傻瓜式数据采集工具。核心采集代码就到这里了,我们只用采集微信公众号后台“整体账号状态”的数据作为演示:

  我们使用 requests 库来处理 HTTP 请求,使用 BeautifulSoup 来解析和提取 HTML 文档的数据。其核心采集代码如下:

  <p> def check_status(self):

   try:

   print("获取到的Cookie:", self.cookie)

   print("获取到的Token:",self.token)

   # 获取当前登录店铺和用户名

   url = 'https://mp.weixin.qq.com/cgi-bin/home?t=home/index&token={token}&lang=zh_CN'.format(token=self.token)

   wbdata = requests.get(url, headers=self.header, cookies=self.cookie).text

   soup = BeautifulSoup(wbdata,'lxml')

   nickname = soup.select_one("a.weui-desktop-account__nickname").get_text()

   total_cnt = soup.select("em.weui-desktop-data-overview__desc")[2].get_text()

   self.nickname = nickname

   except Exception as e:

   self.nickname = None

   logger.error("获取用户信息出错:{}".format(repr(e)))

   return (self.nickname, self.cookie)</p>

  

  搭建图形界面因为微信公众号需要登录才能使用,所以我们使用PyQt5的QtWebEngineWidgets小部件在程序中嵌入浏览器,直接在程序中实现登录操作。

  可以看到我们图形程序的主界面分为两个选项卡,通过QTabWidget选项卡部分实现。在第一个选项卡中,我们放置了一个 QtWebEngineWidgets QWebEngineView 小部件,用于显示网页和登录。在第二个选项卡中,我们放置了按钮小部件和文本输入小部件,用于控制数据采集 的进度和结果以及显示数据采集.

  采集处理与控制 程序的图形界面构建完成后,我们需要对程序的功能进行处理。这些功能包括: 网页的cookie是我们获取登录状态的关键。在这里,浏览器配置文件是通过 QtWebEngineWidgets 的 QWebEngineProfile 组件实现的。QWebEngineProfile 有一个 cookie 存储,每个请求都会将 cookie 写入 QWebEngineProfile,我们将从这里读取最新的 cookie。数据采集的执行是通过“检查登录状态”按钮进行的​​,按钮的点击信号绑定了一个槽函数。slot函数调用QThread在子线程中执行数据采集。核心代码。而结果的输出,我们通过文本输出框来实现。

  <p> # 在控制台中写入信息

   def outputWritten(self, text=None):

   cursor = self.label_1.textCursor()

   cursor.movePosition(QtGui.QTextCursor.End)

   cursor.insertText(text)

   self.label_1.setTextCursor(cursor)

   self.label_1.ensureCursorVisible()</p>

  

  这样,在按钮的slot函数中,调用outputWritten方法在文本框中输出采集信息。最后的结果最终我们实现的效果是:打开程序,在“登录页面”标签页扫码登录微信公众号后台;然后切换到“操作页面”,点击“检查登录状态”按钮,程序会自动采集数据,最后输出到文本输入框。未登录时的效果:

  登录状态下的效果:

  按照同样的逻辑,我们可以在采集网页中实现其他数据,比如文章列表数据、观察列表用户数据等,或者其他网站数据。

  您希望它以“Python GUI 开发视频教程”的形式呈现吗?点击下方“看”,给它一个去大厅的机会,给我一个鼓励!

  核心方法:40张图看懂分布式追踪系统原理及实践

  本文将从以下几个方面进行阐述

  分布式追踪系统的原理和作用

  如何衡量一个接口的性能,一般我们至少会关注以下三个指标

  单体架构

  早期,公司刚起步时,可能采用以下单一结构。对于单一结构,我们应该如何计算上述三个指标呢?

  40张图看懂分布式追踪系统原理与实践

  最容易想到的显然是使用AOP

  40张图看懂分布式追踪系统原理与实践

  使用AOP打印调用具体业务逻辑前后的时间,计算整体调用时间。使用 AOP 捕获异常并知道调用导致异常的位置。

  微服务架构

  在单体架构中,由于所有的服务和组件都在一台机器上,这些监控指标比较容易实现。但是随着业务的快速发展,单体架构必然会向微服务架构发展,如下

  40张图看懂分布式追踪系统原理与实践

  如图:稍微复杂的微服务架构

  如果用户报告一个页面很慢,我们知道这个页面的请求调用链是A -----&gt; C -----&gt; B -----&gt; D,如何定位到哪个模块可能是在这个时候引起的问题。每个服务 Service A、B、C、D 都有几台机器。如何知道请求调用了哪台服务?

  40张图看懂分布式追踪系统原理与实践

  可以明显看出,由于无法准确定位每个请求经过的确切路径,微服务架构下存在以下痛点

  故障排除困难,周期长

  难以重现某些场景

  系统性能瓶颈分析难

  分布式调用链就是为解决上述问题而诞生的,其主要功能如下

  通过分布式跟踪系统,可以很好地定位后续请求的各个具体请求链路,从而轻松实现请求链路跟踪,定位分析各个模块的性能瓶颈。

  40张图看懂分布式追踪系统原理与实践

  分布式调用链标准 - OpenTracing

  了解了分布式调用链的作用,我们来看看分布式调用链的实现方式和原理。首先,为了解决不同分布式追踪系统API不兼容的问题,OpenTracing规范应运而生。OpenTracing 是一个轻量级的 A 级标准化层,位于应用程序/库和跟踪或日志分析器之间。

  40张图看懂分布式追踪系统原理与实践

  通过这种方式,OpenTracing 提供了独立于平台、独立于供应商的 API,使开发人员能够轻松添加跟踪系统的实现。

  说到这里,你有没有想过在 Java 中也有类似的实现?记住JDBC,通过提供一套标准的接口供各个厂商实现,程序员可以直接面对接口编程,而不必关心具体的实现。这里的接口其实是一个标准,所以制定一套标准非常重要,可以实现组件的可插拔。

  40张图看懂分布式追踪系统原理与实践

  接下来我们看一下OpenTracing的数据模型,主要有以下三个

  理解这三个概念非常重要。为了让大家更好的理解这三个概念,特地画了一张图

  40张图看懂分布式追踪系统原理与实践

  如图所示,一个订单的完整请求就是一个trace。显然,对于这个请求,必须有一个全局标识符来标识这个请求。每个调用都称为一个 Span,每个调用都必须随身携带。全局 TraceId,使全局 TraceId 可以与每个调用关联。这个 TraceId 是通过 SpanContext 传输的。由于传输显然需要遵循协议来调用。如图,我们把transport protocol比作汽车,SpanContext比作货物,Span比作道路应该更好理解。

  了解了这三个概念后,再看分布式追踪系统采集如何统一图中的微服务调用链

  40张图看懂分布式追踪系统原理与实践

  我们可以看到底部有一个 Collector 一直在默默的采集数据,那么每次调用 Collector 会采集到哪些信息。

  global trace_id:这很明显,以便每个子调用都可以与原创请求相关联

  span_id: 图中的0, 1, 1.1, 2,这样就可以识别是哪个调用了

  parent_span_id:比如b调用d的span_id是1.1,那么它的parent_span_id就是a调用b的span_id,也就是1,这样就可以关联两个相邻的调用。

  有了这些信息, Collector 每次调用采集的信息如下

  40张图看懂分布式追踪系统原理与实践

  基于这些图表信息,很明显可以绘制出调用链的可视化视图如下

  

  40张图看懂分布式追踪系统原理与实践

  这样就实现了一个完整的分布式跟踪系统。

  上面的实现看起来真的很简单,但是有以下几个问题需要我们仔细思考

  如何自动采集跨越数据:自动采集,不侵入业务代码

  如何跨进程传递上下文

  traceId 如何保证全局唯一

  这么多请求采集会不会影响性能

  接下来,让我看看SkyWalking是如何解决以上四个问题的

  SkyWalking原理及架构设计如何自动采集跨数据

  SkyWalking采用插件+javaagent的形式实现自动跨度数据采集,可以对代码无干扰,插件意味着可插拔,扩展性好(我们将介绍如何定义自己的插件)

  40张图看懂分布式追踪系统原理与实践

  如何跨进程传递上下文

  我们知道数据一般分为header和body,就像http有header和body一样,RocketMQ也有MessageHeader、Message Body,body一般都保存业务数据,所以不宜在body中传递context,而是在header中,如图

  40张图看懂分布式追踪系统原理与实践

  dubbo中的attachment相当于header,所以我们把context放在attachment里面,解决了context传输的问题。

  40张图看懂分布式追踪系统原理与实践

  提示:这里的上下文传递过程由dubbo插件处理,业务不知情。下面将分析这个插件是如何实现的。

  traceId 如何保证全局唯一

  为了确保全局唯一性,我们可以使用分布式或本地生成的 ID。如果你使用分布式,你需要有一个发件人。每次发出请求时,都必须先请求发件人。会有网络调用开销,所以 SkyWalking 最终采用了本地生成 ID 的方法,并且采用了著名的雪流算法,具有很高的性能。

  40张图看懂分布式追踪系统原理与实践

  图:雪花算法生成的id

  但是雪花算法有一个众所周知的问题:时间回溯,会导致产生重复的id。那么 SkyWalking 是如何解决时间回调问题的呢?

  40张图看懂分布式追踪系统原理与实践

  每次生成 id 时,都会记录生成 id 的时间(lastTimestamp)。如果发现当前时间小于上次生成id的时间(lastTimestamp),则表示发生了时间回调,会生成一个随机数作为traceId。这里可能有一些同学想认真一点,他们可能会觉得生成的随机数也会和生成的全局id重复。最好加一层验证。

  这里我想谈谈系统设计中方案的选择。首先,如果对生成的随机数进行唯一性验证,无疑会多出一层调用,会有一定的性能损失,但实际上时间回调的概率很小。(发生后,由于机器时间的混乱,业务会受到很大的影响,所以机器时间的调整一定要谨慎),而且生成的随机数重叠的概率也很小,考虑到有真的没必要再增加一个Layer全局唯一性检查。对于技术方案的选择,必须避免过度设计。

  有这么多请求,所有 采集 都会影响性能吗?

  如果每次请求都调用采集,毫无疑问数据量会很大,但是反过来想,真的有必要对每个请求都调用采集吗?实际上,没有必要。我们可以设置采样频率,只对部分数据进行采样。SkyWalking默认设置为3秒内采样3次,其余请求不采样,如图

  40张图看懂分布式追踪系统原理与实践

  这个采样频率其实已经足够我们分析元器件的性能了。以这种在 3 秒内采样 3 次的频率采样数据有什么问题?理想情况下,每次服务调用都在同一个时间点(如下图),所以每次都在同一个时间点采样是可以的

  40张图看懂分布式追踪系统原理与实践

  但是在生产中,基本上不可能每个服务调用在同一个时间点被调用,因为网络调用存在延迟等,实际调用情况很可能如下

  40张图看懂分布式追踪系统原理与实践

  在这种情况下,会在服务 A 上采样一些调用,而不会在服务 B 和 C 上采样,因此无法分析调用链的性能,那么 SkyWalking 是如何解决的。

  是这样解决的:如果上游携带Context(表示上游已经采样),下游强制采集数据。这确保了链接是完整的。

  SkyWalking 的基础设施

  SkyWalking的基本结构如下。可以说,几乎所有的分布式调用都是由以下组件组成的

  40张图看懂分布式追踪系统原理与实践

  首先当然是对节点数据的定期采样。采样后,数据会定期上报,并存储在 ES、MySQL 等持久层中。有了数据,自然要根据数据进行可视化分析。

  SkyWalking 的表现如何?

  接下来大家一定比较关心SkyWalking的表现,那么我们来看看官方的评测数据

  40张图看懂分布式追踪系统原理与实践

  图中蓝色代表不使用 SkyWalking 的性能,橙色代表使用 SkyWalking 的性能。以上是TPS为5000时测得的数据,可以看出无论是CPU、内存还是响应时间,使用SkyWalking与性能损失几乎可以忽略不计。

  接下来我们看一下SkyWalking与另一个著名的分布式追踪工具Zipkin和Pinpoint的对比(对比是在采样率为每秒1次,线程数为500,总请求数为5000时进行的) )。看到在关键响应时间上,Zipkin (117ms)、PinPoint (201ms) 远不如 SkyWalking (22ms)!

  

  40张图看懂分布式追踪系统原理与实践

  在性能损失方面,SkyWalking 胜出!

  我们再看另一个指标:代码的侵入性如何,ZipKin需要埋在应用程序中,代码的侵入性强,而SkyWalking使用javaagent+插件修改字节码。代码没有入侵。SkyWaking除了具有良好的性能和代码侵入性外,还有以下优点:

  我司对分布式调用链SkyWalking在我司应用架构的实践

  从上面可以看出,SkyWalking 有很多优点,那么我们使用它的所有组件了吗?事实上,事实并非如此。我们来看看它在我们公司的应用架构。

  [图片上传失败...(image-d5afda-81)]

  从图中可以看出,我们只使用了SkyWalking的agent进行采样,而放弃了“数据上报与分析”、“数据存储”、“数据可视化”这三个组件,那为什么不直接使用整套SkyWalking的解决方案,因为在SkyWalking接入之前我们的Marvin监控生态系统是比较完善的,如果我们用SkyWalking来代替,就没有必要了。Marvin在大部分场景下都能满足我们的需求,二来系统更换成本高,三来如果用户重连,学习成本高。

  这也给了我们一个启示:任何产品抓住机会都是非常重要的,后续产品的更新换代成本会非常高。抓住机会,也就是抓住用户的心,就像微信一样,虽然UI在功能上做的很好,但是在国外还是和whatsapp一样可以做的,因为第一个机会已经没有了。

  另一方面,对于架构来说,没有最好,只有最适合,结合当前业务场景平衡折中是架构设计的精髓。

  我们公司对SkyWalking做了哪些改造和实践

  我公司主要做了以下改造和实践

  预发布环境因调试需要强制采样

  实施更细粒度的抽样?

  在日志中嵌入 traceId

  自研SkyWalking插件

  预发布环境因调试需要强制采样

  从上面的分析可以看出,Collector 在后台定时采样。那不是很好吗?为什么我们需要实施强制采样?还是为了排查定位问题,有时候网上有问题,我们希望在预发布中复现,希望看到这个请求的完整调用链,所以需要在预发布中实现强制采样-发布。所以我们修改了Skywalking的dubbo插件来实现强制采样

  我们为请求的 cookie 带来一个类似 force_flag = true 的键值对,以表明我们想要强制采样。网关收到这个cookie后,会在dubbo的附件中带上force_flag = true这个键值对,然后skywalking的dubbo插件就可以根据这个判断是否是强制采样。如果有这个值,就是强制采样。如果没有这个值,就会进行正常的定时采样。

  40张图看懂分布式追踪系统原理与实践

  实施更细粒度的抽样?

  哈,细粒度的采样。我们来看看skywalking默认的采样方式,即统一采样。

  40张图看懂分布式追踪系统原理与实践

  我们知道这个方法默认是在3秒内采样前3次,其他请求都被丢弃。在这种情况下有一个问题。假设这台机器3秒内有多个dubbo、mysql、redis调用,但是如果前3次调用都是dubbo调用,就不能采样mysql、redis等其他调用,所以我们有修改skywalking实现分组采样,如下

  40张图看懂分布式追踪系统原理与实践

  也就是说redis、dubbo、mysql等的采样在3秒内进行了3次,就避免了这个问题。

  如何在日志中嵌入 traceId?

  在输出日志中嵌入traceId,方便我们排查问题,所以打印出traceId是很有必要的。如何将 traceId 嵌入到日志中?我们正在使用 log4j。这里我们需要了解一下log4j的插件机制。log4j 允许我们自定义插件来输出日志的格式。首先,我们需要定义日志的格式,并在自定义日志格式中嵌入 %traceId。位字符,如下

  40张图看懂分布式追踪系统原理与实践

  然后我们实现一个log4j插件,如下

  40张图看懂分布式追踪系统原理与实践

  首先log4j插件需要定义一个类,这个类要继承LogEventPatternConverter类,并使用标准Plugin将自己声明为Plugin,通过@ConverterKeys注解指定要替换的占位符,然后替换在格式方法。失去。这样,我们想要的TraceId就会出现在日志中,如下

  图像.png

  我们公司开发了哪些skywalking插件?

  SkyWalking 已经实现了很多插件,但是没有提供 memcached 和 druid 的插件,所以我们按照他们的规范开发了这两个插件。

  40张图看懂分布式追踪系统原理与实践

  插件是如何实现的?可以看出主要由三部分组成

  插件定义类:指定插件的定义类,最后会根据这里的定义类打包生成插件

  Instrumentation:指定切线,切线,以及增强哪个类的哪个方法

  *敏*感*词*,指定第2步。在方法之前、方法之后或异常中编写增强逻辑很重要。

  可能你看完还是不明白,下面就用dubbo插件简单解释一下。我们知道,在dubbo服务中,每个请求都会收到来自netty的消息,提交给业务线程池处理,到真正调用业务方法时结束。中间经过了十几个Filter的处理

  40张图看懂分布式追踪系统原理与实践

  MonitorFilter可以拦截所有客户端请求或者服务器处理请求,所以我们可以在调用invoke方法之前增强MonitorFilter,将全局traceId注入到其Invocation的附件中,从而保证请求到达真正的全局traceId存在于业务逻辑之前。

  所以很明显我们需要在插件中指定我们要增强的类(MonitorFilter),增强它的方法(invoke),这个方法应该做哪些增强,这就是*敏*感*词*(Inteceptor)要做的,我们看Instrumentation在 Dubbo 插件(DubboInstrumentation)中

  40张图看懂分布式追踪系统原理与实践

  我们来看看代码中描述的*敏*感*词*是做什么的。下面列出了关键步骤。

  40张图看懂分布式追踪系统原理与实践

  首先,beforeMethod表示这里的方法会在执行MonitorFilter的invoke方法之前被调用,与之对应的是afterMethod,表示增强逻辑是在执行完invoke方法之后执行的。

  其次,从第2点和第3点我们可以看出,无论是consumer还是provider,都会对其全局ID进行相应的处理,从而保证到达真实业务层时全局traceid是可用的。定义 Instrumentation 和 Interceptor 后,最后一步是在 skywalking.def 中指定定义的类

  // skywalking-plugin.def 文件 dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation

  这样封装的插件会增强MonitorFilter的invoke方法,并在invoke方法执行前将全局traceId注入到附件中,这些都是无声无息的,对代码无侵入性。

  总结

  本文由浅入深介绍分布式跟踪系统的原理。相信大家对它的功能和工作机制都有很深的了解。特别需要注意的是,某项技能的引入一定要结合现有的技术架构做出最合理的选择,就像SkyWalking有四个模块一样,我司只使用它的代理采样功能,没有最好的技术,只有最适合的技术,通过这篇文章,相信大家应该对SkyWalking的实现机制有了更清晰的认识,本文只介绍了SkyWalking插件的实现,但毕竟是工业级软件。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线