CHAPTER 9: 《DESIGN A WEB CRAWLER》第9章 《设计一个web爬虫》
CHAPTER 9: 《DESIGN A WEB CRAWLER》第九章 设计一个web爬虫
在本章中,我们将重点介绍网络爬虫设计:一种有趣而经典的系统设计
面试问题。
网络爬虫被称为机器人或蜘蛛。它被搜索引擎广泛用于发现网络上的新内容或更新内容。内容可以是网页、图像、视频、PDF文档等。网络爬虫首先收集一些网页,然后跟踪这些网页上的链接页面以收集新内容。图 9-1 显示了爬网过程的直观示例。

爬虫有多种用途:
- 搜索引擎索引:这是最常见的用例。爬虫收集网络页面为搜索引擎创建本地索引。例如Googlebot 就是网络谷歌搜索引擎背后的爬虫。
- Web 存档:这是从 Web 收集信息以保存的过程数据以备将来使用。例如,许多国家图书馆运行爬虫来存档网络网站。值得注意的例子是美国国会图书馆[1]和欧盟网络档案馆[2]。
- 网络挖矿:网络的爆炸性增长为数据挖掘。网络挖掘有助于从互联网上发现有用的知识。为例如,顶级金融公司使用爬虫下载股东大会和年度报告以了解公司的关键举措。
- 网络监控。爬虫有助于监控版权和商标侵权行为通过互联网。例如,Digimarc [3] 利用爬虫来发现盗版作品和报告。
开发网络爬虫的复杂性取决于我们打算支持的规模。它可以是一个只需要几个小时就能完成的小型学校项目,也可以是一个巨大的项目需要专门的工程团队持续改进的项目。因此,我们将在下面探讨要支持的规模和功能。
第 1 步 - 了解问题并确定设计范围
网络爬虫的基本算法很简单:
- 给定一组 URL,下载这些 URL 链接的所有网页。
- 从这些网页中提取 URL
- 将新 URL 添加到要下载的 URL 列表中。重复这 3 个步骤。
网络爬虫真的像这个基本算法一样简单吗?不完全是。设计一个可扩展的网络爬虫是一项极其复杂的任务。任何人都不太可能设计面试期间的大型网络爬虫。在开始设计之前,我们必须提出问题以了解需求并确定设计范围:
应聘者:爬虫的主要用途是什幺?它是否用于搜索引擎索引,数据挖掘,还是别的什幺?
面试官:搜索引擎索引。
应聘者:网络爬虫每月收集多少个网页?
面试官:10 亿页。
应聘者:包括哪些内容类型?仅限 HTML 或其他内容类型,例如还有 PDF 和图像?
面试官:仅限 HTML。
应聘者:我们可以考虑新添加或编辑的网页吗?
面试官:是的,我们应该考虑新添加或编辑的网页。
应聘者:我们需要存储从网络上抓取的 HTML 页面吗?
面试官:是的,最长 5 年
应聘者:如何处理重复内容的网页?
面试官:包含重复内容的页面应被忽略
以上是您可以向面试官提出的一些示例问题。重要的是了解要求并澄清歧义。即使你被要求设计一个
像网络爬虫这样的简单产品,你和你的面试官也可能有不一样的想法。
除了与面试官澄清的功能外,记下一个好的网络爬虫的以下特征:
- 可测量性:网络非常大。那里有数十亿个网页。使用并行化爬网应该非常有效。
- 鲁棒性:网络充满了陷阱。错误的 HTML、无响应的服务器、崩溃、恶意链接等都很常见。爬网进程必须处理所有这些边缘情况。
- 人性:爬虫不应在短时间内向网站发出太多请求时间间隔。
- 可扩展性:系统非常灵活,因此只需进行最少的更改即可支持新的内容类型。例如,如果我们将来想抓取图像文档,我们不需要重新设计整个系统。
封底计算
以下估计基于许多假设,重要的是与面试官沟通以达成共识。
- 假设每月下载10亿个网页。
- QPS:1,000,000,000 / 30 天 / 24 小时 / 3600 秒 = ~400 页/秒。
- 峰值 QPS = 2 * QPS = 800
- 假设平均网页大小为 500k。
- 10 亿页 x 500k = 每月 500 TB 存储。如果您不清楚数字存储单元,请再次浏览第 2 章中的“2 的幂”部分。
- 假设数据存储 5 年,则 500 TB * 12 个月 * 5 年 = 30 PB。一个 30 PB需要存储来存储五年的内容。
第 2 步 - 提出高级设计并获得支持
一旦明确了需求,我们就会继续进行高级设计。灵感来自以前的在对网络爬虫的研究[4] [5]中,我们提出了一个如图9-2所示的高级设计。

首先,我们探索每个设计组件以了解它们的功能。然后我们逐步检查爬虫工作流程。
种子网址
网络爬虫使用种子 URL 作为爬网过程的起点。例如,要抓取大学网站上的所有网页,选择种子 URL 的直观方法是使用大学的域名。要抓取整个网络,我们需要创造性地选择种子 URL。一个好的种子网址作为一个很好的起点,爬虫可以利用它来遍历尽可能多的链接。一般策略是将整个 URL 空间划分为更小的空间。第一个提出的该方法基于地点,因为不同的国家可能有不同的流行网站。另一种方法是根据主题选择种子 URL;例如,我们可以划分 URL 空间购物、体育、医疗保健等。种子 URL 选择是一个开放式问题。你应该不会给出完美的答案。开放思考
网址前沿
大多数现代网络爬虫将爬行状态分为两种:待下载和已下载。存储要下载的 URL 的组件称为 URL Frontier。您可以将其称为先进先出 (FIFO) 队列。有关详细信息URL Frontier,请参阅深入研究。
HTML下载器
HTML 下载器从 Internet 下载网页。通过 URL 边界提供了这些 URL。
DNS解析器
要下载网页,必须将 URL 转换为 IP 地址。超文本标记语言下载器调用DNS解析器来获取URL对应的IP地址。为了例如,自 2019 年 3 月 5 日起,URL www.wikipedia.org 已转换为 IP 地址198.35.26.96。
内容解析器
下载网页后,必须对其进行解析和验证,因为格式错误的网页页面可能会引发问题并浪费存储空间。在中实现内容解析器抓取服务器会减慢抓取过程。因此,内容解析器是一个单独的成分。
内容已存在了?
在线研究[6]显示,29%的网页是重复内容,这可能导致相同的内容被存储多次。我们介绍“看到的内容?”数据结构,消除数据冗余并缩短处理时间。它有助于检测新的之前存储在系统中的内容。要比较两个 HTML 文档,我们可以一个接一个的比较他们。然而,这种方法速度慢且耗时,尤其是当涉及数十亿个网页时。完成这项任务的一个有效方法是比较两个网页的哈希值[7]。
内容存储
它是一个用于存储HTML内容的存储系统。存储系统的选择取决于磁盘和内存,数据类型、数据大小、访问频率、寿命等因素。
- 大多数内容存储在磁盘上,因为数据集太大,无法放入内存。
- 热门内容保留在内存中以减少延迟。
网址提取器
URL Extractor 从 HTML 页面中解析并提取链接。图 9-3 显示了一个示例链接提取过程。通过添加以下内容将相对路径转换为绝对 URL“https://en.wikipedia.org”前缀。

URL 过滤器
URL 筛选器排除了“列入黑名单”的网站。
URL Seen?
“URL Seen?”是一种数据结构,用于跟踪之前或已经访问过的 URL最尾端地址。“URL Seen?”有助于避免多次添加相同的 URL增加服务器负载并导致潜在的无限循环。布隆过滤器和哈希表是实现“URL Seen?”组件。我们不会详细介绍 bloom 过滤器和哈希表的实现这里。有关详细信息,请参阅参考资料 [4] [8]。
URL 存储
URL 存储存储已访问的 URL。到目前为止,我们已经讨论了每个系统组件。接下来,我们把它们放在一起来解释工作流。
网络爬虫工作流程
为了更好地逐步解释工作流程,在设计中添加了串行号如图9-4所示。
第 1 步:将种子 URL 添加到 URL 边界
第 2 步:HTML 下载器从 URL Frontier 获取 URL 列表。
第 3 步:HTML 下载器从 DNS 解析器获取 URL 的 IP 地址并启动下载。
第 4 步:内容解析器解析 HTML 页面并检查页面是否格式不正确。
第 5 步:解析和验证内容后,将其传递给“看到的内容”组件。
第 6 步:“看到的内容”组件检查 HTML 页面是否已在存储中。
- 如果它在存储中,这意味着不同 URL 中的相同内容已经处理。在这种情况下,HTML 页面将被丢弃。
- 如果它不在存储中,则系统之前没有处理过相同的内容。这内容被传递给链接提取器。
第 7 步:链接提取器从 HTML 页面中提取链接。
第 8 步:提取的链接将传递到 URL 过滤器。
第 9 步:过滤链接后,它们被传递到“URL Seen?”组件。
第 10 步:“URL Seen”组件检查 URL 是否已经在存储中,如果是,则为之前处理过,不需要做任何事情。
第 11 步:如果之前未处理过 URL,则会将其添加到 URL 边界。
第 3 步 - 深入探究设计
到目前为止,我们已经讨论了高级设计。接下来,我们将讨论最多的重要的建筑构件和技术深度:
- 深度优先搜索 (DFS) 与广度优先搜索 (BFS)
- URL 边界
- HTML 下载器
- 鲁棒性
- 扩展
- 检测并避免有问题的内容
DFS 与 BFS
您可以将 Web 视为有向图,其中网页充当节点,超链接(URL) 作为边。爬网过程可以看作是从一个 Web 遍历有向图页面给其他人。两种常见的图遍历算法是 DFS 和 BFS。但是,DFS 是通常不是一个好的选择,因为DFS的深度可能很深。BFS 通常由网络爬虫使用,并由先进先出 (FIFO) 实现队列。
在 FIFO 队列中,URL 按照其排队顺序取消排队。但是,这实现有两个问题:
-
来自同一网页的大多数链接都链接回同一主机。在图 9-5 中,所有wikipedia.com 中的链接是内部链接,使爬虫忙于处理 URL来自同一主机 (wikipedia.com)。当爬虫尝试下载同时,维基百科服务器将充斥着请求。这被认为是“不礼貌”。

-
标准 BFS 不考虑 URL 的优先级。网络很大并非每个页面都具有相同的质量和重要性水平。因此,我们可能想要根据URL的页面排名、网络流量、更新频率等确定URL的优先级。
URL 边界
URL 边界有助于解决这些问题。URL 边界是一种存储的数据结构要下载的 URL。URL 边界是确保合理的重要组成部分,URL 优先级和新鲜度。书中提到了一些关于URL前沿的值得注意的论文在参考资料[5] [9]中。这些论文的发现如下:
礼貌
通常,网络爬虫应避免向同一托管服务器发送过多请求在短时间内。发送过多的请求被认为是“不礼貌”的,甚至被对待作为拒绝服务 (DOS) 攻击。例如,在没有任何约束的情况下,爬虫可以发送每秒有数千个请求发送到同一个网站。这可能会使网络不堪重负服务器。强制礼貌的一般思路是一次从同一页面下载一页主机。可以在两个下载任务之间添加延迟。礼貌约束是通过维护从网站主机名到下载(工作线程)线程的映射来实现。每个下载器线程都有一个单独的 FIFO 队列,并且仅下载从那个队列。图 9-6 显示了这个队列合理(礼貌)的设计。

-
队列路由器:确保每个队列(b1、b2、…bn) 仅包含来自同一主机。
-
映射表:它将每个主机映射到一个队列。

-
FIFO 队列 b1、b2 到 bn:每个队列都包含来自同一主机的 URL。
-
队列选择器:每个工作线程都映射到一个 FIFO 队列,并且它只下载该队列中的 URL。队列选择逻辑由队列选择器完成。
-
工作线程 1 到 N。工作线程从同一个线程中一个接一个地下载网页主机。可以在两个下载任务之间添加延迟。
优先权
来自一个关于苹果产品的论坛的随机帖子具有非常不同的分量而不是 Apple 主页上的帖子。尽管它们都有“Apple”关键字,但它是爬虫首先抓取 Apple 主页是明智的。我们根据有用性对 URL 进行优先级排序,这可以通过 PageRank [10] 来衡量,网站流量、更新频率等。 “优先级排序器”是处理 URL 优先级的组件。有关此概念的深入信息,请参阅参考资料 [5] [10]。图 9-7 显示了管理 URL 优先级的设计。

- 优先级排序器:它将 URL 作为输入并计算优先级。
- 队列 f1 到 fn:每个队列都有一个分配的优先级。具有高优先级的队列是以更高的概率被选中。
- 队列选择器:随机选择一个偏向于较高队列的队列优先权。
图 9-8 显示了 URL 边界设计,它包含两个模块:
- 前队列:管理优先级
- 后排:管理合理(礼貌)

新鲜
网页不断地被添加、删除和编辑。网络爬虫必须定期重新抓取下载的页面以保持我们的数据集最新。重新抓取所有 URL 是时候了 -消耗和资源密集型。下面列出了一些优化新鲜度的策略:
- 根据网页的更新历史重新抓取。
- 优先考虑URL 并首先且更频繁地重新抓取重要页面。
URL Frontier 的存储
在现实世界的搜索引擎抓取中,前沿的 URL 数量可能有数百个数百万[4]。将所有内容放入内存既不持久也不可扩展。保存磁盘中的所有内容都是不受欢迎的,因为磁盘速度很慢;它可以很容易地成为爬虫的瓶颈。
我们采用了混合方法。大多数URL都存储在磁盘上,因此存储空间不是问题。为了降低从磁盘读取和写入磁盘的成本,我们在内存中维护缓冲区以进行入队/出队操作。缓冲区中的数据为定期写入磁盘。
HTML下载器
HTML 下载器使用 HTTP 协议从 Internet 下载网页。
在讨论 HTML 下载器之前,我们首先看一下机器人排除协议。
Robots.txt
Robots.txt,全称为机器人排除协议,是网站用于通信的标准与爬虫。它指定允许爬虫下载哪些页面。在尝试之前爬虫抓取网站时,首先要检查其对应的robots.txt并遵循其规则。
为了避免重复下载 robots.txt 文档,我们缓存该文档的结果。该文档是定期下载并保存到缓存。这是一段 robots.txt 文档,取自https://www.amazon.com/robots.txt。某些目录(例如 Creatorhub)是不允许的对于谷歌机器人。
用户代理:Googlebot
禁止:/creatorhub/*
禁止:/rss/people//reviews
禁止:/gp/pdp/rss//reviews
禁止:/gp/cdp/member-reviews/
禁止:/gp/aw/cr/
除了 robots.txt 之外,性能优化是我们将介绍的另一个重要概念
HTML 下载器。
性能优化
以下是 HTML 下载器的性能优化列表。
1.分布式抓取
为了获得高性能,爬虫作业被分发到多台服务器上,每台服务器运行多个线程。 URL空间被分割成更小的部分;所以,每个下载者负责 URL 的子集。图 9-9 显示了分布式爬网的示例。

2.缓存DNS解析器
DNS 解析器是爬虫的瓶颈,因为 DNS 请求可能会由于以下原因而花费时间:许多 DNS 接口的同步特性。 DNS 响应时间范围从 10 毫秒到200毫秒。一旦某个爬虫线程执行了对 DNS 的请求,其他线程就会被阻塞直到第一个请求完成。
维护我们的 DNS 缓存以避免调用 DNS频繁是速度优化的有效技术。我们的 DNS 缓存保留域名名称到 IP 地址的映射,并由 cron 作业定期更新。
3. 地点
按地理位置分布爬网服务器。当爬行服务器距离网站主机较近时,爬虫体验更快的下载时间。设计局部性适用于系统的大部分组件:爬取服务器、缓存、队列、存储等。
4、超时时间短
一些网络服务器响应缓慢或者可能根本不响应。为了避免长时间等待,指定了最长等待时间。如果主机在预定时间内没有响应,爬虫将停止该作业并爬取其他一些页面。
鲁棒性
除了性能优化之外,鲁棒性也是一个重要的考虑因素。我们提出提高系统鲁棒性的几种方法:
- 一致的散列:这有助于在下载者之间分配负载。一个新的可以使用一致性哈希来添加或删除下载服务器。参见第五章:设计一致的哈希以获取更多细节。
- 保存爬网状态和数据:为了防止失败,爬网状态和数据被写入一个存储系统。通过加载保存的状态可以轻松重新启动中断的爬网数据。
- 异常处理:在大型系统中,错误是不可避免且常见的。这爬虫必须优雅地处理异常而不导致系统崩溃。
- 数据验证:这是防止系统错误的重要措施。
可扩展性
随着几乎每个系统的发展,设计目标之一就是使系统变得灵活足以支持新的内容类型。爬虫可以通过插入新的扩展模块。图9-10显示了如何添加新模块。

- 插入 PNG 下载器模块以下载 PNG 文档。
- 添加Web监控模块,监控网页,防止版权和商标侵权。
检测并避免有问题的内容本节讨论如何检测和预防冗余、无意义或有害的内容。
1. 冗余内容
如前所述,近 30% 的网页是重复的。哈希值或校验和帮助检测重复 [11]。
2. 蜘蛛陷阱
蜘蛛陷阱是导致爬虫无限循环的网页。例如,无穷深层目录结构如下:
www.spidertrapexample.com/foo/bar/foo/bar/foo/bar/…
可以通过为 URL 设置最大长度来避免此类蜘蛛陷阱。然而,没有人-存在适合所有尺寸的解决方案来检测蜘蛛陷阱。包含蜘蛛陷阱的网站很容易由于在此类网站上发现了异常大量的网页而进行识别。它是难以开发自动算法来避免蜘蛛陷阱;但是,用户可以手动验证并识别蜘蛛陷阱,然后从爬虫中排除这些网站或应用一些自定义的 URL 过滤器。
3.数据噪声
有些内容几乎没有价值,例如广告、代码片段、垃圾邮件URL 等。这些内容对爬虫没有用处,应尽可能排除。
第 4 步 - 结束
在本章中,我们首先讨论了一个好的爬虫的特征:可扩展性、人性(礼貌)、可扩展性和健壮性。然后,我们提出了一个设计方案,并讨论了关键组件。构建可扩展的网络爬虫并非易事,因为网络非常庞大,而且到处都是陷阱。尽管我们已经涵盖了许多话题,但我们仍然错过了许多相关的谈话积分:
- 服务器端渲染:许多网站使用 JavaScript、AJAX 等脚本来即时生成链接。如果我们直接下载和解析网页,我们将无法检索动态生成的链接。为了解决这个问题,我们执行服务器端在解析页面之前先渲染(也称为动态渲染)[12]。
- 过滤掉不需要的页面:凭借有限的存储容量和抓取资源,反垃圾邮件组件有助于过滤掉低质量和垃圾页面 [13] [14]。
- 数据库复制和分片:复制和分片等技术用于提高数据层的可用性、可扩展性和可靠性。
- 水平扩展:对于大规模爬虫,数百甚至数千台服务器是需要执行下载任务。关键是保持服务器无状态。
- 可用性、一致性和可靠性:这些概念是任何大型系统的成功。我们在第 1 章中详细讨论了这些概念。刷新你的关于这些主题的记忆。
- 分析:收集和分析数据是任何系统的重要组成部分,因为数据是微调的关键成分。
恭喜你走到这一步!鼓励下自己。干得好!
参考资料
[1] 美国国会图书馆:https://www.loc.gov/websites/
[2] 欧盟网络档案馆:http://data.europa.eu/webarchive
[3] Digimarc:https://www.digimarc.com/products/digimarc-services/piracy-intelligence
[4] Heydon A., Najork M. Mercator:可扩展、可扩展的网络爬虫万维网,2(4) (1999),第219-229页
[5] 作者:Christopher Olston、Marc Najork:网络爬虫http://infolab.stanford.edu/~olston/publications/crawling_survey.pdf
[6] 29% 的网站面临重复内容问题:https://tinyurl.com/y6tmh55y
[7] Rabin M.O. 等人。随机多项式指纹识别 Center for Research in大学艾肯计算实验室计算技术(1981)
[8] B. H. Bloom,“具有允许误差的哈希编码中的空间/时间权衡”,《ACM通讯》,第13卷,第7期,第422-426页,1970年。
[9] 唐纳德·帕特森(Donald J. Patterson),网络爬虫:https://www.ics.uci.edu/~lopes/teaching/cs221W12/slides/Lecture05.pdf
[10] L. Page、S. Brin、R. Motwani 和 T. Winograd,“PageRank 引文排名:为网络带来秩序,“技术报告,斯坦福大学,1998.
[11] 伯顿·布鲁姆。哈希编码中的空间/时间权衡与允许的误差。ACM 通讯,13(7),第 422–426 页,1970 年 7 月。
[12] 谷歌动态渲染:
https://developers.google.com/search/docs/guides/dynamic-rendering
[13] T. Urvoy、T. Lavergne 和 P. Filoche,“使用隐藏样式跟踪网络垃圾邮件相似性“,载于第二届对抗性信息国际研讨会论文集网络上检索,2006 年。
[14] H.-T.Lee、D. Leonard、X. Wang 和 D. Loguinov,“IRLbot:扩展到 60 亿页及其他“,第 17 届国际万维网会议论文集,2008 年。
相关文章:
CHAPTER 9: 《DESIGN A WEB CRAWLER》第9章 《设计一个web爬虫》
CHAPTER 9: 《DESIGN A WEB CRAWLER》第九章 设计一个web爬虫 在本章中,我们将重点介绍网络爬虫设计:一种有趣而经典的系统设计 面试问题。 网络爬虫被称为机器人或蜘蛛。它被搜索引擎广泛用于发现网络上的新内容或更新内容。内容可以是网页、图像、视频…...
java SSM网上小卖部管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
一、源码特点 java SSM网上小卖部管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源 代码和数据库,系统主要…...
Java中集合元素的删除
关于集合元素的remove 重点:当集合的结构发生改变时,迭代器必须重新获取,如果还是用以前老的迭代器,会出现异常 java.util.ConcurrentModificationException 重点:在迭代集合元素的过程中,不能调用集合对象…...
HNU-数据挖掘-实验2-数据降维与可视化
数据挖掘课程实验实验2 数据降维与可视化 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验2 数据降维与可视化实验背景实验目标实验数据集说明实验参考步骤实验过程1.对数据进行初步降维2.使用无监督数据降维方法,比如PCA,I…...
【shell编程入门】正则表达式
正则表达式 特殊字符描述[]方括号表达式,表示匹配的字符集合,例如 [0-9]、[abcde]()标记子表达式起止位置*匹配前面的子表达式零或多次匹配前面的子表达式一或多次?匹配前面的子表达式零或一次\转义字符,除了常用转义外,还有&am…...
高效火情监测,科技助力森林防火【数字地球开放平台】
数字地球开放平台-以卫星遥感为核心的空天信息服务开放平台 (geovisearth.com) 2019年3月30日,四川省凉山州木里县爆发了一场森林火灾,火点位于海拔3800米左右,地形险峻、坡度陡峭、谷深难以抵挡火势。在扑救的过程中,27名森林消防…...
第14章_集合与数据结构拓展练习(前序、中序、后序遍历,线性结构,单向链表构建,单向链表及其反转,字符串压缩)
文章目录 第14章_集合与数据结构拓展练习选择填空题1、前序、中序、后序遍历2、线性结构3、其它 编程题4、单向链表构建5、单向链表及其反转6、字符串压缩 第14章_集合与数据结构拓展练习 选择填空题 1、前序、中序、后序遍历 分析: 完全二叉树: 叶结点…...
WEB前端3D变换效果以及如何应用js代码
WEB前端DAY8 变换效果3d <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>body{/* 视距:设置距离xy轴构成的平面有多少像素距离 */perspective: 500px;}div{/* 设置变化效果为3d *…...
Linux中的新建用户、切换用户
目录 一、Linux系统中有哪些用户 二、新建普通用户 三、root账号与普通账号的切换 一、Linux系统中有哪些用户 1.root 超级管理员(不受权限约束) 2.其他用户 普通用户(受到权限约束) 二、新建普通用户 创建新用户 sudo user…...
Vue3使用
1、列表实现 <el-table :data"tableData" border style"width: 100%" selection-change"handleSelectionChange" :header-cell-style"{text-align:center}"><el-table-column type"selection" width"55"…...
BindingException: Invalid bound statement (not found): xxMapper.deleteBatchIds
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xxMapper.deleteBatchIds 在使用mybatisplus的deleteBatchIds方法的时候,发生如下异常 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): …...
开源图床LightPicture搭建本地图片管理系统并实现无公网IP远程访问
文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进,功能也越来越多,而手机…...
黑马苍穹外卖学习Day10
文章目录 Spring Task介绍cron表达式入门案例 订单状态定时处理需求分析代码开发功能测试 WebSocket介绍入门案例 来单提醒需求分析代码开发 客户催单需求分析代码开发 Spring Task 介绍 cron表达式 入门案例 订单状态定时处理 需求分析 代码开发 新建一个task包里面编写代码…...
[数据结构 - C++] 红黑树RBTree
文章目录 1、前言2、红黑树的概念3、红黑树的性质4、红黑树节点的定义5、红黑树的插入Insert6、红黑树的验证7、红黑树与AVL树的比较附录: 1、前言 我们在学习了二叉搜索树后,在它的基础上又学习了AVL树,知道了AVL树是靠平衡因子来调节左右高…...
《WebKit 技术内幕》学习之十(2): 插件与JavaScript扩展
2 Chromium PPAPI插件 2.1 原理 插件其实是一种统称,表示一些动态库,这些动态库根据定义的一些标准接口可以跟浏览器进行交互,至于这个标准接口是什么都可以,重要的是大家都遵循它们,NPAPI接口标准只是其中的一种&a…...
【头歌-数据分析与实践-python】数据分析与实践-python——python基础
注意 : 本文档仅供参考使用,本章节程序绝大多数程序面向对象输出,一旦测试用例改变,会导致无法通过,请悉知 ! ! ! 请勿盲目使用 数据分析与实践-python——python基础 数据分析与实践-python——python基础 数据分析与…...
【数据库原理】(37)Web与数据库
随着网络的高速发展和网络服务的日趋完善,网络上的信息量呈几何级数增长。为了有效地组织、存储、管理和使用网上的信息,数据库技术被广泛地应用于网络领域。特别是在Internet上,已建立了数以万计的网站,其中大中型网站的后台大多…...
STM32 TIM输出比较、PWM波形
单片机学习! 目录 一、输出比较简介 二、PWM简介 三、输出比较通道 3.1通用定时器的输出比较部分电路 3.2高级定时器的输出比较部分电路 四、输出模式控制器 五、PWM基本结构 六、PWM参数计算 总结 前言 文章讲述STM32定时器的输出比较功能,它主…...
React16源码: React中的updateClassComponent的源码实现
ClassComponent 的更新 1 ) 概述 在 react 中 class component,是一个非常重要的角色它承担了 react 中 更新整个应用的API setStateforceUpdate 在react当中,只有更新了state之后,整个应用才会重新进行渲染在 class component 中…...
Mybatis 动态SQL(set)
我们先用XML的方式实现 : 把 id 为 13 的那一行的 username 改为 ip 创建一个接口 UserInfo2Mapper ,然后在接口中声明该方法 package com.example.mybatisdemo.mapper; import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*; import jav…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
