gitweixin
  • 首页
  • 小程序代码
    • 资讯读书
    • 工具类
    • O2O
    • 地图定位
    • 社交
    • 行业软件
    • 电商类
    • 互联网类
    • 企业类
    • UI控件
  • 大数据开发
    • Hadoop
    • Spark
    • Hbase
    • Elasticsearch
    • Kafka
    • Flink
    • 数据仓库
    • 数据挖掘
    • flume
    • Kafka
    • Hive
    • shardingsphere
    • solr
  • 开发博客
    • Android
    • php
    • python
    • 运维
    • 技术架构
    • 数据库
  • 程序员网赚
  • bug清单
  • 量化投资
  • 在线查询工具
    • 去行号
    • 在线时间戳转换工具
    • 免费图片批量修改尺寸在线工具
    • SVG转JPG在线工具

年度归档2025

精品微信小程序开发门户,代码全部亲测可用

  • 首页   /  
  • 2025
  • ( 页面13 )
Flink 1月 22,2025

Flink1.7官方文档中文翻译:有状态流处理

什么是状态?#
虽然数据流中的许多操作通常一次仅处理单个事件(例如事件解析器),但有些操作会在多个事件间记住相关信息(例如窗口操作符)。这些操作被称为有状态操作。
有状态操作的一些示例:

  • 当应用程序搜索特定的事件模式时,状态会存储到目前为止遇到的事件序列。
  • 按分钟 / 小时 / 天聚合事件时,状态保存待处理的聚合结果。
  • 在一系列数据点上训练机器学习模型时,状态保存模型参数的当前版本。
  • 当需要管理历史数据时,状态允许高效访问过去发生的事件。

Flink 需要了解状态,以便使用检查点和保存点实现容错。
了解状态还有助于对 Flink 应用程序进行重新缩放,这意味着 Flink 会负责在并行实例间重新分配状态。
可查询状态允许你在运行时从 Flink 外部访问状态。
在处理状态时,了解 Flink 的状态后端可能也会有所帮助。Flink 提供了不同的状态后端,用于指定状态的存储方式和存储位置。

键控状态 #
键控状态维护在一个可视为嵌入式键值存储的结构中。状态与有状态操作符读取的流严格分区并一起分布。因此,仅在键控流上才能访问键值状态,即在进行键控 / 分区数据交换之后,并且只能访问与当前事件的键相关联的值。将流的键与状态的键对齐,可确保所有状态更新都是本地操作,无需事务开销即可保证一致性。这种对齐还使 Flink 能够透明地重新分配状态并调整流分区。

状态与分区

键控状态进一步组织为所谓的键组。键组是 Flink 重新分配键控状态的基本单元;键组的数量与定义的最大并行度完全相同。在执行过程中,键控操作符的每个并行实例处理一个或多个键组的键。

State and Partitioning

状态持久性#

Flink 通过流重放和检查点相结合的方式实现容错。一个检查点标记每个输入流中的特定点,以及每个操作符的相应状态。通过恢复操作符的状态并从检查点处重新播放记录,流数据流可以从检查点恢复,同时保持一致性(精确一次处理语义)。
检查点间隔是在执行期间容错开销与恢复时间(需要重新播放的记录数)之间进行权衡的一种方式。
容错机制持续对分布式流数据流进行快照。对于状态较小的流应用程序,这些快照非常轻量级,可以频繁进行,而对性能影响不大。流应用程序的状态存储在可配置的位置,通常是分布式文件系统中。
如果程序发生故障(由于机器、网络或软件故障),Flink 会停止分布式流数据流。然后系统重新启动操作符,并将它们重置到最近一次成功的检查点。输入流被重置到状态快照的位置。作为重新启动的并行数据流一部分处理的任何记录,都保证不会影响先前检查点的状态。
默认情况下,检查点功能是禁用的。有关如何启用和配置检查点的详细信息,请参阅 “检查点”。
为使此机制充分发挥其保证作用,数据流源(如消息队列或代理)需要能够将流倒回到最近定义的点。Apache Kafka 具备此能力,Flink 与 Kafka 的连接器利用了这一点。有关 Flink 连接器提供的保证的更多信息,请参阅 “数据源和接收器的容错保证”。
由于 Flink 的检查点是通过分布式快照实现的,我们可互换使用 “快照” 和 “检查点” 这两个词。通常我们也用 “快照” 一词来指代检查点或保存点。

检查点#

Flink 容错机制的核心部分是对分布式数据流和操作符状态进行一致性快照。这些快照作为一致性检查点,系统在发生故障时可以回退到这些检查点。Flink 进行这些快照的机制在《分布式数据流的轻量级异步快照》中有描述。它受标准的 Chandy – Lamport 分布式快照算法启发,并专门针对 Flink 的执行模型进行了定制。
请记住,与检查点相关的所有操作都可以异步完成。检查点屏障不会同步移动,操作可以异步对其状态进行快照。
自 Flink 1.11 起,检查点可以在有对齐或无对齐的情况下进行。在本节中,我们先描述对齐检查点。

屏障#

Flink 分布式快照中的一个核心元素是流屏障。这些屏障被注入到数据流中,并作为数据流的一部分与记录一起流动。屏障永远不会超过记录,它们严格按顺序流动。一个屏障将数据流中的记录分为进入当前快照的记录集和进入下一个快照的记录集。每个屏障携带它前面推送的快照的 ID。屏障不会中断流的流动,因此非常轻量级。来自不同快照的多个屏障可以同时存在于流中,这意味着各种快照可以并发发生。
数据流中的检查点屏障:流屏障在流源处被注入到并行数据流中。注入快照 n 的屏障的点(我们称之为 Sn)是源流中快照覆盖数据的位置。例如,在 Apache Kafka 中,这个位置将是分区中最后一条记录的偏移量。这个位置 Sn 会报告给检查点协调器(Flink 的 JobManager)。

Checkpoint barriers in data streams


然后屏障向下游流动。当一个中间操作符从其所有输入流接收到快照 n 的屏障时,它会向其所有输出流发送一个快照 n 的屏障。一旦一个接收器操作符(流 DAG 的末端)从其所有输入流接收到屏障 n,它就会向检查点协调器确认快照 n。在所有接收器都确认一个快照后,该快照被视为完成。

Aligning data streams at operators with multiple inputs


一旦快照 n 完成,作业将不再要求源提供 Sn 之前的记录,因为此时这些记录(及其衍生记录)将已经通过整个数据流拓扑。
在具有多个输入的操作符处对齐数据流:接收多个输入流的操作符需要在快照屏障上对齐输入流。上图说明了这一点:

  • 一旦操作符从传入流接收到快照屏障 n,在它也从其他输入接收到屏障 n 之前,它不能处理来自该流的任何更多记录。否则,它会将属于快照 n 的记录与属于快照 n + 1 的记录混合。
  • 一旦最后一个流接收到屏障 n,操作符会发出所有挂起的输出记录,然后自己发出快照 n 屏障。
  • 它对状态进行快照,并从所有输入流恢复处理记录,在处理来自流的记录之前先处理输入缓冲区中的记录。
  • 最后,操作符将状态异步写入状态后端。

请注意,所有具有多个输入的操作符以及在洗牌后消耗多个上游子任务输出流的操作符都需要进行对齐。

操作符状态快照#

当操作符包含任何形式的状态时,此状态也必须是快照的一部分。
操作符在从其输入流接收到所有快照屏障的时间点,并且在向其输出流发送屏障之前,对其状态进行快照。在该时间点,已经对屏障之前的记录进行了所有状态更新,并且尚未应用依赖于屏障之后记录的更新。由于快照的状态可能很大,它存储在可配置的状态后端中。默认情况下,这是 JobManager 的内存,但对于生产使用,应配置分布式可靠存储(如 HDFS)。在状态存储之后,操作符确认检查点,向输出流发送快照屏障,然后继续执行。
生成的快照现在包含:

  • 对于每个并行流数据源,启动快照时流中的偏移量 / 位置。
  • 对于每个操作符,指向作为快照一部分存储的状态的指针。

检查点机制图示

Illustration of the Checkpointing Mechanism

恢复#

在此机制下的恢复很简单:发生故障时,Flink 选择最新完成的检查点 k。然后系统重新部署整个分布式数据流,并为每个操作符提供作为检查点 k 一部分进行快照的状态。源被设置为从位置 Sk 开始读取流。例如在 Apache Kafka 中,这意味着告诉消费者从偏移量 Sk 开始获取数据。
如果状态是增量快照的,操作符从最新的完整快照状态开始,然后对该状态应用一系列增量快照更新。
有关更多信息,请参阅 “重启策略”。

非对齐检查点#

检查点也可以以非对齐方式执行。基本思想是,只要飞行中的数据成为操作符状态的一部分,检查点就可以超过所有飞行中的数据。
请注意,这种方法实际上更接近 Chandy – Lamport 算法,但 Flink 仍然在源中插入屏障,以避免使检查点协调器过载。
非对齐检查点:该图展示了一个操作符如何处理非对齐检查点屏障:

  • 操作符对存储在其输入缓冲区中的第一个屏障做出反应。
  • 它立即通过将屏障添加到输出缓冲区的末尾,将其转发到下游操作符。
  • 操作符标记所有被超过的记录以异步存储,并创建自己状态的快照。
  • 因此,操作符仅短暂停止输入处理以标记缓冲区、转发屏障并创建其他状态的快照。

非对齐检查点确保屏障尽快到达接收器。它特别适用于至少有一个缓慢移动数据路径的应用程序,在这种情况下对齐时间可能长达数小时。但是,由于它会增加额外的 I/O 压力,当到状态后端的 I/O 成为瓶颈时,它并无帮助。有关其他限制,请参阅操作中的更深入讨论。
请注意,保存点始终是对齐的。

非对齐恢复#

在非对齐检查点中,操作符在开始处理来自上游操作符的任何数据之前,首先恢复飞行中的数据。除此之外,它执行与对齐检查点恢复期间相同的步骤。

状态后端#

键 / 值索引存储的确切数据结构取决于所选的状态后端。一种状态后端将数据存储在内存哈希表中,另一种状态后端使用 RocksDB 作为键值存储。除了定义保存状态的数据结构之外,状态后端还实现了对键值状态进行时间点快照并将该快照作为检查点一部分存储的逻辑。可以在不更改应用程序逻辑的情况下配置状态后端。
检查点和快照

checkpoints and snapshots

保存点#

所有使用检查点的程序都可以从保存点恢复执行。保存点允许在不丢失任何状态的情况下更新程序和 Flink 集群。
保存点是手动触发的检查点,它对程序进行快照并将其写入状态后端。它们依赖于常规的检查点机制来实现这一点。
保存点与检查点类似,不同之处在于它们由用户触发,并且在新的检查点完成时不会自动过期。为了正确使用保存点,了解检查点与保存点之间的区别非常重要,“检查点与保存点” 中对此进行了描述。

精确一次与至少一次#

对齐步骤可能会给流程序增加延迟。通常,这种额外延迟在几毫秒量级,但我们也看到过一些异常值的延迟明显增加的情况。对于要求所有记录始终具有超低延迟(几毫秒)的应用程序,Flink 提供了一个开关,可在检查点期间跳过流对齐。一旦操作符从每个输入看到检查点屏障,仍会立即进行检查点快照。
当跳过对齐时,即使在检查点 n 的一些检查点屏障到达后,操作符仍会继续处理所有输入。这样,在为检查点 n 拍摄状态快照之前,操作符也会处理属于检查点 n + 1 的元素。在恢复时,这些记录将作为重复项出现,因为它们既包含在检查点 n 的状态快照中,又将作为检查点 n 之后的数据的一部分被重新播放。
仅对于具有多个前驱(连接)的操作符以及具有多个发送者(在流重新分区 / 洗牌之后)的操作符才会发生对齐。因此,仅包含易于并行的流操作(map ()、flatMap ()、filter () 等)的数据流实际上即使在至少一次模式下也能提供精确一次的保证。

批处理程序中的状态与容错#

Flink 将批处理程序作为流程序的一种特殊情况执行,其中流是有界的(元素数量有限)。DataSet 在内部被视为数据流。因此,上述概念同样适用于批处理程序,与适用于流程序的方式相同,但有一些小的例外:

  • 批处理程序的容错不使用检查点。恢复通过完全重放流来实现。这是可行的,因为输入是有界的。这将成本更多地推向恢复阶段,但使常规处理更便宜,因为它避免了检查点。
  • DataSet API 中的有状态操作使用简化的内存 / 外存数据结构,而不是键 / 值索引。
  • DataSet API 引入了特殊的同步(基于超步)迭代,这仅在有界流上才可行。有关详细信息,请查看迭代文档。
作者 east
Flink 1月 22,2025

Flink1.7文档 时间表函数

时间表函数提供了在特定时间点访问时间表版本的功能。为了访问时间表中的数据,必须传递一个时间属性,该属性确定返回的表的版本。Flink 使用表函数的 SQL 语法来提供这种访问方式。

与版本化表不同,时间表函数只能在追加-only 流上定义——它不支持变更日志输入。此外,时间表函数不能通过纯 SQL DDL 来定义。

定义时间表函数

时间表函数可以使用 Table API 在追加-only 流上定义。表会注册一个或多个键列,以及用于版本控制的时间属性。

假设我们有一个追加-only 的货币汇率表,我们希望将其注册为时间表函数。

SELECT * FROM currency_rates; 
update_timecurrencyrate
09:00:00Yen102
09:00:00Euro114
09:00:00USD1
11:15:00Euro119
11:49:00Pounds108

使用 Table API,我们可以使用 currency 作为键,并将 update_time 作为版本时间属性来注册该流。

Java 示例:

TemporalTableFunction rates = tEnv
    .from("currency_rates")
    .createTemporalTableFunction("update_time", "currency");
 
tEnv.createTemporarySystemFunction("rates", rates);      

时间表函数连接

定义时间表函数后,它可以作为标准表函数使用。追加-only 表(左输入/探测方)可以与时间表(右输入/构建方)连接,即一个随着时间变化并跟踪其变化的表,用于在特定时间点获取某个键的值。

考虑一个追加-only 表 orders,它跟踪客户的订单并使用不同的货币。

SELECT * FROM orders; 
order_timeamountcurrency
10:152Euro
10:301USD
10:3250Yen
10:523Euro
11:045USD

给定这些表,我们希望将订单转换为一种统一的货币——美元(USD)。

SQL 查询:

SELECT
  SUM(amount * rate) AS amount
FROM
  orders,
  LATERAL TABLE (rates(order_time))
WHERE
  rates.currency = orders.currency
作者 east
前端 1月 18,2025

在浏览器网页编辑器批量替换关键词

特别是在AIGC时代,复制大模型生成的内容粘贴在浏览器的网页编辑器上,需要修改某个格式,替换某些关键词,可以用下面的方法实现替换,而不用借助文本编辑器。

  1. 右键点击网页,选择 “检查” 或 “Inspect” 进入开发者工具。
  2. 转到 Console 标签。
  3. 输入allow pasting
  4. 使用以下代码来替换页面中的特定文本:

javascriptCopy Codedocument.body.innerHTML = document.body.innerHTML.replace(/旧词/g, ‘新词’);

通过替换旧词和新词的部分,批量修改网页中的文本。

作者 east
面试 1月 18,2025

大数据大厂校招网申入口最全集合和2025年校园招聘时间线

​

 2025年校园招聘时间线

一、2024年12月 – 2025年2月(寒假及寒假实习申请阶段)

  1. 自我评估
    • 这一阶段的首要任务是深刻地进行自我剖析。要清晰地明确自己的职业目标,比如是向往金融行业的高薪高职,还是渴望在教育领域实现育人梦想。同时,精准地确定个人优势所在,是擅长逻辑思维、具备出色的沟通能力,还是有着扎实的专业知识基础等。在此基础上,确定自己想要涉足的行业以及与之相匹配的岗位类型。例如,如果个人对市场动态有着敏锐的洞察力且具备一定的创新思维,那么市场营销类岗位可能就比较适合,像互联网公司的市场专员或者传统企业的品牌推广岗位等。
  2. 简历撰写
    • 简历是求职的敲门砖,所以要根据自己的过往经历和所掌握的技能精心制作或者更新一份专业简历。在撰写过程中,务必确保简历简洁明了,避免冗长复杂的表述。将重点内容,如重要的项目经验、获得的奖项、与目标岗位相关的技能证书等突出展示。例如,如果是应聘程序员岗位,就把自己参与过的软件开发项目,包括项目名称、担任的角色、项目成果等清楚地罗列出来。
  3. 实习申请
    • 积极寻找寒假实习机会是非常关键的,尤其要关注那些与自己未来职业方向相关的企业。这个时期很多企业会提供一些短期但富有价值的实习岗位。例如,金融企业可能会有一些针对市场调研或者客户关系管理的实习项目。寒假实习是为未来的正式求职积累经验的大好时机,通过在实习中的实际操作和与同事的交流合作,可以更好地了解行业动态和企业需求。

二、2025年3月 – 5月(暑期实习申请阶段)

  1. 技能提升
    • 按照目标职位的要求,有针对性地提升自己的技能水平。例如,如果目标是成为一名数据分析师,就需要深入学习数据分析工具,像Python语言中的Pandas和Matplotlib库,用于数据处理和可视化。还可以报名参加相关的培训课程,这些课程由专业的讲师授课,能够系统地传授知识和技能;或者利用丰富的在线学习资源,如在Coursera、Udemy等平台上有许多优质的课程可供选择。
  2. 模拟面试
    • 面试能力对于求职成功与否起着至关重要的作用。要练习常见的面试问题,例如自我介绍、职业规划、优缺点等问题。
  3. 暑期实习网申
    • 暑期实习的含金量通常较高,在这个时候要积极地向心仪的企业投递简历,争取获得实习机会。很多企业在暑期会招聘大量实习生,这些实习岗位往往能够让学生深入了解企业的业务流程和文化氛围。比如大型互联网企业的产品运营实习岗位,可以让实习生参与到产品的策划、推广等各个环节,为后续的秋招打下坚实的基础。

三、2025年6月 – 7月(秋招提前批阶段)

  1. 保持联系
    • 对于之前实习过的公司要定期进行沟通交流。因为在实习过程中,企业可能对实习生有了更深入的了解,存在转正的机会;或者内部可能会有其他适合的岗位推荐给实习生。例如,在实习公司表现优秀的同学可能会被推荐到公司的其他部门担任更高级别的工作岗位。
  2. 准备测评
    • 不同企业有着不同的测评系统,需要仔细熟悉这些测评系统的类型和要求。例如,有些企业会采用心理测评来考察应聘者的性格特点和职业适应性,有些则会进行专业知识测评。针对这些不同的测评类型要进行有针对性的练习,比如通过做历年真题、模拟测评等方式来提高通过测评的概率。
  3. 秋招提前批申请
    • 部分互联网大厂会在6 – 7月这个时间段开启秋招提前批招聘,尤其是技术类岗位比较集中。比如阿里巴巴、腾讯等公司的部分研发岗位会提前开放申请。求职者要及时关注这些企业的官方网站、社交媒体账号等渠道发布的招聘信息,并及时提交申请,以免错过机会。

四、2025年8月 – 10月(秋招正式批阶段)

  1. 广泛撒网
    • 在“金九银十”的求职高峰期,要积极地向各类企业投递简历。不仅要关注热门的软件行业,像软件开发、软件测试等岗位;还要涉足硬件行业,如电子产品的研发、生产管理等岗位;机械行业,例如机械设计、自动化控制等岗位;医药行业,包括医药研发、药品销售等岗位等。通过广泛投递简历,增加获得面试机会的可能性。
  2. 校园招聘
    • 要积极参与学校组织的招聘会、宣讲会等活动。在这些活动中,可以直接与企业的人力资源专员面对面交流,了解企业的发展前景、岗位需求等情况。同时,还能够现场投递简历,给人一种积极主动的印象。
  3. 笔试准备
    • 针对不同公司的笔试特点做好充分的准备。不同企业的笔试内容差异较大,例如科技公司可能会注重数学题、逻辑推理题以及编程挑战等方面的考核;而传统企业可能会考察一些专业知识、英语水平以及综合素质等方面的内容。可以通过收集历年真题、参加笔试培训等方式来提高笔试成绩。

五、2025年9月 – 11月(银行、地产等行业秋招高峰阶段)

  1. 特定行业准备
    • 对于银行、房地产、能源石化等行业的秋招,要特别留意其特殊要求。银行招聘可能会涉及到金融知识测试,要求应聘者掌握基本的金融理论和金融市场知识;房地产企业的招聘可能会有案例分析类的题目,考察应聘者的市场分析、项目管理等能力;能源石化企业可能会注重应聘者的安全知识和相关工程知识的掌握情况。所以,针对这些特殊要求要进行有针对性的学习和准备。
  2. 多渠道获取信息
    • 除了关注企业的官方网站获取招聘信息之外,还可以通过社交媒体平台,如领英(LinkedIn)、微博等;求职论坛,如智联招聘论坛、前程无忧论坛等途径获取最新的招聘信息。这样可以确保不会遗漏任何一个潜在的求职机会。

六、2025年10月 – 12月(秋招Offer发放期阶段)

  1. 面试强化
    • 一旦收到面试通知,就要迅速投入到面试的准备工作中。复习常见问题的答案,如在面试中经常会被问到的职业规划问题,要制定出一个合理、清晰的发展路径;同时准备好具体的工作场景案例,例如在应聘项目经理岗位时,要能够讲述一个自己在团队管理、项目进度控制等方面的实际案例。
  2. 决策制定
    • 当收到多个offer时,要仔细比较各个offer的各项条件,包括薪资待遇、职业发展机会、工作环境等因素。做出最适合自己的选择,权衡短期利益和长期发展之间的关系。

七、2025年11月末 – 12月(秋招补录/春招提前批阶段)

  1. 把握最后机会
    • 注意一些企业在秋招末期可能会提供的补录机会,这些机会可能是由于之前录用的同学放弃或者其他原因而空出来的。同时,也要关注提前开放的春招岗位,这些岗位可能会竞争相对较小,而且对于一些在秋招中未成功求职的同学来说是新的机会。
  2. 总结反思
    • 回顾整个求职过程中的得失,分析自己在各个环节中的优点和不足之处。例如,在简历撰写方面是否存在问题,在面试过程中是否有哪些回答得不好的地方等。通过总结反思,为即将到来的春招做好更充分的准备,在春招中能够更加游刃有余地应对各种挑战。

大数据大厂校招网申入口最全集合

企业招聘地址面试题
字节跳动字节跳动校园招聘官网|字节跳动校招字节跳动后端或大数据基础知识面试题及参考答案(2万字长文)大厂面试:字节大数据面试题及参考答案(10万字长文持续更新)
腾讯首页 | 腾讯校招腾讯大数据开发面试题及参考答案(4万字长文-持续更新)
微众银行 微众银行 – 校园招聘 腾讯微众银行大数据面试题(包含数据分析/挖掘方向)面试题及参考答案
阅文集团 阅文集团_招聘官网 阅文集团大数据面试题及参考答案
微信 首页 | 腾讯校招 腾讯微信大数据面试题及参考答案 腾讯数据分析面试题及参考答案 
阿里巴巴 https://campus.alibaba.com阿里巴巴集团招聘官网 阿里大数据面试题集锦及参考答案(3万字长文:持续更新)
百度 百度校园招聘 百度大数据开发面试题集锦及参考答案(持续更新)
度小满 度小满2025校园招聘 度小满大数据面试题及参考答案
美团 美团招聘 美团大数据开发最新最全面试题及参考答案(持续更新)
京东  京东校招 大厂面经:京东大数据面试题及参考答案(3万字长文)
网易 网易校园招聘 2024年最全网易大数据面试题及参考答案(3万字长文持续更新)
新浪 新浪集团 – 校园招聘 新浪微博大数据面试题及参考答案(数据开发和数据分析)
滴滴出行 滴滴快的官方招聘 滴滴数据分析80道面试题及参考答案
货拉拉 深圳依时货拉拉科技有限公司 – 校园招聘 货拉拉数据分析面试题及参考答案 货拉拉大数据面试题及参考答案(3万字长文) 
小鹏 加入小鹏汽车 小鹏汽车大数据面试题及参考答案
小红书 小红书 大厂面试:小红书大数据面试题及参考答案(3万字长文)
知乎 知乎 – 校园招聘 知乎大数据开发面试题及参考答案   
唯品会 唯品会(中国)有限公司 – 校园招聘 唯品会大数据面试题及参考答案(3万字长文)
希音 SHEIN careers 希音(Shein)大数据面试题及参考答案
虾皮 Shopee 校园招聘  虾皮Shopee大数据面试题及参考答案
快手 快手校招 5万字长文吃透快手大数据面试题及参考答案(持续更新)
携程 携程集团 – 校园招聘 2024年携程大数据开发面试题及参考答案
去哪儿 北京趣拿软件科技有限公司 – 校园招聘 去哪儿大数据面试题及参考答案
OPPO OPPO招聘 – 加入我们 join us OPPO 数据分析面试题及参考答案
小米 小米校园招聘 大厂面试:小米大数据面试题大全及参考答案(130+面试题 12万长文)
VIVO vivo招聘
海康 校园招聘 海康大数据面试题及参考答案
宁德时代 宁德时代校招 | 宁德时代社招 | 宁德时代招聘官网 宁德时代大数据面试题及参考答案(2万字长文)
TCL 校园招聘 TCL大数据面试题及参考答案
科大讯飞 科大讯飞校园招聘 科大讯飞大数据面试题及参考答案
B站 哔哩哔哩-招聘 B站(哔哩哔哩/bilibili)大数据面试题及参考答案(3万字长文)
斗鱼 斗鱼招聘官方网站 斗鱼大数据面试题及参考答案
脉脉 加入脉脉 脉脉大数据面试题及参考答案(2万字长文)
水滴 水滴招聘 水滴大数据面试题及参考答案(2万字长文)
作业帮 作业帮教育科技(北京)有限公司 – 校园招聘 作业帮大数据面试题及参考答案
汇量科技 Mobvista | 加入我们 汇量科技大数据面试题及参考答案
昆仑万维 昆仑万维校园招聘 昆仑万维大数据面试题及参考答案
米哈游 miHoYo招聘官网 米哈游大数据面试题及参考答案
4399 4399游戏2025届校园招聘 4399大数据面试题及参考答案(数据分析和数据开发)
金山 金山办公软件 – 校园招聘 金山云大数据面试题及参考答案
银联 银联校园招聘 银联大数据面试题及参考答案
招商银行 招商银行招聘 招商银行大数据面试题及参考答案
富途证券 富途校园招聘 富途证券大数据面试题及参考答案
平安 中国平安校园招聘 平安科技大数据面试题及参考答案
汇丰银行 Students and graduates | HSBC Holdings plc 万字长文-汇丰银行大数据面试题(持续更新)
联通 招聘官网 联通大数据面试题及参考答案

​

作者 east
运维 1月 17,2025

selenium自动化测试,谷歌驱动器chromedriver最新版本下载(亲试有效)

在用selenium做自动化测试,用的电脑后台自动更新chrome,导致chromedriver版本跟 chrome 版本不一致。

还好官方有更新最新版,可以通过下面的地址进行下载,如果没有chrome也可以在下面一起下载。

https://googlechromelabs.github.io/chrome-for-testing/

作者 east
mysql 1月 16,2025

如何在shell脚本使用 MySQL 命令行给 SQL 文件传参

在编写 Shell 脚本或进行命令行操作时,有时需要执行包含预定义 SQL 语句的文件,并且可能希望根据不同的情况向这些 SQL 文件传递参数。这在批量处理、自动化任务或动态生成查询时特别有用。MySQL 的命令行工具提供了执行 SQL 文件的能力,但直接从命令行传递参数到 SQL 文件的功能有限。因此,我们通常会结合使用文本处理工具如 sed 来实现这一点。

使用 sed 预处理 SQL 文件

sed 是一个流编辑器,可以在不打开文件的情况下对文件内容进行各种操作,比如替换文本、插入文本等。我们可以利用 sed 在执行 SQL 文件之前修改其中的占位符,将实际的参数值写入 SQL 文件中。下面是一个简单的例子:

假设有一个名为 insertstmt.sql 的 SQL 文件,其内容如下:

INSERT INTO test.demo_table VALUES(@name, @age);

这里 @name 和 @age 是我们需要从外部传递的参数。为了实现这一点,我们可以创建一个 Shell 脚本 execute.sh,它接受两个参数并用它们来替换 yoursql.sql 中的变量:

#!/bin/sh
# 设置参数作为 SQL 变量并添加到 yoursql.sql 文件的第一行
sed -i "1 i\ SET @name='$1';" yoursql.sql
sed -i "1 i\ SET @age=$2;" yoursql.sql

# 执行 SQL 脚本
mysql -u root < yoursql.sql

# 清除 SQL 脚本中的变量设置
sed -i '1,2d' yoursql.sql

在这个脚本中,$1 和 $2 分别对应于调用脚本时提供的第一个和第二个参数。当我们运行这个脚本,例如 ./execute.sh lenmom 30,它会先修改 yoursql.sql 文件,使其看起来像这样:

SET @name='lenmom';
SET @age=30;
INSERT INTO test.demo_table VALUES(@name, @age);

然后执行该 SQL 文件,最后恢复原始状态以供下次使用。

安全性与最佳实践

虽然上述方法可以很好地工作,但在实际应用中需要注意几个方面:

  • 安全性:当构建 SQL 查询字符串时,确保对外部输入进行了适当的转义,以防止 SQL 注入攻击。
  • 错误处理:考虑加入错误处理逻辑,以便在出现问题时能够及时通知用户。
  • 日志记录:记录每次操作的日志对于追踪问题和审计非常重要。
  • 备份机制:如果直接修改了 SQL 文件,在执行前最好先创建一个副本以防万一。

实际案例分析

让我们来看一个更复杂的实例,其中涉及到数据库连接信息以及多个参数的传递。想象一下,你有一个定期更新用户信息的任务,需要每天晚上更新一次特定用户的年龄信息。你可以创建一个名为 update_user_age.sh 的 Shell 脚本来完成这项任务:

#!/bin/bash
# 数据库连接信息
DB_HOST="localhost"
DB_PORT="3306"
DB_USER="root"
DB_PASS="password"

# 用户名和新年龄作为参数传递
USER_NAME="$1"
NEW_AGE="$2"

# 更新 SQL 文件中的变量
sed -i "1 i\ USE my_database;" update_user_age.sql
sed -i "2 i\ UPDATE users SET age = $NEW_AGE WHERE username = '$USER_NAME';" update_user_age.sql

# 执行更新
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" < update_user_age.sql

# 恢复 SQL 文件
sed -i '1,2d' update_user_age.sql

此脚本首先指定了数据库连接的信息,接着接收用户名和新的年龄作为参数,并使用 sed 将这些参数插入到 update_user_age.sql 文件中。之后通过 MySQL 命令执行更新操作,最后清理临时添加的内容,保证 SQL 文件的干净。

作者 east
mysql 1月 16,2025

解决命令行mysql -e 执行长sql没结果

用
mysql -h${HOST_NAME} -P${PORT} -u${USER_NAME} ${DB_NAME} -e”${sql}” 方式来执行sql,发现执行没报错,但没有结果。而这个sql在navicat单独执行是没报错的,并且没有双引号等冲突。

在命令行中执行 SQL 时,如果 SQL 语句格式不正确,尤其是涉及到多行 SQL 语句或特殊字符时,命令行可能无法正确解析。可能的原因和解决办法:

  • 分隔符问题:如果 ${bigdata_charge_electric_hour} 包含多行或复杂的 SQL 语句,确保它是一个有效的单行语句。如果包含换行符或者特殊字符,命令行工具可能会解释错误。
  • 引号问题:如果 ${bigdata_charge_electric_hour} 中的 SQL 语句本身包含了引号(例如 ' 或 "),需要确保它们被正确转义,否则命令行会解析错误。可以使用双引号 " 来包装 SQL 查询,或者使用反斜杠转义其中的引号。

解决方法:如果 SQL 语句包含多行或者特殊字符,可以考虑将其写入一个 .sql 文件,并使用 mysql 命令执行文件:

mysql -h${HOST_NAME} -P${PORT} -u${USER_NAME} ${DB_NAME} < your_sql_file.sql 

这样可以避免命令行解析时的格式问题。

修改成上面的方式果然执行成功并且有结果了。

作者 east
python 1月 14,2025

如何利用大模型(ChatGPT)辅助编写selenium代码

方法1:提出需求让大模型编写

例如要编写selenium.webdriver 如何执行Esc返回键的功能 ,由于对这方面不太熟悉,如果查看官方文档,自己一步步试,可能要花费几个小时,可以把明确需求提示给大模型:

方法2:对网页某个元素进行操作

有些网页很复杂,需要对某个元素进行操作,不知代码如何写。可以先在网页上检查,在元素的页面找到要操作元素的定位,然后复制这些前端代码。告诉大模型具体需求,并找出这个元素进行操作。

例如下面的例子:

大模型提问:

selenium.webdriver如何关闭下面的组件:<div class=”container-SfTLY8″><div><div class=”coding-skill-title-container-rWvOE0 coding-skill-title-container gray-WtixXh”><div class=”skill-title-content-OwSt2V”><div class=”icon-wrapper-qgAPoM”><span role=”img” class=”semi-icon semi-icon-default”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” fill-rule=”evenodd” d=”M13.113 2.266a.936.936 0 0 1 .797 1.057l-2.476 17.614a.936.936 0 0 1-1.854-.26l2.476-17.615a.936.936 0 0 1 1.057-.796M6.811 6.744a.936.936 0 0 1 0 1.324l-3.55 3.55 3.55 3.551a.936.936 0 1 1-1.324 1.324l-4.213-4.212a.936.936 0 0 1 0-1.325l4.213-4.212a.936.936 0 0 1 1.324 0m15.447 4.213c.357.356.365.93.025 1.297a6.05 6.05 0 0 0-2.377-1.001l-3.185-3.185a.936.936 0 1 1 1.324-1.324zm-3.47 10.491a.48.48 0 0 0 .48-.425c.225-1.341.423-2.03.849-2.457.425-.426 1.11-.624 2.445-.849a.485.485 0 0 0 .438-.48.48.48 0 0 0-.44-.48c-1.332-.227-2.018-.425-2.443-.851-.426-.427-.624-1.115-.849-2.455a.48.48 0 0 0-.48-.428.49.49 0 0 0-.481.426c-.226 1.341-.423 2.03-.85 2.457-.424.426-1.108.624-2.44.85a.48.48 0 0 0-.442.481c0 .26.199.448.439.48 1.335.225 2.02.418 2.444.842.426.425.623 1.114.849 2.466.04.24.23.423.482.423″ clip-rule=”evenodd”></path></svg></span></div><div class=”content-yHNqH7″><div class=”title-SlDAMe”>AI 编程</div></div><div class=”middle-jf0OPw addon-before-SEgdLZ”><div class=”flex items-center”></div></div><div class=”right-gyA7ZQ”><div><div class=”close-btn-wrapper-HINk0h” data-testid=”skill_header_close_button” tabindex=”0″ aria-describedby=”bkks5ef” data-popupid=”bkks5ef”><span role=”img” class=”semi-icon semi-icon-default close-btn-svg-_cKb_A”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” d=”M5.762 18.238a.8.8 0 0 1-.234-.404 1 1 0 0 1 0-.468.85.85 0 0 1 .234-.396l4.953-4.974L5.762 7.03a.8.8 0 0 1-.226-.396 1 1 0 0 1 0-.468.84.84 0 0 1 .226-.404.86.86 0 0 1 .412-.234 1 1 0 0 1 .467 0q.233.057.404.226l4.961 4.966 4.953-4.966a.76.76 0 0 1 .404-.226.95.95 0 0 1 .46 0 .9.9 0 0 1 .419.234.84.84 0 0 1 .226.404.86.86 0 0 1 0 .468.9.9 0 0 1-.226.404l-4.953 4.958 4.953 4.966a.9.9 0 0 1 .226.412.95.95 0 0 1 0 .46.84.84 0 0 1-.226.404.86.86 0 0 1-.412.234 1 1 0 0 1-.467 0 .84.84 0 0 1-.404-.226l-4.953-4.966-4.961 4.966a.84.84 0 0 1-.404.226 1 1 0 0 1-.467 0 .86.86 0 0 1-.412-.234″></path></svg></span></div></div></div></div></div></div><div class=”editor-container-Ikyh9n”><div role=”textbox” aria-multiline=”true” autocomplete=”off” data-testid=”chat_input_input” dir=”ltr” class=”container-lGWhkH editor-h8aPs4″ data-slate-editor=”true” data-slate-node=”value” contenteditable=”true” zindex=”-1″ style=”position: relative; white-space: pre-wrap; overflow-wrap: break-word; min-height: 28px;”><div data-slate-node=”element” class=”paragraph-GvBwll”><span data-slate-node=”text”><span data-slate-leaf=”true” style=”padding-left: 0.1px;”><span data-slate-placeholder=”true” contenteditable=”false” style=”position: absolute; top: 0px; pointer-events: none; width: 100%; max-width: 100%; display: block; opacity: 0.333; user-select: none; text-decoration: none;”>粘贴代码或描述你的问题</span><span data-slate-zero-width=”n” data-slate-length=”0″><br></span></span></span></div></div></div><div><div class=”skill-bottom-X9vRY0″><div class=”flex-1 flex”><div class=”btn-vRbV5q mr-10″><div class=”upload-btn-wrapper-h2mSyQ”><div class=”” aria-haspopup=”true” tabindex=”0″ aria-describedby=”15ykpw2″ data-popupid=”15ykpw2″><button class=”semi-button semi-button-primary samantha-button-aiwXEk tertiary-kH1mvr medium-UIYozi icon-a2WxRL semi-button-with-icon” type=”button” aria-disabled=”false”><span class=”semi-button-content”><span role=”img” class=”semi-icon semi-icon-default !text-16 text-s-color-text-secondary”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” fill-rule=”evenodd” d=”M9.035 15.956a1.29 1.29 0 0 0 1.821-.004l6.911-6.911a3.15 3.15 0 0 0 0-4.457l-.034-.034a3.15 3.15 0 0 0-4.456 0l-7.235 7.234a5.031 5.031 0 0 0 7.115 7.115l6.577-6.577a1.035 1.035 0 0 1 1.463 1.464l-6.576 6.577A7.1 7.1 0 0 1 4.579 10.32l7.235-7.234a5.22 5.22 0 0 1 7.382 0l.034.034a5.22 5.22 0 0 1 0 7.383l-6.91 6.91a3.36 3.36 0 0 1-4.741.012l-.006-.005-.012-.011a3.346 3.346 0 0 1 0-4.732L12.76 7.48a1.035 1.035 0 0 1 1.464 1.463l-5.198 5.198a1.277 1.277 0 0 0 0 1.805z” clip-rule=”evenodd”></path></svg></span><span class=”semi-button-content-right” x-semi-prop=”children”><span style=”color: rgba(0, 0, 0, 0.8);”>上传文件</span></span></span></button></div></div><input type=”file” multiple=”” class=”input-Er4iXs”><input type=”file” directory=”true” mozdirectory=”true” webkitdirectory=”true” class=”input-Er4iXs”></div><div class=”btn-vRbV5q”><button class=”semi-button semi-button-primary samantha-button-aiwXEk tertiary-kH1mvr medium-UIYozi icon-a2WxRL upload-github-svg-oE359X semi-button-with-icon” type=”button” aria-disabled=”false”><span class=”semi-button-content”><span role=”img” class=”semi-icon semi-icon-default text-20 text-s-color-text-secondary”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” d=”M18.608 5.027a.83.83 0 0 0-.444-.459c-.17-.073-1.674-.65-3.912.765H9.748c-2.241-1.418-3.744-.838-3.912-.765a.84.84 0 0 0-.444.459c-.512 1.293-.353 2.665-.154 3.455-.616.823-.738 1.586-.738 2.685 0 3.474 2.483 4.45 4.428 4.81a3.7 3.7 0 0 0-.254.909 1 1 0 0 0-.007.114v.754c-.381-.08-.801-.233-1.078-.51-.939-.94-1.91-1.91-3.089-1.91V17c.488 0 1.277.788 1.91 1.422.997.997 2.522 1.08 2.997 1.08q.092 0 .127-.003a.834.834 0 0 0 .8-.832v-1.604c.083-.483.394-.969.545-1.1a.833.833 0 0 0-.451-1.457c-2.699-.308-4.261-.954-4.261-3.34 0-1.037.11-1.381.616-1.939a.84.84 0 0 0 .156-.875c-.094-.232-.367-1.278-.127-2.295.404-.031 1.17.089 2.221.8.137.093.3.143.467.143h5c.167 0 .33-.05.467-.143 1.056-.714 1.816-.816 2.22-.804.241 1.02-.03 2.066-.125 2.299a.83.83 0 0 0 .157.877c.505.553.614.898.614 1.938 0 2.394-1.561 3.037-4.259 3.338a.834.834 0 0 0-.451 1.46c.386.332.544.633.544 1.035v2.5h1.666V17c0-.4-.076-.744-.19-1.038 1.895-.373 4.357-1.39 4.357-4.795 0-1.101-.122-1.866-.738-2.686.2-.79.357-2.159-.154-3.454″></path></svg></span><span class=”semi-button-content-right” x-semi-prop=”children”><span>引入 GitHub 仓库</span></span></span></button></div></div><div class=””><div class=”container-G7o3Dk”><div class=””><div class=”flex items-center”><div class=”left-area-UbioLp”><div class=”flex gap-8″><div class=”container-KtUMxI”><div data-testid=”asr_btn” class=”mic-container-uZJexl cursor-pointer” tabindex=”0″ aria-describedby=”30rnba0″ data-popupid=”30rnba0″><span role=”img” class=”semi-icon semi-icon-default icon-mic-NfScWD”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” fill-rule=”evenodd” d=”M12 2.5A2.5 2.5 0 0 1 14.5 5v6a2.5 2.5 0 0 1-5 0V5A2.5 2.5 0 0 1 12 2.5M7.5 5a4.5 4.5 0 0 1 9 0v6a4.5 4.5 0 1 1-9 0zm-2 4a1 1 0 0 0-2 0v2c0 4.213 3.26 7.928 7.5 8.44V21H7.3a1 1 0 1 0 0 2h9.4a1 1 0 1 0 0-2H13v-1.56c4.24-.512 7.5-4.227 7.5-8.44V9a1 1 0 1 0-2 0v2c0 3.46-2.915 6.5-6.5 6.5S5.5 14.46 5.5 11z” clip-rule=”evenodd”></path></svg></span></div></div></div></div><div class=”splitLineWrapper-bVwctz”><div class=”splitLine-wCW4fL”></div></div><div class=”right-area-YZHkCa”><div class=”container-F3bkhm !hidden” data-testid=”chat_input_local_break_button” tabindex=”0″ aria-describedby=”vkk33zj” data-popupid=”vkk33zj”><span role=”img” class=”semi-icon semi-icon-default icon-eivsqq”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”none” viewBox=”0 0 24 24″><path fill=”currentColor” fill-rule=”evenodd” d=”M12 23c6.075 0 11-4.925 11-11S18.075 1 12 1 1 5.925 1 12s4.925 11 11 11m0-20a9 9 0 1 1 0 18 9 9 0 0 1 0-18m-2 5.5A1.5 1.5 0 0 0 8.5 10v4a1.5 1.5 0 0 0 1.5 1.5h4a1.5 1.5 0 0 0 1.5-1.5v-4A1.5 1.5 0 0 0 14 8.5z” clip-rule=”evenodd”></path></svg></span></div><div class=”container-e6cFq5 send-btn-wrapper coding-send-msg-button”><span class=”” tabindex=”0″ aria-describedby=”5u16go3″ data-popupid=”5u16go3″ style=”display: inline-block; cursor: not-allowed;”><button disabled=”” id=”flow-end-msg-send” aria-disabled=”true” aria-label=”发送” data-testid=”chat_input_send_button” class=”semi-button semi-button-disabled semi-button-primary-disabled send-btn-S_MjUh semi-button-with-icon semi-button-with-icon-only” type=”button” style=”pointer-events: none;”><span class=”semi-button-content”><span role=”img” class=”semi-icon semi-icon-default”><svg xmlns=”http://www.w3.org/2000/svg” width=”1em” height=”1em” fill=”currentColor” viewBox=”0 0 28 28″><path d=”M14.007 28q-2.881 0-5.418-1.11a14.3 14.3 0 0 1-4.453-3.026 14.5 14.5 0 0 1-3.04-4.453Q0 16.875 0 13.993q0-2.868 1.095-5.404Q2.191 6.053 4.121 4.12A14.5 14.5 0 0 1 8.59 1.095Q11.124 0 13.993 0t5.404 1.095q2.536 1.096 4.467 3.026A14.2 14.2 0 0 1 26.89 8.59Q28 11.124 28 13.993q0 2.881-1.095 5.418a14.3 14.3 0 0 1-3.027 4.453 14.2 14.2 0 0 1-4.467 3.026Q16.876 28 14.007 28m.015-6.917q.518 0 .835-.317.332-.332.332-.836v-6.816l-.13-2.969 1.37 1.672 1.599 1.643q.316.33.807.331.475 0 .792-.303a.99.99 0 0 0 .332-.763q0-.475-.332-.807L14.944 7.22q-.433-.447-.922-.447-.476 0-.908.447L8.43 11.918q-.317.317-.317.807 0 .461.317.763.318.303.778.303.49 0 .807-.331l1.629-1.658 1.326-1.642-.116 2.954v6.816q0 .504.332.836.331.317.836.317″></path></svg></span></span></button></span></div></div></div></div></div></div></div></div></div>

大模型回答:

要使用 Selenium WebDriver 关闭特定的组件(例如,带有类名 .close-btn-wrapper-HINk0h 的关闭按钮),可以通过定位该元素并模拟点击操作来实现。以下是详细的步骤和示例代码:

步骤:

  1. 导入必要的模块:
    • webdriver 用于控制浏览器。
    • By 用于元素定位。
    • time (可选)用于添加延时,以确保元素已加载。
  2. 初始化 WebDriver:
    • 以 Chrome 为例,确保已安装相应的 WebDriver 并配置好环境。
  3. 打开目标网页:
    • 使用 driver.get() 方法导航到目标 URL。
  4. 定位关闭按钮:
    • 使用合适的定位策略(如 By.CLASS_NAME、By.CSS_SELECTOR 或 By.XPATH)来定位关闭按钮。
  5. 模拟点击操作:
    • 使用 click() 方法点击关闭按钮,以关闭组件。
  6. 关闭浏览器:
    • 使用 driver.quit() 方法关闭浏览器窗口并释放资源。

示例代码:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 初始化 WebDriver(以 Chrome 为例)
driver = webdriver.Chrome()

try:
    # 打开目标网页
    driver.get('https://www.example.com')

    # 等待页面加载(可根据需要调整时间或使用显式等待)
    time.sleep(2)

    # 定位关闭按钮
    # 方法一:使用 CSS 选择器
    close_button = driver.find_element(By.CSS_SELECTOR, '.close-btn-wrapper-HINk0h [role="img"]')
    
    # 方法二:使用 XPath
    # close_button = driver.find_element(By.XPATH, '//div[@class="close-btn-wrapper-HINk0h"]//*[@role="img"]')

    # 模拟点击关闭按钮
    close_button.click()

    # 等待观察效果(可选)
    time.sleep(2)

finally:
    # 关闭浏览器
    driver.quit()

说明:

  1. 定位策略:
    • 在示例中,使用了 CSS 选择器 .close-btn-wrapper-HINk0h [role="img"] 来定位关闭按钮。这个选择器首先定位具有类名 .close-btn-wrapper-HINk0h 的 div,然后在该 div 下查找具有 role="img" 属性的子元素,这通常是实际的关闭图标。
    • 你也可以使用 XPath 来定位,如注释中的方法二所示。
  2. 等待元素加载:
    • 使用 time.sleep(2) 是一种简单的等待方式,但在实际项目中,建议使用显式等待(WebDriverWait)来提高脚本的稳定性和效率。例如:from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待关闭按钮可点击 close_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, '.close-btn-wrapper-HINk0h [role="img"]')) ) close_button.click()
  3. 异常处理:
    • 在实际应用中,建议添加异常处理,以应对元素未找到或其他潜在问题。例如:try: close_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, '.close-btn-wrapper-HINk0h [role="img"]')) ) close_button.click() except Exception as e: print(f"无法关闭组件: {e}")
  4. 确保元素可交互:
    • 确保在尝试点击关闭按钮之前,该按钮处于可见且可点击的状态。如果按钮被其他元素遮挡或尚未完全加载,点击操作可能会失败。
作者 east
doris 1月 14,2025

解决Navicat查看导入运行任务ROUTINE:1105 – errCode = 2, detailMessage = Please check your sql, we meet an error when parsing.

第一次 通过 Doris Routine Load 导入方式持续消费 Kafka Topic 中的数据。 按官方文档
Routine Load – Apache Doris

在navicat按照官方示例查看导入任务:

mysql> SHOW ROUTINE LOAD FOR testdb.example_routine_load\G

发现报错:

1105 – errCode = 2, detailMessage = Please check your sql, we meet an error when parsing.

刚开始很郁闷,以为doris官方团队开发的功能很敷衍,没具体提示具体是什么错误。

反复试验之后,才发现是\G 导致报错,修改为下面这样就正常了

mysql> SHOW ROUTINE LOAD FOR testdb.example_routine_load
作者 east
python 1月 14,2025

selenium.webdriver 如何执行Esc返回键的功能(python实现)

在使用 Selenium WebDriver 进行自动化测试时,有时需要模拟键盘操作,例如按下 Esc 键来执行返回或取消操作。Selenium 提供了多种方法来实现这一点,以下是几种常见的方法:

方法一:使用 send_keys 方法

send_keys 方法允许你向当前聚焦的元素发送按键事件。要模拟按下 Esc 键,可以使用 Keys.ESCAPE。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

# 初始化 WebDriver(以 Chrome 为例)
driver = webdriver.Chrome()

try:
    # 打开目标网页
    driver.get('https://www.example.com')

    # 等待页面加载
    time.sleep(2)

    # 向当前聚焦的元素发送 Esc 键
    driver.find_element(By.TAG_NAME, 'body').send_keys(Keys.ESCAPE)

    # 或者,如果你知道具体的元素,可以定位后发送
    # element = driver.find_element(By.ID, 'some-element-id')
    # element.send_keys(Keys.ESCAPE)

    # 等待观察效果
    time.sleep(2)

finally:
    # 关闭浏览器
    driver.quit()

方法二:使用 ActionChains

ActionChains 提供了更复杂的用户交互方式,包括键盘操作。你可以使用 send_keys 方法来发送 Esc 键。

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import time

# 初始化 WebDriver(以 Chrome 为例)
driver = webdriver.Chrome()

try:
    # 打开目标网页
    driver.get('https://www.example.com')

    # 创建 ActionChains 对象
    actions = ActionChains(driver)

    # 向当前聚焦的元素发送 Esc 键
    actions.send_keys(Keys.ESCAPE).perform()

    # 或者,指定某个元素
    # element = driver.find_element(By.ID, 'some-element-id')
    # actions.move_to_element(element).send_keys(Keys.ESCAPE).perform()

    # 等待观察效果
    time.sleep(2)

finally:
    # 关闭浏览器
    driver.quit()

方法三:使用 JavaScript 执行(适用于某些特定场景)

在某些情况下,直接使用 JavaScript 来触发 Esc 键的效果可能更为有效,尤其是当涉及到模态窗口、弹出层等需要关闭的 UI 元素时。

from selenium import webdriver
import time

# 初始化 WebDriver(以 Chrome 为例)
driver = webdriver.Chrome()

try:
    # 打开目标网页
    driver.get('https://www.example.com')

    # 等待页面加载
    time.sleep(2)

    # 使用 JavaScript 触发 Esc 键的效果
    driver.execute_script("document.activeElement.blur();")  # 失去焦点
    driver.execute_script("window.dispatchEvent(new KeyboardEvent('keydown', {key: 'Escape', code: 'Escape', bubbles: true}));")

    # 等待观察效果
    time.sleep(2)

finally:
    # 关闭浏览器
    driver.quit()

注意事项

  1. 等待元素加载:在执行键盘操作之前,确保目标元素已经加载并且可以被操作。可以使用显式等待(WebDriverWait)来代替 time.sleep,以提高脚本的稳定性和效率。
  2. 元素定位:确保你定位的元素是当前聚焦的元素,或者明确指定要发送 Esc 键的元素。
  3. 浏览器兼容性:不同浏览器对键盘事件的处理可能略有不同,确保在目标浏览器上进行测试。
  4. 权限和安全性:某些网站可能会检测到自动化工具并阻止其操作,确保遵守网站的使用条款,并在合法范围内使用自动化测试。
作者 east
Android 1月 12,2025

WindowManagerService(WMS)的性能优化与调试

一、性能优化策略

(一)窗口重绘优化

  • 减少不必要的重绘
    • WMS 会智能地跟踪窗口的状态变化,只有当窗口的属性发生实质性改变时,才会触发重绘操作。例如,当窗口的背景颜色发生变化,但窗口内的视图布局和内容没有改变时,WMS 不会对整个窗口进行重新绘制。它会通过内部的机制,如判断视图的脏区域(dirty region),只更新背景部分,这样可以大大减少绘制的工作量。
    • 对于复杂的窗口,包含多个子视图的情况,这种优化更为重要。例如,在一个包含列表视图和头部视图的窗口中,如果只是列表中的某一项内容发生变化,WMS 会尽量只重绘该项对应的视图区域,而不是整个列表视图,从而节省系统资源,提高绘制效率。
  • 采用缓冲技术
    • WMS 采用双缓冲或三缓冲技术来优化窗口的绘制操作,减少绘制过程中的闪烁和卡顿现象。双缓冲技术就像是有两块画布,一块在前台显示,另一块在后台绘制。当后台的画布绘制完成后,再将其与前台的画布进行交换,这样可以避免在绘制过程中用户看到不完整的画面而产生闪烁感。
    • 三缓冲技术则是在双缓冲的基础上增加了一块备用画布,进一步提高了绘制的效率和流畅性。例如,在高帧率的游戏应用或者快速滚动的列表视图中,缓冲技术能够有效地保证画面的平滑过渡,提供更好的视觉体验。

(二)资源分配优化

  • 多窗口环境下的资源平衡
    • 在多窗口环境下,WMS 会合理地分配系统资源,避免因某个窗口占用过多资源而导致其他窗口的性能下降。它会根据窗口的优先级、类型以及用户的操作焦点等因素来分配资源。例如,当系统资源紧张时,WMS 会降低一些非关键窗口(如后台运行的小工具窗口)的帧率,优先保证关键窗口(如正在播放视频的窗口或用户正在交互的窗口)的性能。
    • 对于不同类型的窗口,WMS 也有不同的资源分配策略。比如,对于输入法窗口,会确保其响应的及时性,以便用户能够流畅地输入文字;对于系统警报窗口,会优先保证其显示的优先级,使其能够及时引起用户的注意。
  • 内存管理优化
    • WMS 会对窗口相关的内存资源进行有效的管理。在窗口创建时,它会合理地分配内存给窗口的视图层次结构、Surface 等对象。当窗口不再需要时,会及时释放这些内存资源。例如,在一个 Activity 窗口被销毁后,WMS 会通过一系列的机制,如释放与该窗口关联的 Surface 对象所占用的内存,回收窗口状态对象(WindowState)占用的内存等,确保内存的有效利用,减少内存泄漏的风险。

二、调试工具与方法

(一)使用 adb 命令进行调试

  • 查看窗口信息
    • 通过adb shell dumpsys window命令可以获取 WMS 的运行状态信息,特别是窗口相关的详细信息。这个命令会输出当前系统中所有窗口的类型、层级、大小、位置等信息。例如,开发人员可以通过这个命令查看一个应用程序的所有窗口是否按照预期的层级和位置显示。如果发现某个窗口的层级异常,可能是窗口管理的逻辑出现了问题。
    • 还可以使用adb shell dumpsys window <window_name>命令来查看特定窗口的详细信息。这对于排查某个特定窗口的问题非常有用,比如一个自定义的对话框窗口没有正确显示或者无法接收输入事件时,可以通过这个命令查看其详细的属性和状态。
  • 跟踪事件处理过程
    • 利用adb命令结合系统日志,可以跟踪 WMS 的事件处理过程。例如,通过设置日志标签(log tag)并使用adb logcat命令来查看与窗口管理相关的日志信息。当窗口被创建、更新或者销毁时,相关的日志会记录这些事件的详细过程,包括时间戳、操作类型、涉及的窗口等信息。这有助于开发人员了解 WMS 是如何处理这些事件的,以及在事件处理过程中是否出现了异常情况。

(二)利用系统日志进行调试

  • 分析工作流程异常
    • 系统日志是一个重要的调试工具,它记录了 WMS 的工作流程和事件处理过程。当出现窗口显示异常、输入事件分发错误等问题时,可以通过查看系统日志来查找线索。例如,如果一个窗口无法接收触摸事件,在系统日志中可能会发现是因为该窗口的焦点状态没有正确设置或者输入事件分发的逻辑出现了错误。
    • 系统日志还会记录一些错误信息和警告信息,这些信息对于定位和解决性能问题也非常有帮助。比如,当窗口重绘过于频繁导致系统性能下降时,系统日志可能会记录相关的警告信息,提示开发人员检查窗口更新的逻辑是否合理。
  • 结合日志级别进行调试
    • Android 系统的日志分为不同的级别,如 DEBUG、INFO、WARN、ERROR 等。开发人员可以根据需要调整日志级别,以便获取更详细或者更关键的信息。在开发和调试阶段,可以将日志级别设置为 DEBUG,获取最详细的日志信息,包括 WMS 内部的一些调试信息和状态变化。在产品发布阶段,可以将日志级别适当提高,只记录重要的警告和错误信息,以减少日志对系统性能的影响。

(三)使用 Android Studio 的调试工具

  • Layout Inspector 工具
    • Android Studio 中的 Layout Inspector 工具可以查看当前窗口的布局结构和属性。通过这个工具,开发人员可以直观地看到窗口内各个视图的层次结构、大小、位置以及它们的属性设置。例如,当窗口的布局出现问题,如视图重叠或者位置偏移时,可以使用这个工具来快速定位问题所在的视图层次,检查视图的布局参数是否正确设置。
    • 它还可以帮助开发人员分析窗口的性能问题。比如,如果一个窗口的布局过于复杂,导致加载时间过长或者绘制性能下降,可以通过 Layout Inspector 工具来查看布局结构,寻找优化的空间,如减少不必要的视图嵌套或者优化视图的大小和位置计算方式。
  • Profiler 工具
    • Profiler 工具可以用于分析应用程序的性能,包括与 WMS 相关的性能问题。它可以监测 CPU、内存、GPU 等资源的使用情况,以及帧率、卡顿等性能指标。当发现窗口显示卡顿或者系统整体性能下降时,可以使用 Profiler 工具来查看 WMS 相关的操作是否占用了过多的资源。
    • 例如,如果发现 WMS 在窗口重绘过程中占用了大量的 CPU 资源,可以通过 Profiler 工具进一步分析重绘的具体过程,找出导致性能问题的具体代码段或者操作,如复杂的绘图逻辑或者频繁的视图更新,从而进行针对性的优化。
作者 east
Android 1月 12,2025

Android Framework WMS与其他系统服务的协作

在 Android 系统这个复杂而精密的体系中,WMS(WindowManagerService)并不是独立工作的,它与其他系统服务紧密协作,共同实现了系统的高效运行和丰富的用户体验。

一、WMS 与 AMS(Activity Manager Service)的协作

(一)窗口创建阶段

  • 交互流程:当 AMS 需要创建一个新的 Activity 窗口时,会通过 Binder 机制调用 WMS 的 addView 方法。这就好比 AMS 是一个建筑设计师,规划好了要建一座新的 “房子”(Activity 窗口),然后把这个任务交给 WMS 这个 “建筑工人” 去实际建造。
  • 资源分配与协作细节:WMS 接收到请求后,会创建相应的 WindowState 对象,并为其分配 Surface 资源。Surface 资源就像是房子的 “墙面”,是窗口进行内容绘制的基础。例如,在创建一个地图应用的 Activity 窗口时,WMS 会为其分配足够的 Surface 资源,以确保地图能够完整、清晰地显示在窗口中。

(二)窗口布局阶段

  • 信息传递与协作方式:WMS 负责计算窗口的大小和位置,这是基于系统配置(如屏幕分辨率、方向等)以及窗口本身的属性(如窗口类型、内容大小等)来进行的。然后,WMS 会通过回调 AMS 的 onConfigurationChanged 方法通知应用程序配置更改。这就像是 WMS 完成了房间的布局规划后,把布局信息告诉 AMS,让 AMS 去通知房间的 “主人”(应用程序)房间的格局发生了变化。
  • 对用户体验的影响:这种协作确保了应用程序能够及时调整界面布局,以适应窗口大小和位置的变化。例如,在屏幕方向发生改变时,应用程序可以根据 WMS 提供的新布局信息,重新排列界面元素,如将竖屏模式下的列表布局调整为横屏模式下的平铺布局,从而提供更好的用户体验。

(三)焦点管理阶段

  • 焦点更新机制:WMS 维护着焦点窗口的列表,这个焦点窗口就是当前正在与用户交互的窗口,比如用户正在输入文字的编辑窗口或者正在点击操作的游戏窗口等。当焦点发生变化时,WMS 会通知 AMS 更新 Activity 的焦点状态。
  • 对应用程序的作用:这使得应用程序能够准确地知道哪个窗口处于焦点状态,从而正确地处理用户输入。例如,在一个聊天应用中,当用户从聊天列表窗口切换到聊天输入窗口时,WMS 会通知 AMS 焦点的转移,聊天输入窗口所在的 Activity 就可以激活输入法,准备接收用户的输入内容。

(四)动画处理阶段

  • 协作实现动画效果:WMS 负责实现窗口切换动画,比如淡入淡出、滑动等动画效果。在进行窗口切换动画时,WMS 会通知 AMS 暂停或恢复 Activity 的绘制。这就像是一场舞台表演,WMS 是舞台特效师,负责窗口切换的动画特效,而 AMS 则像是演员调度员,根据特效师的要求安排演员(Activity)暂停或继续表演。
  • 确保动画平滑过渡的重要性:这种协作确保了动画的平滑过渡,避免了窗口切换过程中的画面闪烁或卡顿。例如,在打开一个新的应用程序时,旧应用程序窗口逐渐淡出,新应用程序窗口逐渐淡入,用户可以看到一个流畅的过渡过程,提升了系统的视觉体验。

(五)输入事件分发阶段

  • 不同类型窗口的事件分发方式:WMS 作为输入事件的中转站,会将接收到的事件分发给相应的窗口。对于非装饰窗口(如 PopupWindow),WMS 会直接处理事件;而对于装饰窗口(如 Activity),WMS 会将事件传递给 AMS,由 AMS 再转发给具体的 Activity。这就好比信件的投递,WMS 是邮局,先对信件(输入事件)进行分类,然后把属于 Activity 的信件交给 AMS,由 AMS 送到具体的 “收件人”(Activity)手中。
  • 保障输入事件的准确处理:这种分工明确的协作方式确保了输入事件能够准确地被相应的窗口处理。例如,当用户在屏幕上点击一个按钮时,WMS 会根据按钮所在的窗口类型,正确地将点击事件发送到对应的窗口处理逻辑中,保证了应用程序能够按照用户的意图做出正确的响应。

二、WMS 与 SurfaceFlinger 的协作

  • 显示控制与渲染协作流程:WMS 通过创建 SurfaceControl 对象并与 SurfaceFlinger 交互,实现了窗口的显示和更新。SurfaceControl 作为 SurfaceFlinger 的核心组件,负责管理窗口的显示层级和属性。例如,WMS 利用 SurfaceControl 的 setLayer 方法设置窗口的 Z 轴层级,就像在一个多层的展示架上安排物品的位置一样,确保正确的显示顺序。
  • 对图形显示的重要性:这种协作机制实现了高效的窗口渲染和管理,为 Android 系统提供了流畅的用户界面体验。SurfaceFlinger 就像是一个图形合成器,将各个窗口的内容(通过 Surface)进行合成,然后显示在屏幕上。WMS 与 SurfaceFlinger 的紧密配合,使得窗口能够按照正确的顺序、位置和属性显示出来,无论是简单的文本窗口还是复杂的游戏画面,都能准确地呈现在用户眼前。比如在一个多窗口应用场景中,WMS 和 SurfaceFlinger 协同工作,保证不同窗口的内容能够正确地叠加和显示,不会出现窗口内容混乱的情况。
作者 east

上一 1 … 12 13 14 下一个

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。回复”chatgpt”获取免注册可用chatgpt。回复“大数据”获取多本大数据电子书

标签

AIGC AI创作 bert chatgpt github GPT-3 gpt3 GTP-3 hive mysql O2O tensorflow UI控件 不含后台 交流 共享经济 出行 图像 地图定位 外卖 多媒体 娱乐 小程序 布局 带后台完整项目 开源项目 搜索 支付 效率 教育 日历 机器学习 深度学习 物流 用户系统 电商 画图 画布(canvas) 社交 签到 联网 读书 资讯 阅读 预订

官方QQ群

小程序开发群:74052405

大数据开发群: 952493060

近期文章

  • 如何在Chrome中设置启动时自动打开多个默认网页
  • spark内存溢出怎样区分是软件还是代码原因
  • MQTT完全解析和实践
  • 解决运行Selenium报错:self.driver = webdriver.Chrome(service=service) TypeError: __init__() got an unexpected keyword argument ‘service’
  • python 3.6使用mysql-connector-python报错:SyntaxError: future feature annotations is not defined
  • 详解Python当中的pip常用命令
  • AUTOSAR如何在多个供应商交付的配置中避免ARXML不兼容?
  • C++thread pool(线程池)设计应关注哪些扩展性问题?
  • 各类MCAL(Microcontroller Abstraction Layer)如何与AUTOSAR工具链解耦?
  • 如何设计AUTOSAR中的“域控制器”以支持未来扩展?

文章归档

  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年1月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年7月
  • 2018年6月

分类目录

  • Android (73)
  • bug清单 (79)
  • C++ (34)
  • Fuchsia (15)
  • php (4)
  • python (45)
  • sklearn (1)
  • 云计算 (20)
  • 人工智能 (61)
    • chatgpt (21)
      • 提示词 (6)
    • Keras (1)
    • Tensorflow (3)
    • 大模型 (1)
    • 智能体 (4)
    • 深度学习 (14)
  • 储能 (44)
  • 前端 (5)
  • 大数据开发 (491)
    • CDH (6)
    • datax (4)
    • doris (31)
    • Elasticsearch (15)
    • Flink (78)
    • flume (7)
    • Hadoop (19)
    • Hbase (23)
    • Hive (41)
    • Impala (2)
    • Java (71)
    • Kafka (10)
    • neo4j (5)
    • shardingsphere (6)
    • solr (5)
    • Spark (100)
    • spring (11)
    • 数据仓库 (9)
    • 数据挖掘 (7)
    • 海豚调度器 (10)
    • 运维 (34)
      • Docker (3)
  • 小游戏代码 (1)
  • 小程序代码 (139)
    • O2O (16)
    • UI控件 (5)
    • 互联网类 (23)
    • 企业类 (6)
    • 地图定位 (9)
    • 多媒体 (6)
    • 工具类 (25)
    • 电商类 (22)
    • 社交 (7)
    • 行业软件 (7)
    • 资讯读书 (11)
  • 嵌入式 (71)
    • autosar (63)
    • RTOS (1)
    • 总线 (1)
  • 开发博客 (16)
    • Harmony (9)
  • 技术架构 (6)
  • 数据库 (32)
    • mongodb (1)
    • mysql (13)
    • pgsql (2)
    • redis (1)
    • tdengine (4)
  • 未分类 (7)
  • 程序员网赚 (20)
    • 广告联盟 (3)
    • 私域流量 (5)
    • 自媒体 (5)
  • 量化投资 (4)
  • 面试 (14)

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

All Rights Reserved by Gitweixin.本站收集网友上传代码, 如有侵犯版权,请发邮件联系yiyuyos@gmail.com删除.