当前位置: 首页 > 编程日记 > 正文

python 获取用户ip_Python爬虫教程:你还在苦苦拉票吗?刷票小程序案例原理剖析!...

628a4756c32884bcbc60521a7fe1f3a5.png

你还在苦苦拉票吗?

  • 前言
  • 剖析投票原理
  • 处理思路
  • 具体实战
  • 主要流程
  • 具体细节python
  • 代码实例python
  • 具体细节java
  • 代码实现java
  • 总结

点击此处,获取海量Python学习资料!

前言

3c94866e6c51714d7a5495e68b2a78d3.png


现在生活中离不开各类的比赛,然而,各个比赛离不开投票,我们会清一色有时候找到我们的朋友在朋友圈发—帮宝贝投一票,帮某某老师,学生投一票。又或许你自己参加比赛,你在为你自己拉票。

剖析投票原理

作为一名程序员,你是否想为自己的生活开一点G呢?熟悉网络请求的我们,应该从问题根源分析问题。对于一个投票的网站。大致分为两类:

  • 登录类:
    这类网站是确实不太好操作,一般是每个账户每天能够刷若干票。因为账户的资源是有限的,我们很难通过获取大量的账户资源为我们服务。况且,一般的登录稍微大厂或者技术高点其中的js加密会比较复杂,对于普通人js水平不高很难行的通这条路。比如常见需要微信登录,qq登陆的网站投票,就很难开挂。
  • 非登录类:
    并不是所有网站都有腾讯的登录授权的,有很多他们自己的官网他们自己就是一个体系。这类网站普通人或许也感觉不到差异:投几票之后也不能投。然后纷纷找朋友帮忙投。剖析这类网站,既然没有登录机制,那么它就是根据ip机制进行鉴定。因为正常你的公网ip相对来说是稳定。所以正常一个用户只能投固定的几票。或许高级一点他会和浏览器信息结合鉴定,但这种还是比较少的。

处理思路

既然原理已经剖析完成,那么剩下的就是设计程序的问题了,对于一个点击投票的事件,它的实质就是一次http(post)请求,然后后台对数据进行更改。那么我们就可以对这个操作流程进行抓包,分析这个请求是那种类型,需要那些参数。然后根据这个请求模拟写出请求。

然而最重要的就是ip代理,你要用代理的ip去访问那个接口,让对方以为是你代理的那个ip再对他访问,所以你需要维护一个代理ip池。对于代理ip池,并不是什么高大上的东西,准确的来说就是一个集合中包含一些可用的ip,能够供我使用。市面上也有很多出售代理ip,也不贵。我用的是蘑菇代理。

具体实战

主要流程

碰巧,最近参加的一个比赛就有拉票环节,如果人为手动拉票的话效率地下,并且你肯定也不会愿意天天去舔人家求情。那就自己分析一波!

  1. 首先,打开你在的网站(有的手机端,电脑端好抓包可调),谷歌或者其他浏览器F12抓包,点击network,xhr准备(肯定是ajax请求不用想)。
  2. 分析这个请求的重要参数.(header)
    找到url和几个参数,就可以准备程序了。模拟请求了

具体细节python

因为这是多次请求,所以要考虑性能的问题和效率问题。不能让异常漫天飞,中断,ip白白浪费,或者苦苦等待吧。
对于代理ip,各家卖的虽然有些差异但是大体相同。大致均为卖数量,然后每个ip从开始被用后能够维持几分钟的使用。并且有的ip是不能用的,有的是高延迟的,这些在写程序的时候都要过滤掉。这里面就要考虑下这个程序额设计。

  1. 多线程:
    python虽然多线程有个全局锁大大的影响效率。但是对于io请求型多线程还是能有一定的提速的。因为io有大量的线程等待。多线程的模块大致为定义一个线程类,定义初始方法和run函数。然后在外面定义几个线程,让他们跑任务。
  2. ip处理和资源处理
    正常的ip代理是一群ip随机抽取其中作为代理ip,进行爬取任务,然后ip失效从ip池中删除。而url的链接一般放到线程安全的全局容器中一个个抛出。ip放到list或者redis中进行维护,做好try catch异常即可。但是这个刷票只有一个url。并且一个ip只能用有限次数。所以换个思路,url不需要容器维护。而ip用队列维护最好,并且python的队列是线程安全的。所以整个程序的架构也就很清晰了。只需要用个queue解析ip获取的格式进行相应储存。然后被消费,当少于一定个数时,请求api获取ip进行填充。
  3. 在预处理方面,以前介绍过另一个蘑菇代理使用和ip池类似的问题,可以预先参考。

代码实例python

import requests
import random
import time
import threading
from queue import Queue
def loadip():url2 = 'http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=f16367295e284173ae450fc38d9098b3&count=20&expiryDate=0&format=1&newLine=2'req = requests.get(url2)date = req.json()if(date['code'])!='3001':ipdate2 = date['msg']global ipdateipdate.extend(ipdate2)for va in ipdate2:que.put(va)print(ipdate)class downspider(threading.Thread):def __init__(self, threadname, que):threading.Thread.__init__(self)self.threadname = threadnameself.que = quedef run(self):print('start thread' + self.threadname)while True:try:print(self.name,end='')toupiaospider(que,self.threadname)except Exception as e:print(e,'888')break
def getproxies():b = ipdate[0]b=que.get()d = '%s:%s' % (b['ip'], b['port'])global proxiesproxies['http'] = dglobal msgmsg = breturn proxies
def toupiaospider(que,threadname):if (que.qsize() < 15):  # 拓展ip池loadip()proxies2=getproxies()for i in range(0,5):try:#formData['times']=ireq = requests.post(url, headers=header, data=formData, proxies=proxies2, timeout=1.5)res = req.json()if res['res']==2001 or req.status_code!=200:#ipdate.remove(msg)continueprint(threadname,res,que.qsize())except Exception as e:print('errror',e)# ipdate.remove(msg)if __name__ == '__main__':ipdate = []msg = {}proxies = {'http': ''}stadus = 0que = Queue()threads=[]#线程url='http://yunxin.163.com/api/vote/update'header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}formData = {'Referer':'http://yunxin.163.com/promotion/minichallenge/gallery?from=groupmessage&isappinstalled=0','id':'17','times':'1','activity':'minichallenge1'}proxies = {'http': '182.247.92.99:21136',}loadip()time.sleep(5)threadList = ['thread-1','thread-2','thread-3','thread-4','thread-4']for j in threadList:thread = downspider(j, que)thread.start()threads.append(thread)for t in threads:t.join()

结果

e170552236bce0657670ff2b64b8ef1d.png

具体细节java

在java中比较棘手的就是java自身对json和http请求的处理不太方便,需要借助第三方jar,并且一些操作稍显的繁琐。

首先java要弄清几点:

  1. 代理方式:
    java主要有两种代理方式,一种是jdk全局代理,另一种是net包下的proxy代理。对于多线程程序并且ip只能用一次的当然是用net的proxy代理。
  2. 解析json
    通过api获取ip,格式固定的,需要借助fastjson解析json串获取需要的信息。
  3. 线程安全问题。你可以用线程安全的blockqueue,当然其实你可以在操作队列的方法加上synchronized关键字也可以。你可以定义固定的线程每个线程任务多个。也可以用线程池定义多个线程类,每个线程完成一个任务。
  4. 网络请求虽然urlconnection可以实现,但是太繁琐,远比jsoup复杂。所以这里使用jsoup。

针对上面的问题。写了个demo测试进行预备,对于获取ip的api,大致这种格式

64201a870c0b10cc89655d639e087905.png


首先你要下载fastjson和jsoup的jar包。或者加入maven依赖。(可在maven官网下jar包)

然后写个demo跑一下

package com.bigsai;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class test2 {static int va=1;public static void main(String[] args) {String ti="{"code":"0","msg":[{"port":"40034","ip":"114.237.64.247"},{"port":"33257","ip":"223.240.210.250"},{"port":"39618","ip":"113.101.255.11"},{"port":"43151","ip":"183.135.106.62"},{"port":"41795","ip":"182.108.44.227"}]}";JSONObject jsonObject= JSON.parseObject(ti);String code=(String) jsonObject.get("code");JSONArray jsonArray=jsonObject.getJSONArray("msg");for(Object te:jsonArray){JSONObject team=(JSONObject) te;String ip=team.getString("ip");int port=team.getInteger("port");System.out.println(team " " ip " " port);}ExecutorService ex= Executors.newFixedThreadPool(10);for(int i=0;i<200;i ){threadtest threadtest=new threadtest();ex.execute(threadtest);}ex.shutdown();}static synchronized void addva()//去掉注释试试{va ;try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() " " va);}static class threadtest implements Runnable{@Overridepublic void run() {addva();}}
}

观察结果。打印,这些边角问题你就明白了。就可以设计java程序了。

代码实现java

package com.bigsai;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class wangyi {// 改成你自己的token已经被我改了static String ipurl = "http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=f16367295e284173ae3&count=20&expiryDate=0&format=1&newLine=2";/*** java的多线程和python略有不同,但也可以改成相似的 py是5个线程每个线程死循环任务,而java用线程池每个线程一个任务,只不过new了很多对象* * @param args*/static Queue q1;public static void main(String[] args) {q1=new ArrayDeque();//队列存放结构体 ip和portExecutorService ex= Executors.newFixedThreadPool(10);for(int i=0;i<200;i ){try {Proxy proxy=getproxies(q1);//获得代理ipvote vote=new vote(proxy);ex.execute(vote);}catch (Exception e){e.printStackTrace();}}ex.shutdown();}static synchronized Proxy getproxies(Queue q1) throws IOException// 上锁获得代理,因为ip只用一次,也可使用自带的线程安全队列{if (q1.size() < 15)// 扩充ip池{String jsonva = Jsoup.connect(ipurl).timeout(2500).get().text();JSONObject jsonObject = JSON.parseObject(jsonva);String code = (String) jsonObject.get("code");// 状态吗if (code.equals("0")) {// 正常返回接口JSONArray jsonArray = jsonObject.getJSONArray("msg");for (Object jsonobj : jsonArray) {JSONObject team = (JSONObject) jsonobj;String ip = team.getString("ip");int port = team.getInteger("port");proxynode node = new proxynode(ip, port);q1.add(node);}} elsereturn null;}proxynode proxynode = q1.poll();Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxynode.ip, proxynode.port));return proxy;}static class proxynode// 一个node储存ip和端口{String ip;int port;proxynode(String ip, int port) {this.ip = ip;this.port = port;}}static class vote implements Runnable {Proxy proxy;vote(Proxy proxy) {this.proxy = proxy;}public void dovote() throws IOException {//Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host", 8888));try {Connection connect = Jsoup.connect("http://yunxin.163.com/api/vote/update").timeout(2000);Map date=new HashMap();date.put("id","17");date.put("times","1");date.put("activity","minichallenge1");date.put("Referer","http://yunxin.163.com/promotion/minichallenge/gallery?from=groupmessage&isappinstalled=0");date.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");connect.data(date);connect.ignoreContentType(true);connect.proxy(proxy);Document doc=connect.post();System.out.println(Thread.currentThread().getName() " " proxy.address() " " doc.text());}catch (Exception e){System.out.println(e.toString());}}public void run() {try {for(int i=0;i<5;i ) {dovote();}} catch (IOException e) {e.printStackTrace();}}}
}

结果

dbad5e69034cd0efa5be905603cb2ff2.png

总结

在写爬虫还是python方便和简单。因为py对json支持较好(字典),而java强对象类型语法要求较严。但是在多线程方面java肯定是秒杀py的。因为py的多线程是(假)多线程。想提高速度的可以研究多进程。

这类问题本质不难的,做过一次就很简单了。这只是其中一种案例。提供一些思想和解决思路。遇到不同的问题可能需要不同的结构,方式去解决,这就需要融汇贯通。

相关文章:

下拉菜单被挡住了,DIV置于最底层的方法

网站常会用到一些 下拉菜单&#xff0c;&#xff0c;幻灯片&#xff0c;&#xff0c;&#xff0c;飘浮广告等。但经常会发现。幻灯片会挡住下拉菜单或者飘浮广告等。解决办法有下第一&#xff0c;可将幻灯片所在DIV 置于最底层。添加CSS如下style"z-index:-100;position: …

github的删除

github项目删除 首先找到你要删除的项目&#xff0c;点击开 复制项目名称然后找到Settings 将滚动条滑至底部&#xff0c;找到 Danger Zone 下的 Delete this repository 这里会弹出一个警告对话框 将该项目名称重新输一遍即可 这里会弹出账号重新确认&#xff0c;将密码在输入…

区块链的去中心化VS传统互联网的去中心化:技术与治理的双重困境

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 区块链的去中心化VS传统互联网的去中心化&#xff1a;技术与治理的双重困境11 主要观点&#xff1a; 1、传统互联网经典的去中心化项目BitTorrent…

第三章| 3.1文件处理

1、三元运算 简单条件语句&#xff1a; if 条件成立:val 1 else: val 2 改成三元运算&#xff1a; val 1 if 条件成立 else 2 2、文件处理 &#xff08;用python对硬盘上的文件操作&#xff09; 读 读取文件的三个方法&#xff1a;read()、readline()、readlines() 三个方法…

LR常见的报错处理方法

1.LR录制时不弹出IE浏览器 当一台主机上装有多个浏览器&#xff0c;LR录制脚本时&#xff0c;经常遇到打不开浏览器的情况&#xff0c;可以用下面的方法来解决 启动浏览器&#xff0c;打开Internet 选项对话框&#xff0c;切换到高级标签&#xff0c;去掉“启用第三方浏览器扩展…

均匀分布取某一点概率_概率和概率分布

概率与概率分布是统计学中的基础概念&#xff0c;在我们的高中的课本中就接触过了&#xff0c;如果有遗忘&#xff0c;一起来回顾一下吧&#xff01;知识点&#xff1a;概率概率分布一、概率说到概率&#xff0c;需要先了解一个概念&#xff0c;叫做随机试验。随机试验是指在相…

EOS共识机制——DPoS代理权益证明

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 区块链共识机制与它的演进&#xff0c;是由于区块链式去中心化而且分布式的系统&#xff0c;必须要有一套放诸四海皆准类似宪法的规则&#xff0c;来…

active mq topic消费后删除_Spring cloud stream 整合mq

说明&#xff1a;本案例win10环境测试scs(spring cloud stream)整合kfk(kafka)/rbt(rabbitmq)消息生产消费场景流程一、准备中间件环境(kfk/rbt)后续内容提供kfk与rbt的环境准备流程二、导入scs的依赖项目spring boot 版本&#xff1a;2.1.3.RELEASE引入spring cloud 版本&…

翻译的艺术 —— 无能为力的翻译,搞笑的音译

0. 无能为力的翻译 至尊宝&#xff1a;best sonny&#xff0c;乌龙&#xff1a;own goal&#xff0c;的粤语发音&#xff1b;1. 取其发音 word ⇒ 我的&#xff0c;word 妈呀&#xff0c; Need just word,word has word&#xff0c;你的就是我的&#xff0c;我的还是我的&#…

经常可能会用到的【函数节流和函数防抖】记录下,做下区分

今天突然被人问到&#xff0c;函数节流和函数防抖的区别是什么&#xff0c;结果我脑子一热直接举了个滚动条的粟子说是优化高频率执行的手段&#xff0c;就记得自己是用setTimeout来实现的。完了区别是什么&#xff1f;&#xff1f;哪个是哪个都蒙B了回家想想&#xff0c;有些东…

智能合约和区块链技术:入门指南

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 智能合约和区块链技术&#xff1a;入门指南 多年前&#xff0c;在没有数字合约和区块链技术存在的情况下&#xff0c;双方的合约往往以传统的方式进…

2. 尾部的零

题目 设计一个算法&#xff0c;计算出n阶乘中尾部零的个数 样例 11! 39916800&#xff0c;因此应该返回 2 题解 一开始就用最简单对1-n找出5的个数&#xff0c;然后超时了。虽然都直到是要找5&#xff0c;因为2肯定比5多&#xff0c;所以5的个数就是0的个数&#xff0c;只是计…

case when then else end

1、根据数据库表中特定的值进行排序显示 select * from tablename where order by case when columname then 1 wnen columname when 2 else 3 end 2、根据数据库中存的值根据情况对其进行赋值CASE sexWHEN 1 THEN 男WHEN 2 THEN 女 ELSE 其他 END --Ca…

python replace函数_Python3 replace()函数使用方法

描述 replace() 方法把字符串中的 old&#xff08;旧字符串&#xff09; 替换成 new(新字符串)&#xff0c;如果指定第三个参数max&#xff0c;则替换不超过 max 次。 语法replace()方法语法&#xff1a; str.replace(old, new[, max]) 参数 old -- 将被替换的子字符串。 new -…

EOS技术知识介绍

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 EOS 简介 EOS&#xff1a;EOS可以理解为Enterprise Operation System&#xff0c;即为商用分布式应用设计的一款区块链操作系统。EOS是EOS软件引入…

团体程序设计天梯赛-练习集-L1-044. 稳赢

L1-044. 稳赢 大家应该都会玩“锤子剪刀布”的游戏&#xff1a;两人同时给出手势&#xff0c;胜负规则如图所示&#xff1a; 现要求你编写一个稳赢不输的程序&#xff0c;根据对方的出招&#xff0c;给出对应的赢招。但是&#xff01;为了不让对方输得太惨&#xff0c;你需要每…

currenttimemillis 毫秒还是秒_Elasticsearch(ES)如何做到亿级数据查询毫秒级返回

前言&#xff1a;这个问题其实是更面向原理及实操方面的内容。换个问法&#xff0c;可以是这样来问&#xff1a;ES 在数据量很大的情况下(数十亿级别)如何提高查询效率&#xff1f;为了精简&#xff0c;如下内容将Elasticsearch简称为ES如果你仅仅是用过ES&#xff0c;对于这个…

分布式系统的时间顺序

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 分布式系统的时间顺序 区块链被认为是分布式的系统&#xff0c;分布式系统中由于多节点&#xff0c;通讯、物理位置等的问题&#xff0c;各节点间时…

JVM 老年代对象来源

一般情况是四种&#xff0c;但是尤其以第一种来源最多1.新生代对象每经历依次minor gc&#xff0c;年龄会加一&#xff0c;当达到年龄阀值会直接进入老年代。阀值大小一般为152.Survivor空间中年龄所有对象大小的总和大于survivor空间的一半&#xff0c;年龄大于或等于该年龄的…

[心跳] 使用心跳机制实现CS架构下多客户端的在线状态实时更新以及掉线自动重连...

此文讲述的内容是一个实际项目开发中的一部分内容&#xff0c;笔者将亲身经历写成文章。 【背景】 现 需要实现这样的功能&#xff1a;有多个客户端连着同一个服务器。服务器和客户端之间需要“互相”知道彼此的连接状态。比如在某一时刻&#xff0c;服务器需要知道当前有多少个…

python绝对值编程_Python-abs vs fabs

编辑&#xff1a;正如aix所建议的&#xff0c;比较速度差异的更好&#xff08;更公平&#xff09;方法是&#xff1a;In [1]: %timeit abs(5) 10000000 loops, best of 3: 86.5 ns per loop In [2]: from math import fabs In [3]: %timeit fabs(5) 10000000 loops, best of 3:…

如何搭建以太坊私有链

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 如何搭建以太坊私有链1 今天讲一下如何搭建以太坊私有连&#xff0c;当然了在你阅读这篇文章的时候&#xff0c;最好是有一定基础&#xff0c;比如…

Autocomplete 自动补全(Webform实战篇)

开篇语 因为项目中需要用到一个自动补全的功能&#xff0c;功能描述&#xff1a; 需求一&#xff1a;新增收件人的时候&#xff0c;自动下拉显示出数据库中所有的收件人信息&#xff08;显示的信息包括&#xff1a;姓名-收件地址-联系方式&#xff09; 需求二&#xff1a;选中一…

前端开发基础7(Bootstrap框架)

Bootstrap介绍 Bootstrap是Twitter开源的基于HTML、CSS、JavaScript的前端框架。 它是为实现快速开发Web应用程序而设计的一套前端工具包。 它支持响应式布局&#xff0c;并且在V3版本之后坚持移动设备优先。 为什么要使用Bootstrap&#xff1f; 在Bootstrap出现之前&#xff1…

python自动化测试难不难_Python测试自动化好学还是Pythonweb开发好学?

还是测试吧。。。 用动态语言搞开发&#xff0c;项目大了根本没法维护&#xff0c;而且还会bug层出不穷&#xff0c;任谁也Hold不住。真想搞开发&#xff0c;要么玩Java&#xff0c;要么玩C#。 下面举个例子。 比如一个游戏项目&#xff0c;是这样的(伪代码)&#xff1a;角色 l…

以太坊智能合约开发第二篇:理解以太坊相关概念

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 很多人都说比特币是区块链1.0&#xff0c;以太坊是区块链2.0。在以太坊平台上&#xff0c;可以开发各种各样的去中心化应用&#xff0c;这些应用构成…

【python之旅】python的基础二

一、集合的操作 1、什么是集合&#xff1f; 集合是一个无序的&#xff0c;不重复的数据组合&#xff0c;它的主要作用如下&#xff1a; 去重&#xff1a;把一个列表变成集合&#xff0c;就自动去重关系测试&#xff1a;测试两组数据之前的交集&#xff0c;差集&#xff0c;并集…

hash 值重复_程序员:判断对象是否重复,不重写equals和hashcode不行吗?

前言大家都知道如果要判断一个对象是否相同&#xff0c;都要在对象实体中重写equals和hashcode方法&#xff0c;那你知道为什么重写这两个方法就能根据自己定义的规则实现相等比较了吗&#xff1f;今天带大家来了解一下equals和hashcode重写的实现。set是如何去重的&#xff1f…

LazyT 延迟加载

namespace ConsoleAppTest {class Program{static void Main(string[] args){Lazy<Student> student new Lazy<Student>();//默认未初始化Console.WriteLine(student);//在第一次使用时才实例化Console.WriteLine(student.Value);Console.ReadLine();}public clas…

如何编写一个可升级的智能合约

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 如何编写一个可升级的智能合约 区块链信任基础的数据不可修改的特性&#xff0c;让它传统应用程序有一个很大的不同的地方是一经发布于区块链上就…