深入浅出区块链技术

article/2025/9/4 19:20:01

大厂技术  坚持周更  精选好文

本文为纯粹区块链技术分享,没有任何投资建议。希望大家喜欢~

一、故事导读

开始分享之前,引用自网上一个段子来引导大家。

《小明的故事》

小明是谁?小明是一名前端工程师,也是一个足球迷。

他有一项神奇的技能:他对足球有很深的理解,能够在每届世界杯开赛之前准确预测出最终夺冠的球队

84c534f72a98708966270b4616cc92e9.png

比如,在 2010 年的那届世界杯,小明就预测出了正确的结果。大赛闭幕,小明难掩兴奋之情,想在女朋友面前显摆一下。

2b044f4e50f387f391d190cad4bfd618.png

女朋友很自然地提出质疑,而小明并没有证据证明自己,只能哑口无言。

小明痛定思痛,决定写一个网站来提前记录自己的预言。

  1. 小明自己设计了网页界面。

  1. 找小伙伴帮忙写了一个后端服务,提供两个接口。

  1. 小明基于这两个接口,写了一个纯前端渲染的网站。

最终网站看起来是这个样子的:

d433feb63632e9ada654ee693cf119ee.png

接下来,小明静静等待下一届世界杯的到来。

时间过得很快,转眼到了 2014 年。这一次,小明再次正确预测出了冠军得主。

有网站记录预言,小明心想,这次女朋友应该会相信自己了吧!

然而……

77d3d3d6dbdca1a77c9eae4d04bfc52f.png

女朋友也是懂技术的,她这次仍然提出了一个合理的质疑。小明再次无言以对。

那么问题来了,该怎么办能够让女朋友相信自己呢?

如果现在还有没结论,可以继续向下看。

二、基础概念

区块链技术中有很多新的概念,对于一些并不深入这个领域的同学来说,相对不是很友好。本文先对一些技术的概念进行讲解。作为前置的知识。

区块链的概念

特殊的分布式数据库。

9a56fd96797f1377da464391169dfe74.png

一种链表结构,链表中元素作为一个区块。而每个链表的结构包括:

  • timestamp: 区块产生时间戳

  • nonce: 与区块头的hash值共同证明计算量(工作量)

  • data: 区块链上存储的数据

  • previousHash: 上一个区块的hash

  • hash: 本区块链的hash,由上述几个属性进行哈希计算而得

暂时无法在飞书文档外展示此内容

一些特点

  1. 去中心化存储

分布式数据库很早之前就已经出现,但与之不同的是区块链是一个没有管理者的、无中心化的分布式数据库。其起初的设计目标就是防止出现位于中心地位的管理者当局。

那么下一个问题就来了,如果没有一个管理者进行数据的管理,如何保证这个分布式数据库中的数据是可信任的呢?这就要提到下一个不可修改的特性了。

  1. 不可篡改

128d9af25302a773cab68fbeba618308.png

区块链上的数据是不可篡改的,大家都这样说。但其实,数据是可以改的,只是说改了以后就你自己认,而且被修改数据所在区块之后的所有区块都会失效。区块链网络有一个同步逻辑,整个区块链网络总是保持所有节点使用最长的链,那么你修改完之后,一联网同步,修改的东西又会被覆盖。这是不可篡改的一个方面。

更有意思的是,区块链通过加密校验,保证了数据存取需要经过严格的验证,而这些验证几乎又是不可伪造的,所以也很难篡改。加密并不代表不可篡改,但不可篡改是通过加密以及经济学原理搭配实现的。这还有点玄学的味道,一个纯技术实现的东西,还要靠理论来维持。但事实就是这样。这就是传说中的挖矿。

挖矿过程其实是矿工争取创建一个区块的过程,一旦挖到矿,也就代表这个矿工有资格创建新区块。怎么算挖到矿呢?通过一系列复杂的加密算法,从0开始到∞,找到一个满足难度的hash值,得到这个值,就是挖到矿。这个算法过程被称为“共识机制”,也就是通过什么形式来决定谁拥有记账权,共识机制有很多种,区块链采用哪种共识机制最佳,完全是由区块链的实际目的结合经济学道理来选择。

除了这些,区块链里面的加密比比皆是,这些加密规则和算法,使得整个区块链遵循一种规律,让篡改数据的成本特别高,以至于参与的人对篡改数据都没有兴趣,甚至忌惮。这又是玄学的地方。

针对这些不可篡改的特性,我们是不是能够解决一开始提出的问题呢。

用js来写一段区块链的代码,来解决小明的困惑。

三、【实战】用JavaScript来写一个基本的区块链demo。

实现一个基本的区块链

  1. 创建区块

区块链是由许许多多的区块链接在一起的(这听上去好像没毛病..)。链上的区块通过某种方式允许我们检测到是否有人操纵了之前的任何区块。

那么我们如何确保数据的完整性呢?每个区块都包含一个基于其内容计算出来的hash。同时也包含了前一个区块的hash。

下面是一个区块类用JavaScript写出来大致的样子:采用构造函数初始化区块的属性。

在这里的哈希值是无法修改的。我们能够看到,哈希值是由多个元素组成的,一旦一个哈希值受到了修改,意味着previousHash被修改了,这个时候如果想要继续修改就要对下一个区块进行操作,否则修改的区块就不具有意义了。而哈希值的计算非常耗时,同时修改51%以上的节点基本不可能,所以,这种联动机制也就保证了其不可修改的特性。

const crypto = require('crypto');class Block {constructor(previousHash, timestamp, data) {this.previousHash = previousHash;this.timestamp = timestamp;this.data = data;this.nonce = 0;this.hash = this.calculateHash();}// 计算区块的哈希值calculateHash() {return crypto.createHash('sha256').update(this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce).digest('hex');}
}
  1. 创建链

我们通过创建包含创世区块的数组来初始化整个链。这样一来,第一个区块是特殊的,因为他并没有指向前一个区块。并且添加了两个方法:

  • getLatestBlock()返回我们区块链上最新的区块。

  • addBlock()负责将新的区块添加到我们的链上。为此,我们将前一个区块的hash添加到我们新的区块中。这样我们就可以保持整个链的完整性。因为只要我们变更了最新区块的内容,我们就需要重新计算它的hash。当计算完成后,我将把这个区块推进链里(一个数组)。

最后,我创建一个isChainValid()来确保没有人篡改过区块链。它会遍历所有的区块来检查每个区块的hash是否正确。它会通过比较previousHash来检查每个区块是否指向正确的上一个区块。如果一切都没有问题它会返回true否则会返回false

class Blockchain{constructor() {this.chain = [this.createGenesisBlock()];}// 创建当前时间下的区块(创世块)createGenesisBlock() {return new Block(0, "20/05/2022", "Genesis block", "0");}// 获得区块链上最新的区块getLatestBlock() {return this.chain[this.chain.length - 1];}// 将新的区块添加到链上addBlock(newBlock) {newBlock.previousHash = this.getLatestBlock().hash;newBlock.hash = newBlock.calculateHash();this.chain.push(newBlock);}// 验证区块链是否被篡改。// 遍历每个区块的hash值是否正确&&每个区块的指向previousHash是否正确。isChainValid() {for (let i = 1; i < this.chain.length; i++){const currentBlock = this.chain[i];const previousBlock = this.chain[i - 1];if (currentBlock.hash !== currentBlock.calculateHash()) {return false;}if (currentBlock.previousHash !== previousBlock.hash) {return false;}}return true;}
}
  1. 使用

我们的区块链类已经写完啦,可以真正的开始使用它了!

这里,我们创建了一个区块链的实例,并在其中添加区块。其中的数据就写成了小明对于世界杯冠军的预言。

let firstClain = new Blockchain();
firstClain.addBlock(new Block(0, "21/05/2022", { champion: 'Spain'}));
firstClain.addBlock(new Block(1, "22/05/2022", { champion: 'China'}));// 检查是否有效(将会返回true)
console.log('firstClain valid? ' + firstClain.isChainValid(), firstClain.chain);// 现在尝试操作变更数据
firstClain.chain[1].data = {  champion: 'korea'  }; // 再次检查是否有效 (将会返回false)
console.log("firstClain valid? " + firstClain.isChainValid(), firstClain.chain);
  1. 尝试修改数据

我会在一开始通过运行isChainValid()来验证整个链的完整性。我们操作过任何区块,所以它会返回true。

之后我将链上的第一个(索引为1)区块的数据进行了变更。之后我再次检查整个链的完整性,发现它返回了false。我们的整个链不再有效了。

// 检查是否有效(将会返回true)
console.log('firstClain valid? ' + firstClain.isChainValid(), firstClain.chain);// 现在尝试操作变更数据
firstClain.chain[1].data = {  champion: 'korea'  }; // 再次检查是否有效 (将会返回false)
console.log("firstClain valid? " + firstClain.isChainValid(), firstClain.chain);

POW(proof-of-work)工作量证明

POW是在第一个区块链被创造之前就已经存在的一种机制。这是一项简单的技术,通过一定数量的计算来防止滥用。工作量是防止垃圾填充和篡改的关键。如果它需要大量的算力,那么填充垃圾就不再值得。

比特币通过要求hash以特定0的数目来实现POW。这也被称之为难度

不过等一下!一个区块的hash怎么可以改变呢?在比特币的场景下,一个区块包含有各种金融交易信息。我们肯定不希望为了获取正确的hash而混淆了那些数据。

为了解决这个问题,区块链添加了一个nonce值。Nonce是用来查找一个有效Hash的次数。而且,因为无法预测hash函数的输出,因此在获得满足难度条件的hash之前,只能大量组合尝试。寻找到一个有效的hash(创建一个新的区块)在圈内称之为挖矿。

在比特币的场景下,POW确保每10分钟只能添加一个区块。你可以想象垃圾填充者需要多大的算力来创造一个新区块,他们很难欺骗网络,更不要说篡改整个链。

暂时无法在飞书文档外展示此内容

我们该如何实现呢?我们先来修改我们区块类并在其构造函数中添加Nonce变量。我会初始化它并将其值设置为0。

constructor(previousHash, timestamp, data) {this.previousHash = previousHash;this.timestamp = timestamp;this.data = data;// 工作量this.nonce = 0;this.hash = this.calculateHash();}

我们还需要一个新的方法来增加Nonce,直到我们获得一个有效hash。强调一下,这是由难度决定的。所以我们会收到作为参数的难度。

// 工作量计算mineBlock(difficulty) {while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')) {this.nonce++;this.hash = this.calculateHash();}

最后,我们还需要更改一下calculateHash()函数。因为目前他还没有使用Nonce来计算hash。

// 计算区块的哈希值calculateHash() {return crypto.createHash('sha256').update(this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce).digest('hex');}

将它们结合在一起,你会得到如下所示的区块类:

class Block {constructor(previousHash, timestamp, data) {this.previousHash = previousHash;this.timestamp = timestamp;this.data = data;// 工作量this.nonce = 0;this.hash = this.calculateHash();}// 计算区块的哈希值calculateHash() {return crypto.createHash('sha256').update(this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce).digest('hex');}// 工作量计算mineBlock(difficulty) {while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')) {this.nonce++;this.hash = this.calculateHash();}}
}

修改区块链

现在,我们的区块已经拥有Nonce并且可以被开采了,我们还需要确保我们的区块链支持这种新的行为。让我们先在区块链中添加一个新的属性来跟踪整条链的难度。我会将它设置为2(这意味着区块的hash必须以2个0开头)。

constructor() {this.chain = [this.createGenesisBlock()];this.difficulty = 2;
}

现在剩下要做的就是改变addBlock()方法,以便在将其添加到链中之前确保实际挖到该区块。下面我们将难度传给区块。

addBlock(newBlock) {newBlock.previousHash = this.getLatestBlock().hash;newBlock.mineBlock(this.difficulty);this.chain.push(newBlock);
}

大功告成!我们的区块链现在拥有了POW来抵御攻击了。

测试

现在让我们来测试一下我们的区块链,看看在POW下添加一个新区块会有什么效果。我将会使用之前的代码。我们将创建一个新的区块链实例然后往里添加2个区块。

let firstClain = new Blockchain();
firstClain.addBlock(new Block(0, "21/05/2022", { champion: 'Spain'}));
firstClain.addBlock(new Block(1, "22/05/2022", { champion: 'China'}));// 检查是否有效(将会返回true)
console.log('firstClain valid? ' + firstClain.isChainValid(), firstClain.chain);// 现在尝试操作变更数据
firstClain.chain[1].data = {  champion: 'korea'  }; // 再次检查是否有效 (将会返回false)
console.log("firstClain valid? " + firstClain.isChainValid(), firstClain.chain);

如果你运行了上面的代码,你会发现添加新区块依旧非常快。这是因为目前的难度只有2(或者你的电脑性能非常好)。

如果你创建了一个难度为5的区块链实例,你会发现你的电脑会花费大概十秒钟来挖矿。随着难度的提升,你的防御攻击的保护程度越高。

实际的难度系数与hash值

上面计算hash的过程其实就是一个简略版本的挖矿过程,也就是计算机来计算出一个相应的hash值,但就像上面的所提及的并不是所有的hash都能够满足,这个条件比较苛刻,使得绝大多数的hash都不能够满足要求,需要重新计算。

在区块链的协议中,有一个标准的常量和一个目标值。只有小于目标值的hash才可以被使用。用常量除以难度系数,可以得到目标值,显然,难度系数越大,目标值越小。

target = const / diffculty

否则,hash无效只能重新计算,而nonce的大小就计算了相应的工作量证明。

整体代码贴在下方

const crypto = require('crypto');class Block {constructor(previousHash, timestamp, data) {this.previousHash = previousHash;this.timestamp = timestamp;this.data = data;// 工作量this.nonce = 0;this.hash = this.calculateHash();}// 计算区块的哈希值calculateHash() {return crypto.createHash('sha256').update(this.previousHash + this.timestamp + JSON.stringify(this.data) + this.nonce).digest('hex');}// 工作量计算mineBlock(difficulty) {while (this.hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')) {this.nonce++;this.hash = this.calculateHash();}}
}class Blockchain{constructor() {this.chain = [this.createGenesisBlock()];this.difficulty = 5;}// 创建当前时间下的区块(创世块)createGenesisBlock() {return new Block(0, "20/05/2022", "Genesis block", "0");}// 获得区块链上最新的区块getLatestBlock() {return this.chain[this.chain.length - 1];}// 将新的区块添加到链上addBlock(newBlock) {newBlock.previousHash = this.getLatestBlock().hash;newBlock.mineBlock(this.difficulty);this.chain.push(newBlock);}// 验证区块链是否被篡改。// 遍历每个区块的hash值是否正确&&每个区块的指向previousHash是否正确。isChainValid() {for (let i = 1; i < this.chain.length; i++){const currentBlock = this.chain[i];const previousBlock = this.chain[i - 1];if (currentBlock.hash !== currentBlock.calculateHash()) {return false;}if (currentBlock.previousHash !== previousBlock.hash) {return false;}}return true;}
}module.exports.Blockchain = Blockchain;
module.exports.Block = Block;
const { Block, Blockchain } = require('./block-chain');let firstClain = new Blockchain();
firstClain.addBlock(new Block(0, "21/05/2022", { champion: 'Spain'}));
firstClain.addBlock(new Block(1, "22/05/2022", { champion: 'China'}));// 检查是否有效(将会返回true)
console.log('firstClain valid? ' + firstClain.isChainValid(), firstClain.chain);// 现在尝试操作变更数据
firstClain.chain[1].data = {  champion: 'korea'  }; // 再次检查是否有效 (将会返回false)
console.log("firstClain valid? " + firstClain.isChainValid(), firstClain.chain);

四、总结

回到一开始的问题.

小明用js用区块链的形式在世界本的开始之前把预测的内容存储在了这里。并且成功预测.

338f9e01722ab17f2fb9a41cfceba38d.png

这一次,终于没有之一,成功的在女朋友面前秀了一把。

本文从一个小故事引出区块链的相关内容,其作为一门新的技术和思路,提供了一些不可篡改,分布式数据库的观念,并用前端的js代码来写了一个小的demo。

当然其作为一种无人管理的不可随意篡改的分布式数据库确实没有很大的问题,但也有一些弊端,首先是链表的结构与hash值计算的困难导致其写入是数据的效率并不高,需要一定的时间才能保证所有的节点同步。第二、区块的计算所需要的一些无意义的计算,也是较为消耗能源的。

最后本文作为纯技术分享,无任何投资建议。希望大家喜欢~

参考文章

  1. https://juejin.cn/post/6844903541903982606

  1. https://juejin.cn/post/6844903557649399821

  1. https://juejin.cn/post/6844903575617798157

  1. https://juejin.cn/post/6844903734837772301

  1. https://mp.weixin.qq.com/s/feo6YuBv4x-UcsLOooLGlA

  1. https://juejin.cn/post/6844903607343513613

❤️ 谢谢支持

以上便是本次分享的全部内容,希望对你有所帮助^_^

喜欢的话别忘了 分享、点赞、收藏 三连哦~。

欢迎关注公众号 趣谈前端 收货大厂一手好文章~


http://chatgpt.dhexx.cn/article/Fg9EI9X6.shtml

相关文章

区块链相关技术学习总结(1)——区块链以及区块链技术入门详解

区块链是目前一个比较热门的新概念&#xff0c;蕴含了技术与金融两层概念。从技术角度来看&#xff0c;这是一个牺牲一致性效率且保证最终一致性的的分布式的数据库&#xff0c;当然这是比较片面的。从经济学的角度来看&#xff0c;这种容错能力很强的点对点网络&#xff0c;恰…

p7结构的数字信封

PKCS7的数字信封格式分为两种&#xff1a;带签名的数字信封和不带签名的数字信封。由于这个数字信封的生成过程比较复杂&#xff0c;所以这两种格式比较容易记混&#xff0c;导致都搞不清楚一个数字信封里面到底是存储的什么内容了。下面我就详细的解释一下&#xff0c;这两种数…

数字签名和数字信封

数字签名和数字信封 数字签名定义原理作用签名种类P7签名又分为两类&#xff1a;Attached签名Detached签名P1签名也称为裸签 验证签名验签的原理 数字信封定义原理作用 签名 、数字信封、证书的关系 数字签名 定义 用户用自己的【私钥】对原始数据的哈希摘要进行加密所得的数…

chewing的作业——数字信封实现文件传输

文件安全传输系统设计作业 通信模式&#xff1a;端到端通信 数字信封&#xff1a; 对称密码优点是加解密运算非常快&#xff0c;适合处理大批量数据&#xff0c;但其密码的分发与管理比较复杂。而非对称密码算法的特点是公钥和私钥分离&#xff0c;非常适合密钥的分发和管理。…

什么又是数字证书?(数字证书与数字签名什么关系?)数字信封、PGP又是啥?

什么是非对称加密&#xff1f; 什么是信息摘要&#xff1f; 什么是数字签名&#xff1f; 本节我们接着上面的内容继续&#xff0c;话说有了非对称加密技术、有了信息摘要技术、也有了数字签名技术&#xff0c;信息的安全传输是不是就万无一失了呢&#xff1f; 其实并不完全&a…

sm2格式数字信封加解密详解

sm2格式数字信封 0、参考链接 密码行业标准化技术委员会http://www.gmbz.org.cn/main/bzlb.html SM2密码算法使用规范http://www.gmbz.org.cn/main/viewfile/2018011001400692565.html SM2密码算法应用分析https://blog.csdn.net/arlaichin/article/details/23708155?utm_so…

数字签名和数字信封的比较

参考博客&#xff1a;数字签名与数字信封流程 相同点 都使用了非对称算法对密钥进行了加密 数字签名 重点&#xff1a;防止文本被篡改&#xff0c;防止抵赖 发送方将文本取摘要&#xff0c;再生成一个密钥对摘要加密&#xff0c;同时该密钥使用自己的私钥进行非对称加密&am…

密码学~~~数字信封

#本文仅供参考有不足之处请指出 一、概括 数字信封是公钥密码体制在实际中的一个应用&#xff0c;是用加密技术来保证只有规定的特定收信人才能阅读通信的内容。数字信封的功能类似于普通信封&#xff0c;普通信封在法律的约束下保证只有收信人才能阅读信的内容&#xff1b;数…

数字信封工作原理

数字信封是指发送方使用接收方的公钥来加密对称密钥后所得的数据&#xff0c;其目的是用来确保对称密钥传输的安全性。采用数字信封时&#xff0c;接收方需要使用自己的私钥才能打开数字信封得到对称密钥。 数字信封的加/解密过程如图1-19所示。甲也要事先获得乙的公钥&#xf…

RSA+AES数字信封加解密设计

登录认证、鉴权这些都做好了过后。就开始我们的加密设计了、这里采用了简化数字信封进行加密。首先客户端&#xff08;浏览器&#xff09;先请求一份RSA非对称密钥、如果我们采用了openresty或者有能力在nginx开发C模块的插件&#xff0c;就可以在这里保留一份用户的私钥&#…

数字信封加密

OpenSSL 是目前 PHP 甚至是整个开发圈中的数据加密事实标准&#xff0c;包括 HTTPS/SSL 在内的加密都是它的实际应用&#xff0c; OpenSSL 提供了对称和非对称加密的形式&#xff0c;也就是我们日常中最普遍的两种加密方式。 那么&#xff0c;它和 Hash 类的加密有什么不同吗&…

p7数字信封

PKCS7的数字信封格式分为两种&#xff1a;带签名的数字信封和不带签名的数字信封。由于这个数字信封的生成过程比较复杂&#xff0c;所以这两种格式比较容易记混&#xff0c;导致都搞不清楚一个数字信封里面到底是存储的什么内容了。下面我就详细的解释一下&#xff0c;这两种数…

数字信封原理

数字信封是指发送方使用接收方的公钥来加密对称密钥后所得的数据&#xff0c;其目的是用来确保对称密钥传输的安全性。采用数字信封时&#xff0c;接收方需要使用自己的私钥才能打开数字信封得到对称密钥。 数字信封的加/解密过程如图所示。甲也要事先获得乙的公钥&#xff0c;…

PKCS7数字信封简述

1、数字信封的概念 数字信封,英文是Digital Envelope,望文生义,就可以知道将需要传递的数据,通过加密的方式包裹起来。 数字信封的准确定义,在《PKCS #7: Cryptographic Message Syntax Standard》标准的第10章中给出,原话是:“加密的内容,以及对内容解密的密钥被加密…

什么是数字信封?

一、什么是数字信封 数字信封是公钥密码体制在实际中的一个应用&#xff0c;是用加密技术来保证只有规定的特定收信人才能阅读通信的内容。 在数字信封中&#xff0c;信息发送方采用对称密钥来加密信息内容&#xff0c;然后将此对称密钥用接收方的公开密钥来加密&#xff08;这…

数据来源渠道及采集工具_几款简单好用的爬虫抓取数据采集工具

新朋友点上方蓝字“Office交流网”快速关注 1. 火车头采集器 火车采集器我们也一直在用&#xff0c;是老牌的采集工具了。它不仅可做抓取工具&#xff0c;也可以做数据清洗、分析、挖掘已经可视化等工作。数据源可来源于网页&#xff0c;网页中能看到的内容和不可看到都可以通过…

爬虫抓取新浪微博数据

工具&#xff1a;云采爬虫 目标&#xff1a;抓取某个博主的全部微博 分析网页结构&#xff1a; 我们抓取的思路是模拟浏览器自动访问页面抓取。 我们来看一下页面结构&#xff0c;首先每个微博列表&#xff0c;必须进行三四次的下拉加载&#xff0c;如果底部有个翻页的按钮…

python3 爬虫抓取股市数据

python3 爬虫抓取股市数据 爬虫抓取数据的一般步骤代码运行结果小结注意事项 爬虫抓取数据的一般步骤 1、确定需要抓取的网站2、分析url&#xff0c;找到url的的变化规律3、分析页面的数据4、获取页面数据5、提取需要爬取的数据6、写入数据库或写入文件代码 import requests i…

Python_爬虫数据存入数据库(超详细过程

目录 一、新建项目 二、程序的编写 三、数据的爬取 一、新建项目 1.在cmd窗口输入scrapy startproject [项目名称] 创建爬虫项目 接着创建爬虫文件&#xff0c;scrapy genspider [爬虫名字] [爬虫域名] 打开pycharm项目&#xff0c;就可以看到生成的cblog.py文件 二、程序的…

爬虫抓取分页数据的简单实现

爬虫抓取分页数据的简单实现 昨天&#xff0c;我们已经利用Jsoup技术实现了一个简单的爬虫&#xff0c;原理很简单&#xff0c;主要是要先分析页面&#xff0c;拿到条件&#xff0c;然后就去匹配url&#xff0c;采用dome解析的方式循环抓取我们需要的数据&#xff0c;从而即可轻…