首页
文章分类
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
网上邻居
留言板
欣赏小姐姐
关于我
Search
登录
1
利用AList搭建家庭个人影音库
5,054 阅读
2
浅尝Restful Fast Request插件,一句话完成 逆向过程
4,746 阅读
3
完美破解The Economist付费墙
3,362 阅读
4
i茅台app接口自动化csharp wpf实现,挂机windows服务器每日自动预约
3,093 阅读
5
青龙面板基本使用并添加修改微信/支付宝步数脚本
2,536 阅读
Search
标签搜索
PHP
Laravel
前端
csharp
Python
安卓逆向
JavaScript
Java
爬虫
抓包
Git
winform
android
Fiddler
Vue
selenium
LeetCode
每日一题
简单题
docker
Hygge
累计撰写
102
篇文章
累计收到
451
条评论
首页
栏目
逆向网安
中英演讲
杂类教程
学习笔记
前端开发
汇编
数据库
.NET
服务器
Python
Java
PHP
Git
算法
安卓开发
生活记录
读书笔记
作品发布
人体健康
页面
网上邻居
留言板
欣赏小姐姐
关于我
用户登录
搜索到
102
篇与
的结果
2023-07-25
C# 生成程序目录避免生成多余的XML和pdb
1:用记事本打开你C#项目工程下的.csproj 文件2:搜索找到你的生成类型一行:比如我用的是'Release|x64'生成程序3:在此行下添加以下代码,即可以屏蔽随dll一起的xml和pdb文件在Release中生成<AllowedReferenceRelatedFileExtensions>.allowedextension</AllowedReferenceRelatedFileExtensions> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>x64</PlatformTarget> <DebugSymbols>false</DebugSymbols> <DebugType>none</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <AllowedReferenceRelatedFileExtensions>.allowedextension</AllowedReferenceRelatedFileExtensions> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <AllowedReferenceRelatedFileExtensions>.allowedextension</AllowedReferenceRelatedFileExtensions> </PropertyGroup> 生成程序目录去除pdb的另一方法:项目=>属性=>生成=>高级=>调试信息 选【无】
2023年07月25日
305 阅读
0 评论
0 点赞
2023-07-25
第三篇Android逆向:去除广告和弹窗
一、基本概念1.1 安卓四大组件组件描述Activity(活动)在应用中的一个Activity可以用来表示一个界面,意思可以理解为“活动”,即一个活动开始,代表 Activity组件启动,活动结束,代表一个Activity的生命周期结束。一个Android应用必须通过Activity来运行和启动,Activity的生命周期交给系统统一管理。Service(服务)Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。Broadcast Receiver(广播接收器)一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。Content Provider(内容提供者)作为应用程序之间唯一的共享数据的途径,Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android内置的许多数据都是使用Content Provider形式,供开发者调用的(如视频,音频,图片,通讯录等)1.2 activity的切换<!---声明实现应用部分可视化界面的 Activity,必须使用 AndroidManifest 中的 <activity> 元素表示所有 Activity。系统不会识别和运行任何未进行声明的Activity。-----> <activity android:label="@string/app_name" android:name="com.zj.wuaipojie.ui.MainActivity" android:exported="true"> <!--当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动--> <!---指明这个activity可以以什么样的意图(intent)启动---> <intent-filter> <!--表示activity作为一个什么动作启动,android.intent.action.MAIN表示作为主activity启动---> <action android:name="android.intent.action.MAIN" /> <!--这是action元素的额外类别信息,android.intent.category.LAUNCHER表示这个activity为当前应用程序优先级最高的Activity--> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.zj.wuaipojie.ui.ChallengeFirst" /> <activity android:name="com.zj.wuaipojie.ui.ChallengeFifth" android:exported="true" /> <activity android:name="com.zj.wuaipojie.ui.ChallengeFourth" android:exported="true" /> <activity android:name="com.zj.wuaipojie.ui.ChallengeThird" android:exported="false" /> <activity android:name="com.zj.wuaipojie.ui.ChallengeSecond" android:exported="false" /> <activity android:name="com.zj.wuaipojie.ui.AdActivity" /> 启动广告流程:启动Activity->广告Activity->主页Activity修改方法:1.修改加载时间2.Acitivity切换定位,修改Intent的Activity类名switch (position) { case 0: Intent intent = new Intent(); intent.setClass(it.getContext(), ChallengeFirst.class); it.getContext().startActivity(intent); return; case 1: Intent intent2 = new Intent(); intent2.setClass(it.getContext(), ChallengeSecond.class); it.getContext().startActivity(intent2); return; case 2: Intent intent3 = new Intent(); //new一个Intent, intent3.setClass(it.getContext(), AdActivity.class); //传入要切换的Acitivity的类名 it.getContext().startActivity(intent3); //启动对应的Activity return; case 3: Intent intent4 = new Intent(); intent4.setClass(it.getContext(), ChallengeFourth.class); it.getContext().startActivity(intent4); return; default: return; }1.3 Activity生命周期函数名称描述onCreate()一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。onStart()当Activity显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。onResume()这个方法在onStart()之后调用,也就是在Activity准备好与用户进行交互的时候调用,此时的Activity一定位于Activity栈顶,处于运行状态。onPause()这个方法是在系统准备去启动或者恢复另外一个Activity的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。onStop()这个方法是在Activity完全不可见的时候调用的。onDestroy()这个方法在Activity销毁之前调用,之后Activity的状态为销毁状态。onRestart()当Activity从停止stop状态恢进入start状态时调用状态。1.4 弹窗定位&堆栈分析修改方法:1.修改xml中的versioncode2.Hook弹窗(推荐算法助手开启弹窗定位)3.修改dex弹窗代码4.抓包修改响应体(也可以路由器拦截)1.5 布局优化1.开发者助手抓布局2.MT管理器xml搜索定位3.修改xml代码android:visibility="gone"二、练习2.1 去开屏广告首先定位到这个Activity弹出的广告的是com.zj.wuaipojie.ui.AdActivity,mt管理器进行搜索类名.method private final loadAd()V .registers 5 .line 27 new-instance v0, Landroid/os/Handler; invoke-direct {v0}, Landroid/os/Handler;-><init>()V new-instance v1, Lcom/zj/wuaipojie/ui/AdActivity$$ExternalSyntheticLambda0; invoke-direct {v1, p0}, Lcom/zj/wuaipojie/ui/AdActivity$$ExternalSyntheticLambda0;-><init>(Lcom/zj/wuaipojie/ui/AdActivity;)V // v2赋值0xbb8 即3000毫秒 = 3秒 const-wide/16 v2, 0xbb8 // 调用延时的方法postDelayed 意为3秒后广告结束 切入主窗口 // 这里的参数 vo 代表 Handler的引用 v1 表示Runnable的引用 v2表示时长的引用 v3没有用到忽略 invoke-virtual {v0, v1, v2, v3}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z return-void .end method2.1.1 修改广告时长了解v2寄存器存储广告时长后可以直接赋值为0x0变相实现跳过但其实还是会跳转到AdActivity2.1.2 修改Activity切换重新搜索Lcom/zj/wuaipojie/ui/AdActivity;类型选择代码,目的是定位在smali层面哪里调用了AdActivity就可以找到切换Activity的逻辑。2.1.3 修改AndroidManifest将启动类的名称直接修改为ChallengeThird不推荐,容易跳过应用内部加载数据的逻辑2.2 跳弹窗广告2.2.1 版本更新广告方式一:修改AndroidManifest.xml中的versionCode<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1"># 由1改成2即可过 </manifest> 方式二:直接注释掉弹窗代码1.直接根据文件内容搜索有新版本需要更新 得到布局文件为y4.xml2.使用Arsc编辑器打开resources.arsc得到布局名称为fragment_update,再在Dex编辑器++中根据代码搜索,得到对应的资源Id0x7f0b003a在搜索整数十六进制,拿到关键类DialogUtilsKt,这是一个工具类,只需要找到在主Activity中调用的位置进行注释即可。3.定位DialogUtilsKt的使用注释掉即可。2.2.2 普通弹窗分别是可回退跳过和不可回退跳过的类型。2.2.2.1 算法助手的使用勾选上后原先无法使用回退的弹窗也可以进行返回取消了。查看使用日志分析发现是在ChallengeThird.onCreate生命周期内调用的方法。 protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(2131427361); Context context = (Context) this; Builder builder = new Builder(context); builder.setTitle("这是二号广告标题"); builder.setMessage("这是二号广告内容"); builder.setCancelable(false); String str = "前往论坛"; builder.setPositiveButton(str, new ExternalSyntheticLambda1(this)); String str2 = "退出软件"; builder.setNegativeButton(str2, ExternalSyntheticLambda2.INSTANCE); builder.show(); new CommonDialog.Builder(context).setMessage("一号广告弹窗已就位").setNegativeButton(str2, ExternalSyntheticLambda3.INSTANCE).setMessageColor(-16777216).setPositiveButton(str, new ExternalSyntheticLambda0(this)).setWith(0.8f).create().show(); checkUpdate(); }直接切到smali下将两个show的调用注释即可。2.3 去横幅遮挡广告1.首先定位元素Id(Hex):0x7f0801ca直接将宽高改为0dp或添加属性android:visibility="gone"三、课后作业这里发现有三个方法 三处show调用。方法一: show全部注释掉即可。方法二:查看每个方法的调用找到真正的函数调用,并从调用处解决引用1.《安卓逆向这档事》四、恭喜你获得广告&弹窗静默卡:https://www.52pojie.cn/thread-1706691-1-1.html2.吾爱破解安卓逆向入门教程《安卓逆向这档事》四、恭喜你获得广告&弹窗静默卡:https://www.bilibili.com/video/BV14v4y1D7yA/3.算法助手!基于Xposed的通用Hook工具:https://bbs.kanxue.com/thread-267985.htm
2023年07月25日
640 阅读
0 评论
0 点赞
2023-07-24
第二篇Android逆向:初识smali破解vip
一、基本概念1.什么是JVM、Dalvik、ARTJVM是JAVA虚拟机,运行JAVA字节码程序Dalvik是Google专门为Android设计的一个虚拟机,Dalvik有专属的文件执行格式dex(Dalvik executable)Art(Android Runtime)相当于Dalvik的升级版,本质与Dalvik无异2.smali及其语法smali是Dalvik的寄存器语言,smali代码是dex反编译而来的。关键字名称注释.class类名.super父类名,继承的上级类名名称.source源名.field变量.method方法名.register寄存器.end method方法名的结束public公有protected半公开,只有同一家人才能用private私有,只能自己使用.parameter方法参数.prologue方法开始.line xxx位于第xxx行数据类型对应smali类型java类型注释Vvoid无返回值Zboolean布尔值类型,返回0或1Bbyte字节类型,返回字节Sshort短整数类型,返回数字Cchar字符类型,返回字符Iint整数类型,返回数字Jlong (64位 需要2个寄存器存储)长整数类型,返回数字Ffloat单浮点类型,返回数字Ddouble (64位 需要2个寄存器存储)双浮点类型,返回数字stringString文本类型,返回字符串Lxxx/xxx/xxxobject对象类型,返回对象常用指令关键字注释const重写整数属性,真假属性内容,只能是数字类型const-string重写字符串内容const-wide重写长整数类型,多用于修改到期时间。return返回指令if-eq全称equal(a=b),比较寄存器ab内容,相同则跳if-ne全称not equal(a!=b),ab内容不相同则跳if-eqz全称equal zero(a=0),z即是0的标记,a等于0则跳if-nez全称not equal zero(a!=0),a不等于0则跳if-ge全称greater equal(a>=b),a大于或等于则跳if-le全称little equal(a<=b),a小于或等于则跳goto强制跳到指定位置switch分支跳转,一般会有多个分支线,并根据指令跳转到适当位置iget获取寄存器数据其余指令可用语法工具查询定位方法:搜索弹窗关键字、抓取按钮id例子://一个私有、静态、不可变的方法 方法名 .method private static final onCreate$lambda-2(Lkotlin/jvm/internal/Ref$IntRef;Lcom/zj/wuaipojie/ui/ChallengeSecond;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/view/View;)Z //(这里面是方法的参数)这里是方法返回值类型,表示布尔值类型,返回假或真 .registers 7 //寄存器数量 .line 33 //代码所在的行数 iget p0, p0, Lkotlin/jvm/internal/Ref$IntRef;->element:I //读取p0(第一个参数,参考寄存器知识)中element的值赋值给p0 const/4 p5, 0x1 //p5赋值1 const/16 v0, 0xa //v0赋值10,在16进制里a表示10 if-ge p0, v0, :cond_15 //判断p0的值是否大于或等于v0的值(即p0的值是否大于或等于10),如果大于或等于则跳转到:cond_15 .line 34 //以下是常见的Toast弹窗代码 check-cast p1, Landroid/content/Context; //检查Context对象引用 const-string p0, "请先获取10个硬币哦" //弹窗文本信息,把""里的字符串数据赋值给p0 check-cast p0, Ljava/lang/CharSequence; //检查CharSequence对象引用 invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; //将弹窗文本、显示时间等信息传给p1 move-result-object p0 //结果传递给p0 invoke-virtual {p0}, Landroid/widget/Toast;->show()V //当看到这个Toast;->show你就应该反应过来这里是弹窗代码 goto :goto_31 //跳转到:goto_31 :cond_15 //跳转的一个地址 invoke-virtual {p1}, Lcom/zj/wuaipojie/ui/ChallengeSecond;->isvip()Z //判断isvip方法的返回值是否为真(即结果是否为1) move-result p0 //结果赋值给p0 if-eqz p0, :cond_43 //如果结果为0则跳转cond_43地址 const p0, 0x7f0d0018 //在arsc中的id索引,这个值可以进行查询 .line 37 invoke-virtual {p2, p0}, Landroid/widget/ImageView;->setImageResource(I)V //设置图片资源 const p0, 0x7f0d0008 .line 38 invoke-virtual {p3, p0}, Landroid/widget/ImageView;->setImageResource(I)V const p0, 0x7f0d000a .line 39 invoke-virtual {p4, p0}, Landroid/widget/ImageView;->setImageResource(I)V .line 40 sget-object p0, Lcom/zj/wuaipojie/util/SPUtils;->INSTANCE:Lcom/zj/wuaipojie/util/SPUtils; check-cast p1, Landroid/content/Context; const/4 p2, 0x2 //p2赋值2 const-string p3, "level" //sp的索引 invoke-virtual {p0, p1, p3, p2}, Lcom/zj/wuaipojie/util/SPUtils;->saveInt(Landroid/content/Context;Ljava/lang/String;I)V //写入数据 goto :goto_50 //跳转地址 :cond_43 check-cast p1, Landroid/content/Context; const-string p0, "\u8bf7\u5148\u5145\u503c\u5927\u4f1a\u5458\u54e6\uff01" //请先充值大会员哦! check-cast p0, Ljava/lang/CharSequence; invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object p0 invoke-virtual {p0}, Landroid/widget/Toast;->show()V :goto_50 return p5 //返回p5的值 .end method //方法结束 //判断是否是大会员的方法 .method public final isvip()Z .registers 2 const/4 v0, 0x0 //v0赋值0 return v0 //返回v0的值 .end method修改方法:修改判断、强制跳转、修改寄存器的值3.寄存器在smali里的所有操作都必须经过寄存器来进行:本地寄存器用v开头数字结尾的符号来表示,如v0、 v1、v2。 参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2。特别注意的是,p0不一定是函数中的第一个参数,在非static函数中,p0代指“this",p1表示函数的第一个 参数,p2代表函数中的第二个参数。而在static函数中p0才对应第一个参数(因为Java的static方法中没有this方法)二、实现修改教程中使用的是jadx来分析smail代码,然后通过mt管理器打包修改。最近逛看雪论坛发现一个神器GDA,可以分析并直接完成打包。目标: 长按一键三连按钮可以点亮图标2.1 定位关键类2.1.1 搜索关键字直接搜索关键字大会员2.1.2 抓取按钮id分析界面布局,获取控件Id-Hex切换Mt管理器,使用Dex编辑器++打开Classes.dex,搜索控件2.2 修改方式2.2.1 修改判断分析图按下R重打包运行2.2.2 强制跳转2.2.3 修改寄存器的值三、实战demo搜索关键字登录失败可以直接拿到密钥引用1.《安卓逆向这档事》三、初识smali,vip终结者:https://www.52pojie.cn/thread-1701353-1-1.html2.[原创]基于Smali即时编译的DEX静态补丁技术实现:https://bbs.kanxue.com/thread-278098.htm3.GDA-android-reversing-Tool:https://github.com/charles2gan/GDA-android-reversing-Tool4.GJoy Dex Analyzer(GDA),亚洲第一款全交互式的现代反编译器,同时也是世界上最早实现的dalvik字节码反编译器。:http://www.gda.wiki:9090/
2023年07月24日
537 阅读
0 评论
0 点赞
2023-07-23
第一篇Android逆向:App双开、汉化、基本内容修改
一、基本概念1.1 Magisk介绍Magisk 是一套用于定制 Android 的开源软件,支持高于 Android 5.0 的设备。以下是一些功能亮点:MagiskSU:为应用程序提供 root 访问权限Magisk 模块:通过安装模块修改只读分区MagiskHide:从根检测 / 系统完整性检查中隐藏 Magisk(Shamiko)MagiskBoot : 最完整的安卓启动镜像解包和重新打包工具1.2 Apk结构apk 全称 Android Package,它相当于一个压缩文件,只要在电脑上将apk后缀改为zip即可解压。文件注释assets目录存放APK的静态资源文件,比如视频,音频,图片等lib 目录armeabi-v7a基本通用所有android设备,arm64-v8a只适用于64位的android设备,x86常见用于android模拟器,其目录下的.so文件是c或c++编译的动态链接库文件META-INF目录保存应用的签名信息,签名信息可以验证APK文件的完整性,相当于APK的身份证(验证文件是否被修改)res目录res目录存放资源文件,包括图片,字符串等等,APK的脸蛋由他的layout文件设计AndroidMainfest.xml文件APK的应用清单信息,它描述了应用的名字,版本,权限,引用的库文件等等信息classes.dex文件classes.dex是java源码编译后生成的java字节码文件,APK运行的主要逻辑resources.arsc文件resources.arsc是编译后的二进制资源文件,它是一个映射表,映射着资源和id,通过R文件中的id就可以找到对应的资源二、 双开及原理双开:简单来说,就是手机同时运行两个或多个相同的应用,例如同时运行两个微信原理解释修改包名让手机系统认为这是2个APP,这样的话就能生成2个数据存储路径,此时的多开就等于你打开了两个互不干扰的APP修改Framework对于有系统修改权限的厂商,可以修改Framework来实现双开的目的,例如:小米自带多开通过虚拟化技术实现虚拟Framework层、虚拟文件系统、模拟Android对组件的管理、虚拟应用进程管理 等一整套虚拟技术,将APK复制一份到虚拟空间中运行,例如:平行空间以插件机制运行利用反射替换,动态代理,hook了系统的大部分与system—server进程通讯的函数,以此作为“欺上瞒下”的目的,欺骗系统“以为”只有一个apk在运行,瞒过插件让其“认为”自己已经安装。例如:VirtualApp2.1 修改包名NT管理器安装包提取点击提取的Apk,选择APK共存修改包名简单情况下实现APK共存2.2 修改Framework2.3 通过虚拟化技术实现2.4 以插件机制运行三、 汉化APK汉化:使用专门的工具对外文版的软件资源进行读取、翻译、修改、回写等一系列处理,使软件的菜单、对话框、提示等用户界面显示为中文,而程序的内核和功能保持不变,这个过程即为软件汉化基本上字符串都是在arsc里,建议一键汉化,然后再润色。少量没汉化到的字符串参考视频中的方法定位去逐个汉化。3.1 流程图这里还需要注意的是,如果要直装应用,那就应该先签名安装,看看是否有签名校验导致的闪退简单的汉化有三个分支Arsc汉化Xml汉化Dex汉化教程中还提到较为复杂的so层面的字符串资源3.2 Xml汉化汉化前:1.全局搜索文件内容Hello 52pojie2.字符常量池打开资源文件3.字符串编辑4.更新并自动签名5.完成3.3 Arsc汉化接着替换下方的俄文,使用开发者助手检索界面资源复制文本后再次使用MT管理器进行搜索Я не могу поверить, что это работает, почему?选择翻译模式定位到要翻译的字符串后进行编辑完成汉化3.4 dex汉化这次要替换掉 Reverse determines height, development determines depth.这段文本还是先搜索再在Dex编辑器++中搜索直接进行替换即可完成汉化四、修改应用名称和图标4.1 初识AndroidManifest.xmlAndroidManifest.xml文件是整个应用程序的信息描述文件,定义了应用程序中包含的Activity,Service,Content provider和BroadcastReceiver组件信息。每个应用程序在根目录下必须包含一个AndroidManifest.xml文件,且文件名不能修改。它描述了package中暴露的组件,他们各自的实现类,各种能被处理的数据和启动位置。属性定义versionCode版本号,主要用来更新,例如:12versionName版本名,给用户看的,例如:1.2package包名,例如:com.zj.52pj.demouses-permission android:name=""应用权限,例如:android.permission.INTERNET 代表网络权限android:label="@string/app_name"应用名称android:icon="@mipmap/ic_launcher"应用图标路径android:debuggable="true"应用是否开启debug权限4.2 修改测试切换到NT管理器修改成功五、修改应用内图标对图中的表情包进行替换首先找到对应的布局文件,查看ImageView的资源ID:@7F0D000B使用Arsc编辑方式打开resources.arsc,搜索资源ID再去搜索first_img定位图片哦~原来first_img已经在对应资源图片了,那我直接修改它的映射关系改成D2.png完成引用1.《安卓逆向这档事》一、模拟器环境搭建:https://www.52pojie.cn/thread-1695141-1-1.html2.《安卓逆向这档事》二、初识APK文件结构、双开、汉化、基础修改:https://www.52pojie.cn/thread-1695796-1-1.html3.吾爱破解安卓逆向入门教程《安卓逆向这档事》二、初识APK文件结构、双开、汉化、基础修改:https://www.bilibili.com/video/BV18G411j7gV/?spm_id_from=333.788&vd_source=33cfe7dc102c64b5cac16bcfaad7f2a84.[更新!]适用于几乎所有安卓模拟器(7+)安装magisk的教程-简单无脑向:https://www.52pojie.cn/thread-1583586-1-1.html5.【VirtualAPP 双开系列08】如何实现多开 - UID:https://blog.csdn.net/u014294681/article/details/116270479
2023年07月23日
564 阅读
0 评论
0 点赞
2023-07-13
解决RTSP推流前端切换视频导致播放黑屏频闪问题
解决RTSP推流前端切换视频导致播放黑屏频闪问题背景供应商那边设备类似于摄像头,推送的视频流格式是rtsp格式,需要进行转换到前端播放。实现效果是摄像头在前端页面展示类似实时视频直播,问题是一个页面有多个视频源,在多个源进行切换时会导致视频画面黑屏频闪。复现前提条件两个视频文件*.mp4nodejsffmpeg及配置环境变量客户端web页面1.依赖准备前端播放视频流需要导入jsmpeg-playerpackages.json... "dependencies": { "axios": "^1.4.0", "element-plus": "^2.3.5", "jsmpeg": "^1.0.0", "jsmpeg-player": "^3.0.3", "vue": "^3.2.47" }, ...App.vue<script setup> import { ref, watch, getCurrentInstance } from "vue"; import JsMpeg from "jsmpeg-player"; const ws = ref(null); const { proxy } = getCurrentInstance(); const videoObject = ref({}); // 用于存储当前正在播放的视频数据 /** * 视频的url构成规则为: rtsp://本机IP/自定义地址标识,后续将通过ffmpeg将对应视频转换为RTSP流,并通过TCP传输于该地址。 * 视频的port意义为: 不同的端口对应不同的视频,RTSP流通过TCP传输的地址前端不能直接对接,会将url发送给服务端,服务端进行接入后再于该端口进行ws推送。 */ const videoList = [ { label: "视频1-一人之下", name: "sp1", url: "rtsp://192.168.0.107/test", port: 8834, }, { label: "视频2-小猫咪", name: "sp2", url: "rtsp://192.168.0.107/test2", port: 8812, }, ]; // ... </script>2.页面准备重要:视频推流的展示是需要canvas标签,但是一个canvas标签多次复用就会导致黑屏频闪问题!!!所以将dom中的canvas标签移除,修改为每次点击按钮播放都动态创建一个canvas标签<template> <el-button v-for="item in videoList" :key="item.name" @click="playerVideo(item)" >{{ item.label }}</el-button > </template> <style scoped></style>3.播放实现const useWs = (data) => { // 建立一个新的ws视频流播放时先对旧的ws视频流进行释放 if (ws.value) ws.value.close(); // 移除所有canvas const canvasList = document.querySelectorAll("canvas"); canvasList.forEach((item) => { item.remove(); }); // 追加一个canvas#sp const sp = document.createElement("canvas"); sp.setAttribute("id", "sp"); document.body.appendChild(sp); // 与服务端建立ws通信,并未开始播放 ws.value = new WebSocket("ws://localhost:5001"); videoObject.value = data; }; // 向服务端发送信息是通过watch监听实现,当videoObject发生变化时调用,即当前视频对象切换 watch( () => videoObject.value, (newV, oldV) => { // 当ws连接打开时回调 ws.value.onopen = function () { // 向服务端发送欲播放的视频数据,服务端接收后会进行推流 ws.value.send(JSON.stringify(newV)); // 使用框架 建立ws视频流播放,不同的端口对应不同的视频。 new JsMpeg.Player(`ws://localhost:${newV.port}`, { canvas: document.getElementById('sp'), }); }; } ); const playerVideo = (e) => { useWs(e); };服务端node实现重要:ffmpeg环境变量的配置+运行目录放一个ffmpeg.exe1.依赖准备packages.json"dependencies": { "express": "^4.18.2", "node-ffmpeg-stream": "^1.1.0", "node-rtsp-stream": "^0.0.9", "node-rtsp-stream-jsmpeg": "^0.0.2", "ws": "^8.13.0" },index.jsconst Stream = require('node-ffmpeg-stream').Stream; const WebSocket = require('ws'); const ws = new WebSocket.Server({ port: 5001 }); const streams = new Map(); // 存储视频流的 Map2.端口推流ws.on('connection', (client) => { client.on('message', (msg) => { const data = JSON.parse(msg); console.log('开始播放'); // 下面固定格式 const stream = new Stream({ name: data.name, url: data.url, // eg: rtsp://192.168.0.107/test wsPort: data.port, // eg: 8834 options: { '-stats': '', // 没有必要值的选项使用空字符串 '-r': 30, // 具有必需值的选项指定键后面的值<br> } }); streams.set(data.name, stream); // 前端视频流切换时 + 页面刷新或关闭时触发,通知服务端停止推送当前流 client.on('close', () => { if (streams.has(data.name)) { const stream = streams.get(data.name); stream.stopStream(); streams.delete(data.name); console.log('连接已关闭'); } }); }); });ffmpeg转换流并进行传输这段代码使用 ffmpeg 工具来将本地的视频文件(test.mp4)转换为 RTSP 流,并将其通过 TCP 传输。让我逐行解释这段代码的含义:ffmpeg -stream_loop -1 -re -i "C:\Users\Administrator\Downloads\Video\test.mp4" -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://localhost/testffmpeg: 这是命令行中调用 ffmpeg 工具的命令。-stream_loop -1: 这个选项告诉 ffmpeg 无限循环输入文件。即使视频文件结束,它也会重新开始播放。-re: 这个选项告诉 ffmpeg 使用实时模式,以原始速度读取输入文件。在实时模式下,ffmpeg 将尽力按照视频的实际帧率发送流数据。-i "C:\Users\Administrator\Downloads\Video\test.mp4": 这是输入文件的路径。ffmpeg 将读取该文件作为输入。-rtsp_transport tcp: 这个选项指定了 RTSP 流的传输协议为 TCP。通过 TCP 传输可以提供更稳定的连接。-vcodec h264: 这个选项指定了视频编解码器为 H.264(AVC)。它将使用 H.264 编码视频流。-f rtsp: 这个选项指定了输出格式为 RTSP。rtsp://localhost/test: 这是输出的 RTSP 流的地址。ffmpeg 将流式传输的视频流发布到该地址。综上所述,这段代码的作用是使用 ffmpeg 将本地的视频文件转换为 RTSP 流,并通过 TCP 传输发布到 rtsp://localhost/test 地址上。这样其他支持 RTSP 协议的设备或应用程序就可以通过该地址来接收和播放该视频流输入命令如果卡着不动的话需要配合EasyDarwin流媒体服务,直接启动EasyDarwin后就可以了。EasyDarwinEasyDarwin 是一个开源的流媒体服务器软件,用于实现音视频流的传输和处理。它提供了一套完整的流媒体解决方案,包括流媒体推流、录制、转发、播放等功能。EasyDarwin 可以用于搭建自己的流媒体服务器,支持常见的音视频编码格式和传输协议,如 RTSP、RTMP、HLS 等。它具有跨平台的特性,可以在 Windows、Linux、macOS 等操作系统上运行。使用 EasyDarwin,您可以搭建一个可靠的流媒体服务器,从摄像头、音频设备或其他音视频源推送实时流,并将其传输到支持的客户端应用程序或播放器上进行播放。它也可以用于构建视频监控系统、直播平台、音视频会议等应用场景。EasyDarwin 的开源性质使得它具有灵活性和可定制性,您可以根据自己的需求进行定制和扩展。同时,它还提供了一些管理工具和 Web 控制台,方便用户进行配置和管理流媒体服务器。总的来说,EasyDarwin 是一个功能强大的开源流媒体服务器软件,可以帮助用户快速搭建自己的流媒体平台,并实现高质量的音视频流传输和处理。引用1.node-ffmpeg-stream:https://www.npmjs.com/package/node-ffmpeg-stream2.ffmpeg实现将视频文件转换成rtsp流:https://blog.csdn.net/weixin_44591652/article/details/123004247{cloud title="解决RTSP推流前端切换视频导致播放黑屏频闪问题.zip" type="bd" url="https://pan.baidu.com/s/1tQZu7ULVbBPLKF9w_EbTyw?pwd=pe4n" password="pe4n"/}
2023年07月13日
375 阅读
0 评论
0 点赞
2023-07-07
使用Frp实现内网穿透便于外网访问本机JavaWeb项目
使用Frp实现内网穿透便于外网访问本机JavaWeb项目背景在微信开发者工具里调用uni.getLocation调试没有效果,笔记本没有对应的传感器真机调试需要勾选微信小程序位置接口权限,由于后端部署在本机上,真机调试无法链接,所以进行一下内网穿透准备工作搭建一个完整的frp服务链,我们需要VPS一台(也可以是具有公网IP的实体机)访问目标设备(就是你最终要访问的设备)简单的Linux基础(会用cp等几个简单命令即可)文章中用到的端口别忘记设置安全组和宝塔防火墙!服务端设置SSH连接到VPS之后运行如下命令查看处理器架构,根据架构下载不同版本的frparch查看结果,如果是“X86_64“即可选择”amd64”,运行如下命令,根据架构不同,选择相应版本并进行下载wget https://github.com/fatedier/frp/releases/download/v0.51.0/frp_0.51.0_linux_amd64.tar.gz然后解压tar -zxvf frp_0.51.0_linux_amd64.tar.gz文件夹改个名,方便使用cp -r frp_0.51.0_linux_amd64 frp把解压出来的文件夹复制到你想要的目录下,为了方便我直接放在用户目录下了,进入该目录cd frp查看一下文件ls -a我们只需要关注如下几个文件frpsfrps.inifrpcfrpc.ini前两个文件(s结尾代表server)分别是服务端程序和服务端配置文件,后两个文件(c结尾代表client)分别是客户端程序和客户端配置文件。因为我们正在配置服务端,可以删除客户端的两个文件rm frpc rm frpc.ini然后修改frps.ini文件vim frps.ini这个文件应有如下格式[common] bind_port = 7000 dashboard_port = 7500 token = 12345678 dashboard_user = admin dashboard_pwd = admin vhost_http_port = 7880 vhost_https_port = 7843 subdomain_host = lisok.cn 如果没有必要,端口均可使用默认值,token、user和password项请自行设置。“bind_port”表示用于客户端和服务端连接的端口,这个端口号我们之后在配置客户端的时候要用到。“dashboard_port”是服务端仪表板的端口,若使用7500端口,在配置完成服务启动后可以通过浏览器访问 x.x.x.x:7500 (其中x.x.x.x为VPS的IP)查看frp服务运行信息。“token”是用于客户端和服务端连接的口令,请自行设置并记录,稍后会用到。“dashboard_user”和“dashboard_pwd”表示打开仪表板页面登录的用户名和密码,自行设置即可。“vhost_http_port”和“vhost_https_port”用于反向代理HTTP主机时使用。"subdomain_host"自定义二级域名,后续在客户端会配置一个"subdomain",部署完成后将通过{subdomain}.{subdomain_host}:{vhost_http_port} 来访问自己的 web 服务。本来想通过ip来访问,但是不设置域名的话会出错 官方文档:https://gofrp.org/docs/features/http-https/subdomain/编辑完成后保存(vim保存如果不会请自行搜索)。之后我们就可以运行frps的服务端了./frps -c frps.ini如果看到屏幕输出这样一段内容,即表示运行正常,如果出现错误提示,请检查上面的步骤。2023/07/07 15:22:39 [I] [service.go:130] frps tcp listen on 0.0.0.0:7000 2023/07/07 15:22:39 [I] [service.go:172] http service listen on 0.0.0.0:7880 2023/07/07 15:22:39 [I] [service.go:193] https service listen on 0.0.0.0:7843 2023/07/07 15:22:39 [I] [service.go:216] Dashboard listen on 0.0.0.0:7500 2023/07/07 15:22:39 [I] [root.go:210] Start frps success此时访问 x.x.x.x:7500 并使用自己设置的用户名密码登录,即可看到仪表板界面服务端后台运行至此,我们的服务端仅运行在前台,如果Ctrl+C停止或者关闭SSH窗口后,frps均会停止运行,因而我们使用 nohup命令将其运行在后台。nohup后台程序管理或关闭相关命令可自行查询资料,上面这个连接中也有所提及。nohup ./frps -c frps.ini &输出如下内容即表示正常运行nohup: ignoring input and appending output to 'nohup.out'此时可先使用Ctrl+C关闭nohup,frps依然会在后台运行,使用jobs 或者 ps -aux | grep frps命令查看后台运行的程序在结果中我们可以看到frps正在后台正常运行[1]+ Running nohup ./frps -c frps.ini &此时访问 x.x.x.x:7500 依然可以打开仪表板界面,至此,服务端即设置完成,你可以关闭SSH窗口了。客户端设置frp的客户端就是我们想要真正进行访问的那台设备,大多数情况下应该会是一台Windows主机,因而本文使用Windows主机做例子;Linux配置方法类似,不再赘述。同样地,根据客户端设备的情况选择相应的frp程序进行下载,Windows下下载和解压等步骤不再描述。假定你下载了“frp_0.51.0_windows_amd64.zip”,将其解压在了C盘根目录下,并且将文件夹重命名为“frp”,可以删除其中的frps和frps.ini文件。用文本编辑器打开frpc.ini,与服务端类似,内容如下。[common] server_addr=116.xxx.xxx.xxx server_port=7000 token=12345678 [web] type=http local_port=8085 remote_port=7880 subdomain=nwys # 仅仅复制以上即可,以下是其他协议的例子,不必复制 [rdp] type = tcp local_ip = 127.0.0.1 local_port = 3389 remote_port = 7001 [smb] type = tcp local_ip = 127.0.0.1 local_port = 445 remote_port = 7002其中common字段下的三项即为服务端的设置。“server_addr”为服务端IP地址,填入即可。“server_port”为服务器端口,填入你设置的端口号即可,如果未改变就是7000“token”是你在服务器上设置的连接口令,原样填入即可。自定义规则frp实际使用时,会按照端口号进行对应的转发,原理如下图所示。上面frpc.ini的rdp、smb字段都是自己定义的规则,自定义端口对应时格式如下。“[xxx]”表示一个规则名称,自己定义,便于查询即可。“type”表示转发的协议类型,有TCP和UDP等选项可以选择,如有需要请自行查询frp手册。“local_port”是本地应用的端口号,按照实际应用工作在本机的端口号填写即可。“remote_port”是该条规则在服务端开放的端口号,自己填写并记录即可。RDP,即Remote Desktop 远程桌面,Windows的RDP默认端口是3389,协议为TCP,建议使用frp远程连接前,在局域网中测试好,能够成功连接后再使用frp穿透连接。SMB,即Windows文件共享所使用的协议,默认端口号445,协议TCP,本条规则可实现远程文件访问。配置完成frpc.ini后,就可以运行frpc了frpc程序不能直接双击运行!使用命令提示符或Powershell进入该目录下cd C:\frp并执行./frpc -c frpc.ini运行frpc程序,窗口中输出如下内容表示运行正常。2023/07/07 16:14:56 [I] [service.go:205] login to server success, get run id [2b65b4e58a5917ac], server udp port [0] 2023/07/07 16:14:56 [I] [proxy_manager.go:136] [2b65b4e58a5917ac] proxy added: [rdp smb] 2023/07/07 16:14:56 [I] [control.go:143] [smb] start proxy success 2023/07/07 16:14:56 [I] [control.go:143] [rdp] start proxy success不要关闭命令行窗口,此时可以在局域网外使用相应程序访问 x.x.x.x:xxxx (IP为VPS的IP,端口为自定义的remote_port)即可访问到相应服务。工具使用参考引用7的地址软件设置中的参数不包含域名设置,所以建议手动编辑一下配置文件再使用软件托管。引用frp官网-简单、高效的内网穿透工具:https://gofrp.org/frp github release:https://github.com/fatedier/frp/releasesfrp document:https://gofrp.org/docs/overview/使用frp进行内网穿透:https://sspai.com/post/52523使用frp进行内网穿透:https://blog.csdn.net/qq_41743601/article/details/127461156新手入门 - 详解 frp 内网穿透 frpc.ini 配置:https://www.ioiox.com/archives/79.htmlCnFRP控制台-内网映射外网访问的工具 : [https://www.52pojie.cn/thread-1647522-1-1.html]
2023年07月07日
309 阅读
0 评论
0 点赞
2023-07-03
青龙面板基本使用并添加修改微信/支付宝步数脚本
青龙面板使用青龙面板安装# curl -sSL get.docker.com | sh docker run -dit \ -v $PWD/ql/data:/ql/data \ -p 5700:5700 \ # 部署路径非必须,以斜杠开头和结尾,比如 /test/ -e QlBaseUrl="/" \ --name qinglong \ --hostname qinglong \ --restart unless-stopped \ whyour/qinglong:latest安装完成后进入面板1.安装运行依赖勾选自动拆分nodejs依赖:request canvas cheerio js-base64 dotenv magic tough-cookie ws@7.4.3 require requests date-fns ts-md5 typescript json5 axios@v0.27.2 crypto-js @types/node png-js node-telegram-bot-api fs jsdom form-data jieba tslib ds jsdom -g prettytable ql common node-jsencrypt juejin-helper moment global-agentpython3:bs4 telethon cacheout jieba PyExecJS ping3 canvas Crypto ds requests pycryptodomelinux:bizCode bizMsg lxml libc-dev gcc g++ libffi-dev python3-dev2.环境变量点击环境变量——点击新建环境变量——名称设为:JD_COOKIE—输入获取到Cookies的相关参数(获取方法:【点击进入】——然后用手机登录——登录后按F12——点击Application——点开Cookies——找到pt_key=?;pt_pin=?;——把对应的值替换到问号中即可,分号要保留这里名称是不能自定义的,一定要用JD_COOKIE注意事项:1、登录后不要退出账号,否则Cookies会失效3.脚本拉取脚本项目地址一:https://github.com/shufflewzc/faker2脚本项目地址二:https://github.com/shufflewzc/faker3脚本项目地址三:https://github.com/Gnuyoah/Thread脚本项目地址四:https://github.com/Akali5/jd-depot进入之后拷贝Clone地址:ql repo https://ghproxy.com/https://github.com/shufflewzc/faker2.git "jd_|jx_|gua_|jddj_|getJDCookie" "activity|backUp" "^jd[^_]|USER|function|utils|ZooFaker_Necklace.js|JDJRValidator_Pure|sign_graphics_validate|ql" # 直接使用github地址拉不下来的话就套个镜像 https://ghproxy.com/ + github地址创建完立即执行一下,拉取一下脚本4.自建一个修改步数脚本# -*- coding: utf8 -*- import requests,time,re,json from random import randint headers = { 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; MI 6 MIUI/20.6.18)' } #获取登录code def get_code(location): code_pattern = re.compile("(?<=access=).*?(?=&)") code = code_pattern.findall(location)[0] #print(code) return code #登录 def login(user,password): url1 = "https://api-user.huami.com/registrations/+86" + user + "/tokens" headers = { "Content-Type":"application/x-www-form-urlencoded;charset=UTF-8", "User-Agent":"MiFit/4.6.0 (iPhone; iOS 14.0.1; Scale/2.00)" } data1 = { "client_id":"HuaMi", "password":f"{password}", "redirect_uri":"https://s3-us-west-2.amazonaws.com/hm-registration/successsignin.html", "token":"access" } r1 = requests.post(url1,data=data1,headers=headers,allow_redirects=False) print(r1.text) location = r1.headers["Location"] #print(location) try: code = get_code(location) except: return 0,0 print("access_code获取成功!") print(code) url2 = "https://account.huami.com/v2/client/login" data2 = { "app_name":"com.xiaomi.hm.health", "app_version":"4.6.0", "code":f"{code}", "country_code":"CN", "device_id":"2C8B4939-0CCD-4E94-8CBA-CB8EA6E613A1", "device_model":"phone", "grant_type":"access_token", "third_name":"huami_phone", } r2 = requests.post(url2,data=data2,headers=headers).json() login_token = r2["token_info"]["login_token"] print("login_token获取成功!") print(login_token) userid = r2["token_info"]["user_id"] print("userid获取成功!") print(userid) return login_token,userid #主函数 def main(): login_token = 0 login_token,userid = login(user,password) if login_token == 0: print("登陆失败!") return "login fail!" t = get_time() app_token = get_app_token(login_token) date = time.strftime("%Y-%m-%d",time.localtime()) today = time.strftime("%F") data_json = '%5B%7B%22data_hr%22%3A%22%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FVv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0v%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0n%5C%2Fa%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1FK%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9PTFFpaf9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0j%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9K%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzf%5C%2F%5C%2F%5C%2F86%5C%2Fzr%5C%2FOv88%5C%2Fzf%5C%2FPf%5C%2F%5C%2F%5C%2F0v%5C%2FS%5C%2F8%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FSf%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fz3%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0r%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F9L%5C%2Fzb%5C%2FSf9K%5C%2F0v%5C%2FRf9H%5C%2Fzj%5C%2FSf9K%5C%2F0%5C%2F%5C%2FN%5C%2F%5C%2F%5C%2F%5C%2F0D%5C%2FSf83%5C%2Fzr%5C%2FPf9M%5C%2F0v%5C%2FOv9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzv%5C%2F%5C%2Fz7%5C%2FO%5C%2F83%5C%2Fzv%5C%2FN%5C%2F83%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fz%5C%2F%5C%2FNv83%5C%2Fzn%5C%2FXv84%5C%2Fzr%5C%2FPP84%5C%2Fzj%5C%2FN%5C%2F9e%5C%2Fzr%5C%2FN%5C%2F89%5C%2F03%5C%2FP%5C%2F89%5C%2Fz3%5C%2FQ%5C%2F9N%5C%2F0v%5C%2FTv9C%5C%2F0H%5C%2FOf9D%5C%2Fzz%5C%2FOf88%5C%2Fz%5C%2F%5C%2FPP9A%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fzz%5C%2FNv87%5C%2F0D%5C%2FOv84%5C%2F0v%5C%2FO%5C%2F84%5C%2Fzf%5C%2FMP83%5C%2FzH%5C%2FNv83%5C%2Fzf%5C%2FN%5C%2F84%5C%2Fzf%5C%2FOf82%5C%2Fzf%5C%2FOP83%5C%2Fzb%5C%2FMv81%5C%2FzX%5C%2FR%5C%2F9L%5C%2F0v%5C%2FO%5C%2F9I%5C%2F0T%5C%2FS%5C%2F9A%5C%2Fzn%5C%2FPf89%5C%2Fzn%5C%2FNf9K%5C%2F07%5C%2FN%5C%2F83%5C%2Fzn%5C%2FNv83%5C%2Fzv%5C%2FO%5C%2F9A%5C%2F0H%5C%2FOf8%5C%2F%5C%2Fzj%5C%2FPP83%5C%2Fzj%5C%2FS%5C%2F87%5C%2Fzj%5C%2FNv84%5C%2Fzf%5C%2FOf83%5C%2Fzf%5C%2FOf83%5C%2Fzb%5C%2FNv9L%5C%2Fzj%5C%2FNv82%5C%2Fzb%5C%2FN%5C%2F85%5C%2Fzf%5C%2FN%5C%2F9J%5C%2Fzf%5C%2FNv83%5C%2Fzj%5C%2FNv84%5C%2F0r%5C%2FSv83%5C%2Fzf%5C%2FMP%5C%2F%5C%2F%5C%2Fzb%5C%2FMv82%5C%2Fzb%5C%2FOf85%5C%2Fz7%5C%2FNv8%5C%2F%5C%2F0r%5C%2FS%5C%2F85%5C%2F0H%5C%2FQP9B%5C%2F0D%5C%2FNf89%5C%2Fzj%5C%2FOv83%5C%2Fzv%5C%2FNv8%5C%2F%5C%2F0f%5C%2FSv9O%5C%2F0ZeXv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1X%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9B%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FTP%5C%2F%5C%2F%5C%2F1b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9N%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%22%2C%22date%22%3A%222021-08-07%22%2C%22data%22%3A%5B%7B%22start%22%3A0%2C%22stop%22%3A1439%2C%22value%22%3A%22UA8AUBQAUAwAUBoAUAEAYCcAUBkAUB4AUBgAUCAAUAEAUBkAUAwAYAsAYB8AYB0AYBgAYCoAYBgAYB4AUCcAUBsAUB8AUBwAUBIAYBkAYB8AUBoAUBMAUCEAUCIAYBYAUBwAUCAAUBgAUCAAUBcAYBsAYCUAATIPYD0KECQAYDMAYB0AYAsAYCAAYDwAYCIAYB0AYBcAYCQAYB0AYBAAYCMAYAoAYCIAYCEAYCYAYBsAYBUAYAYAYCIAYCMAUB0AUCAAUBYAUCoAUBEAUC8AUB0AUBYAUDMAUDoAUBkAUC0AUBQAUBwAUA0AUBsAUAoAUCEAUBYAUAwAUB4AUAwAUCcAUCYAUCwKYDUAAUUlEC8IYEMAYEgAYDoAYBAAUAMAUBkAWgAAWgAAWgAAWgAAWgAAUAgAWgAAUBAAUAQAUA4AUA8AUAkAUAIAUAYAUAcAUAIAWgAAUAQAUAkAUAEAUBkAUCUAWgAAUAYAUBEAWgAAUBYAWgAAUAYAWgAAWgAAWgAAWgAAUBcAUAcAWgAAUBUAUAoAUAIAWgAAUAQAUAYAUCgAWgAAUAgAWgAAWgAAUAwAWwAAXCMAUBQAWwAAUAIAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWREAWQIAUAMAWSEAUDoAUDIAUB8AUCEAUC4AXB4AUA4AWgAAUBIAUA8AUBAAUCUAUCIAUAMAUAEAUAsAUAMAUCwAUBYAWgAAWgAAWgAAWgAAWgAAWgAAUAYAWgAAWgAAWgAAUAYAWwAAWgAAUAYAXAQAUAMAUBsAUBcAUCAAWwAAWgAAWgAAWgAAWgAAUBgAUB4AWgAAUAcAUAwAWQIAWQkAUAEAUAIAWgAAUAoAWgAAUAYAUB0AWgAAWgAAUAkAWgAAWSwAUBIAWgAAUC4AWSYAWgAAUAYAUAoAUAkAUAIAUAcAWgAAUAEAUBEAUBgAUBcAWRYAUA0AWSgAUB4AUDQAUBoAXA4AUA8AUBwAUA8AUA4AUA4AWgAAUAIAUCMAWgAAUCwAUBgAUAYAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAWwAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAeSEAeQ8AcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBcAcAAAcAAAcCYOcBUAUAAAUAAAUAAAUAAAUAUAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCgAeQAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcBgAeQAAcAAAcAAAegAAegAAcAAAcAcAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCkAeQAAcAcAcAAAcAAAcAwAcAAAcAAAcAIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCIAeQAAcAAAcAAAcAAAcAAAcAAAeRwAeQAAWgAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcBoAeScAeQAAegAAcBkAeQAAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAegAAegAAcAAAcAAAcBgAeQAAcAAAcAAAcAAAcAAAcAAAcAkAegAAegAAcAcAcAAAcAcAcAAAcAAAcAAAcAAAcA8AeQAAcAAAcAAAeRQAcAwAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcBEAcA0AcAAAWQsAUAAAUAAAUAAAUAAAUAAAcAAAcAoAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBYAegAAcAAAcAAAegAAcAcAcAAAcAAAcAAAcAAAcAAAeRkAegAAegAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAEAcAAAcAAAcAAAcAUAcAQAcAAAcBIAeQAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBsAcAAAcAAAcBcAeQAAUAAAUAAAUAAAUAAAUAAAUBQAcBYAUAAAUAAAUAoAWRYAWTQAWQAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAMAcAAAcAQAcAAAcAAAcAAAcDMAeSIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBQAeQwAcAAAcAAAcAAAcAMAcAAAeSoAcA8AcDMAcAYAeQoAcAwAcFQAcEMAeVIAaTYAbBcNYAsAYBIAYAIAYAIAYBUAYCwAYBMAYDYAYCkAYDcAUCoAUCcAUAUAUBAAWgAAYBoAYBcAYCgAUAMAUAYAUBYAUA4AUBgAUAgAUAgAUAsAUAsAUA4AUAMAUAYAUAQAUBIAASsSUDAAUDAAUBAAYAYAUBAAUAUAUCAAUBoAUCAAUBAAUAoAYAIAUAQAUAgAUCcAUAsAUCIAUCUAUAoAUA4AUB8AUBkAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAA%22%2C%22tz%22%3A32%2C%22did%22%3A%22DA932FFFFE8816E7%22%2C%22src%22%3A24%7D%5D%2C%22summary%22%3A%22%7B%5C%22v%5C%22%3A6%2C%5C%22slp%5C%22%3A%7B%5C%22st%5C%22%3A1628296479%2C%5C%22ed%5C%22%3A1628296479%2C%5C%22dp%5C%22%3A0%2C%5C%22lt%5C%22%3A0%2C%5C%22wk%5C%22%3A0%2C%5C%22usrSt%5C%22%3A-1440%2C%5C%22usrEd%5C%22%3A-1440%2C%5C%22wc%5C%22%3A0%2C%5C%22is%5C%22%3A0%2C%5C%22lb%5C%22%3A0%2C%5C%22to%5C%22%3A0%2C%5C%22dt%5C%22%3A0%2C%5C%22rhr%5C%22%3A0%2C%5C%22ss%5C%22%3A0%7D%2C%5C%22stp%5C%22%3A%7B%5C%22ttl%5C%22%3A18272%2C%5C%22dis%5C%22%3A10627%2C%5C%22cal%5C%22%3A510%2C%5C%22wk%5C%22%3A41%2C%5C%22rn%5C%22%3A50%2C%5C%22runDist%5C%22%3A7654%2C%5C%22runCal%5C%22%3A397%2C%5C%22stage%5C%22%3A%5B%7B%5C%22start%5C%22%3A327%2C%5C%22stop%5C%22%3A341%2C%5C%22mode%5C%22%3A1%2C%5C%22dis%5C%22%3A481%2C%5C%22cal%5C%22%3A13%2C%5C%22step%5C%22%3A680%7D%2C%7B%5C%22start%5C%22%3A342%2C%5C%22stop%5C%22%3A367%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A2295%2C%5C%22cal%5C%22%3A95%2C%5C%22step%5C%22%3A2874%7D%2C%7B%5C%22start%5C%22%3A368%2C%5C%22stop%5C%22%3A377%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A1592%2C%5C%22cal%5C%22%3A88%2C%5C%22step%5C%22%3A1664%7D%2C%7B%5C%22start%5C%22%3A378%2C%5C%22stop%5C%22%3A386%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A1072%2C%5C%22cal%5C%22%3A51%2C%5C%22step%5C%22%3A1245%7D%2C%7B%5C%22start%5C%22%3A387%2C%5C%22stop%5C%22%3A393%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A1036%2C%5C%22cal%5C%22%3A57%2C%5C%22step%5C%22%3A1124%7D%2C%7B%5C%22start%5C%22%3A394%2C%5C%22stop%5C%22%3A398%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A488%2C%5C%22cal%5C%22%3A19%2C%5C%22step%5C%22%3A607%7D%2C%7B%5C%22start%5C%22%3A399%2C%5C%22stop%5C%22%3A414%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A2220%2C%5C%22cal%5C%22%3A120%2C%5C%22step%5C%22%3A2371%7D%2C%7B%5C%22start%5C%22%3A415%2C%5C%22stop%5C%22%3A427%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A1268%2C%5C%22cal%5C%22%3A59%2C%5C%22step%5C%22%3A1489%7D%2C%7B%5C%22start%5C%22%3A428%2C%5C%22stop%5C%22%3A433%2C%5C%22mode%5C%22%3A1%2C%5C%22dis%5C%22%3A152%2C%5C%22cal%5C%22%3A4%2C%5C%22step%5C%22%3A238%7D%2C%7B%5C%22start%5C%22%3A434%2C%5C%22stop%5C%22%3A444%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A2295%2C%5C%22cal%5C%22%3A95%2C%5C%22step%5C%22%3A2874%7D%2C%7B%5C%22start%5C%22%3A445%2C%5C%22stop%5C%22%3A455%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A1592%2C%5C%22cal%5C%22%3A88%2C%5C%22step%5C%22%3A1664%7D%2C%7B%5C%22start%5C%22%3A456%2C%5C%22stop%5C%22%3A466%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A1072%2C%5C%22cal%5C%22%3A51%2C%5C%22step%5C%22%3A1245%7D%2C%7B%5C%22start%5C%22%3A467%2C%5C%22stop%5C%22%3A477%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A1036%2C%5C%22cal%5C%22%3A57%2C%5C%22step%5C%22%3A1124%7D%2C%7B%5C%22start%5C%22%3A478%2C%5C%22stop%5C%22%3A488%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A488%2C%5C%22cal%5C%22%3A19%2C%5C%22step%5C%22%3A607%7D%2C%7B%5C%22start%5C%22%3A489%2C%5C%22stop%5C%22%3A499%2C%5C%22mode%5C%22%3A4%2C%5C%22dis%5C%22%3A2220%2C%5C%22cal%5C%22%3A120%2C%5C%22step%5C%22%3A2371%7D%2C%7B%5C%22start%5C%22%3A500%2C%5C%22stop%5C%22%3A511%2C%5C%22mode%5C%22%3A3%2C%5C%22dis%5C%22%3A1268%2C%5C%22cal%5C%22%3A59%2C%5C%22step%5C%22%3A1489%7D%2C%7B%5C%22start%5C%22%3A512%2C%5C%22stop%5C%22%3A522%2C%5C%22mode%5C%22%3A1%2C%5C%22dis%5C%22%3A152%2C%5C%22cal%5C%22%3A4%2C%5C%22step%5C%22%3A238%7D%5D%7D%2C%5C%22goal%5C%22%3A8000%2C%5C%22tz%5C%22%3A%5C%2228800%5C%22%7D%22%2C%22source%22%3A24%2C%22type%22%3A0%7D%5D' finddate = re.compile(r'.*?date%22%3A%22(.*?)%22%2C%22data.*?') findstep = re.compile(r'.*?ttl%5C%22%3A(.*?)%2C%5C%22dis.*?') data_json = re.sub(finddate.findall(data_json)[0], today, str(data_json)) data_json = re.sub(findstep.findall(data_json)[0], step, str(data_json)) url = f'https://api-mifit-cn.huami.com/v1/data/band_data.json?&t={t}' head = { "Content-Type": "application/x-www-form-urlencoded", 'apptoken': f'{app_token}' } data = f'userid={userid}&last_sync_data_time=1597306380&device_type=0&last_deviceid=DA932FFFFE8816E7&data_json={data_json}' response = requests.post(url, data=data, headers=head).json() print(response) result = f"当前用户:{user}</br> 修改步数: {step} </br> 修改结果: "+ response['message'] server_send(result) qmsg_send(result) plus_send(result) print(result) return result #获取时间戳 def get_time(): url = 'http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp' response = requests.get(url,headers=headers).json() t = response['data']['t'] return t #获取app_token def get_app_token(login_token): url = f"https://account-cn.huami.com/v1/client/app_tokens?app_name=com.xiaomi.hm.health&dn=api-user.huami.com%2Capi-mifit.huami.com%2Capp-analytics.huami.com&login_token={login_token}&os_version=4.1.0" response = requests.get(url,headers=headers).json() app_token = response['token_info']['app_token'] print("app_token获取成功!") print(app_token) return app_token #server酱微信推送 def server_send(msg): if sckey == '': return server_url = "https://sc.ftqq.com/" + str(sckey) + ".send" data = { 'text': msg, 'desp': msg } requests.post(server_url, data=data) #Qmsg酱QQ推送 def qmsg_send(msg): if qkey == '': return qmsg_url = "https://qmsg.zendee.cn:443/send/" + str(qkey) data = { 'qq': f'{qq}', 'msg': msg } requests.post(qmsg_url, data=data) # PUSHPLUS推送 def plus_send(msg,title='小米运动助手',template ='markdown'): if plustoken == '': return url = 'http://www.pushplus.plus/send' data = { "token": plustoken, "title": title, "content": msg, "template":template } body = json.dumps(data).encode(encoding='utf-8') headers = {'Content-Type': 'application/json'} response = requests.post(url, data=body, headers=headers) if response.status_code ==200: return 1 return 0 # -- 配置 -- # ------------------------------ user = "136****1234" #小米运动账号 password = "123456" #密码 step = str(randint(18000,25000)) # 范围内取随机数, 前面不但能大于后面的数 #以下为信息推送,不懂的可不填写不影响刷步 sckey = '' # server酱微信推送key(不懂不要填,可空) qkey = '' # Qmsg酱QQ推送key(不懂不要填,可空) qq= '' # 需要推送的qq号 (不懂不要填,可空) plustoken = '' #PUSHPLUS的token 官网为https://www.pushplus.plus/(不懂不要填,可空) # ------------------------------ # def main_handler(event, context): # return main() # 阿里云函数 def handler(*args): main() if __name__ == '__main__': main()通过编辑器自建一个, 我这里的路径是custom/xiaomiStep.py回到定时任务tab我填写的定时规则是每天早上7点执行引用1.qinglong github: https://github.com/whyour/qinglong2.2023最新青龙面板安装|Docker安装青龙面板,JD自动签到,青龙面板搭建 ,每天自动做任务领取京豆,操作简单&设置简单,非常适合有软路由和服务器&vps的小伙伴,一次搭建长期使用:https://www.youtube.com/watch?v=4CWlq8Xp_Oc&t=6s&ab_channel=%E4%B8%80%E7%93%B6%E5%A5%B6%E6%B2%B93.搭建青龙面板:https://naiyou001.tk/knowledge/6864.青龙拉取faker库以及脚本去重详细教程:https://blog.csdn.net/cbh1987/article/details/1204834215.小米运动步数修改_阿里云函数版本:https://www.52pojie.cn/thread-1656364-1-1.html
2023年07月03日
2,536 阅读
1 评论
0 点赞
2023-06-29
完美破解The Economist付费墙
去除经济学人的限制:1.油猴插件https://greasyfork.org/zh-CN/scripts/449408-%E6%B0%B8%E4%B9%85%E6%9B%B4%E6%96%B0-economist%E7%BB%8F%E6%B5%8E%E5%AD%A6%E4%BA%BA%E5%85%8D%E8%B4%B9%E7%9C%8B-%E5%85%A8%E9%83%A8%E8%A7%A3%E9%94%81-%E5%B9%B6%E7%A7%BB%E5%87%BA%E4%BA%86%E5%B9%BF%E5%91%8A2.Github开源的一个项目:https://github.com/vivek9patel/economist.com-unlocked以下是转载的原文,镜像站点可以使用,下面的方法可能已经失效了。经济学人镜像:https://taizihuang.github.io/TheEconomist/外交杂志镜像:https://taizihuang.github.io/ForeignAffairs/安装 Adblock Plus 和 Stylus 插件经济学人:禁用 https://www.economist.com/engassets/_next/static/chunks/main-*.js纽约时报: 禁用 https://meter-svc.nytimes.com/meter.js*大西洋月刊:禁用网站cookie外交:禁用 www.foreignaffairs.com;禁用网站cookie;添加CSS样式,复制 https://www.foreignaffairs.com/sites/default/files/css/css_BRKcyoXIH258fUGLDtxb4JCNcnNyU2o2rmvhZGFfEA0.css 内容,粘贴进 Stylus.一年能省2000块钱吧。引用完美破解The Economist付费墙:https://www.douban.com/note/797208219/?_i=8001969nLWE4CN
2023年06月29日
3,362 阅读
0 评论
4 点赞
2023-06-25
Docker安装MongoDB
1.拉取镜像docker pull mongo:latest2.创建容器docker run -itd --name mongo -p 27017:27017 mongo --auth参数说明:-p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过 宿主机 ip:27017 访问到 mongo 的服务。--auth:需要密码才能访问容器服务。3.安装成功接着使用以下命令添加用户和设置密码,并且尝试连接。$ docker exec -it mongo mongo admin # MongoDB 6.0 及以上版本使用以下命令: # docker exec -it mongo mongosh admin # 创建一个名为 admin,密码为 123456 的用户。 > db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]}); # 尝试使用上面创建的用户信息进行连接。 > db.auth('admin', '123456')4.常用命令4.1 超级用户相关进入数据库adminuse admin增加或修改用户密码db.addUser(‘name’,’pwd’)查看用户列表db.system.users.find()用户认证db.auth(‘name’,’pwd’)删除用户db.removeUser(‘name’)查看所有用户show users查看所有数据库show dbs查看所有的collectionshow collections查看各collection的状态db.printCollectionStats()查看主从复制状态db.printReplicationInfo()修复数据库db.repairDatabase()设置记录profiling,0=off 1=slow 2=alldb.setProfilingLevel(1)查看profilingshow profile拷贝数据库db.copyDatabase(‘mail_addr’,’mail_addr_tmp’)删除collectiondb.mail_addr.drop()删除当前的数据库db.dropDatabase()4.2 增删改存储嵌套的对象db.foo.save({‘name’:’imdst’,’address’:{‘city’:’guangzhou’,’post’:100096},’phone’:[158,155]})存储数组对象db.user_addr.save({‘Uid’:’leoiceo@163.com’,’Al’:['test-1@163.com','test-2@163.com']})根据query条件修改,如果不存在则插入,允许修改多条记录db.foo.update({‘yy’:5},{‘$set’:{‘xx’:2}},upsert=true,multi=true)删除yy=5的记录db.foo.remove({‘yy’:5})删除所有的记录db.foo.remove()4.3 索引增加索引 1(ascending),-1(descending)db.foo.ensureIndex({firstname: 1, lastname: 1}, {unique: true});索引子对象db.user_addr.ensureIndex({‘Al.Em’: 1})查看索引信息db.foo.getIndexes()db.foo.getIndexKeys()根据索引名删除索引db.user_addr.dropIndex(‘Al.Em_1′)4.4 查询查找所有db.foo.find()查找一条记录db.foo.findOne()根据条件检索10条记录db.foo.find({‘msg’:’Hello 1′}).limit(10)sort排序db.deliver_status.find({‘From’:’ixigua@sina.com’}).sort({‘Dt’,-1}) db.deliver_status.find().sort({‘Ct’:-1}).limit(1)count操作db.user_addr.count()distinct操作,查询指定列,去重复db.foo.distinct(‘msg’)\#”>=”操作db.foo.find({“timestamp”: {“$gte” : 2}})子对象的查找db.foo.find({‘address.city’:’beijing’})4.5 管理查看collection数据的大小db.deliver_status.dataSize()查看colleciont状态db.deliver_status.stats()查询所有索引的大小db.deliver_status.totalIndexSize()advanced queries:高级查询条件操作符 $gt : > $lt : <<br> $gte: >= $lte: <= $ne : !=、<> $in : in $nin: not in $all: all $not: 反匹配(1.3.3及以上版本)查询 name <> “bruce” and age >= 18 的数据db.users.find({name: {$ne: “bruce”}, age: {$gte: 18}});查询 creationdate > ’2010-01-01′ and creationdate <= ’2010-12-31′ 的数据db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)});查询 age in (20,22,24,26) 的数据db.users.find({age: {$in: [20,22,24,26]}});查询 age取模10等于0 的数据db.users.find(‘this.age % 10 == 0′);db.users.find({age : {$mod : [10, 0]}});查询所有name字段是字符类型的db.users.find({name: {$type: 2}});查询所有age字段是整型的db.users.find({age: {$type: 16}});对于字符字段,可以使用正则表达式 查询以字母b或者B带头的所有记录db.users.find({name: /^b.*/i});匹配所有db.users.find({favorite_number : {$all : [6, 8]}});查询不匹配name=B*带头的记录db.users.find({name: {$not: /^B.*/}});查询 age取模10不等于0 的数据db.users.find({age : {$not: {$mod : [10, 0]}}});选择返回age和id字段(id字段总是会被返回)db.users.find({}, {age:1});db.users.find({}, {age:3});db.users.find({}, {age:true});db.users.find({ name : “bruce” }, {age:1});0为false, 非0为true选择返回age、address和_id字段db.users.find({ name : “bruce” }, {age:1, address:1});排除返回age、address和_id字段db.users.find({}, {age:0, address:false});db.users.find({ name : “bruce” }, {age:0, address:false});查询所有存在name字段的记录db.users.find({name: {$exists: true}});排序sort()查询所有不存在phone字段的记录db.users.find({phone: {$exists: false}});排序sort() 以年龄升序ascdb.users.find().sort({age: 1});以年龄降序descdb.users.find().sort({age: -1});限制返回记录数量limit()返回5条记录db.users.find().limit(5);返回3条记录并打印信息db.users.find().limit(3).forEach(function(user) {print(‘my age is ‘ + user.age)});结果my age is 18my age is 19my age is 20限制返回记录的开始点skip()从第3条记录开始,返回5条记录(limit 3, 5)db.users.find().skip(3).limit(5);查询记录条数count()db.users.find().count();db.users.find({age:18}).count();以下返回的不是5,而是user表中所有的记录数量db.users.find().skip(10).limit(5).count();如果要返回限制之后的记录数量,要使用count(true)或者count(非0)db.users.find().skip(10).limit(5).count(true);分组group()假设test表只有以下一条数据{ domain: “www.mongodb.org”, invoked_at: {d:”2015-05-03″, t:”17:14:05″}, response_time: 0.05, http_action: “GET /display/DOCS/Aggregation”}使用group统计test表11月份的数据count:count()、totaltime:sum(responsetime)、avgtime:total*time/count;db.test.group( { cond: {“invoked_at.d”: {$gt: “2015-05″, $lt: “2015-06″}} , key: {http_action: true} , initial: {count: 0, total_time:0} , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time } , finalize: function(out){ out.avg_time = out.total_time / out.count } } ); [ { "http_action" : "GET /display/DOCS/Aggregation", "count" : 1, "total_time" : 0.05, "avg_time" : 0.05 } ]引用1.Docker 安装 MongoDB:https://www.runoob.com/docker/docker-install-mongodb.html
2023年06月25日
283 阅读
0 评论
0 点赞
2023-06-24
诗歌收集
元代高明的《琵琶记》我本将心向明月,奈何明月照我心。过华清宫绝句三首唐•杜牧长安回望绣成堆,山顶千门次第开。一骑红尘妃子笑,无人知是荔枝来。新丰绿树起黄埃,数骑渔阳探使回。霓裳一曲千峰上,舞破中原始下来。万国笙歌醉太平,倚天楼殿月分明。云中乱拍禄山舞,风过重峦下笑声。https://so.gushiwen.cn/mingju/juv_a25e9428db6e.aspx咸阳城东楼许浑〔唐代〕一上高城万里愁,蒹葭杨柳似汀洲。溪云初起日沉阁,山雨欲来风满楼。鸟下绿芜秦苑夕,蝉鸣黄叶汉宫秋。行人莫问当年事,故国东来渭水流。♡https://so.gushiwen.cn/shiwenv_65bc4719e0b1.aspx木兰诗乐府诗集〔南北朝〕 唧唧复唧唧,木兰当户织。不闻机杼声,唯闻女叹息。(唯 一作:惟) 问女何所思,问女何所忆。女亦无所思,女亦无所忆。昨夜见军帖,可汗大点兵,军书十二卷,卷卷有爷名。阿爷无大儿,木兰无长兄,愿为市鞍马,从此替爷征。 东市买骏马,西市买鞍鞯,南市买辔头,北市买长鞭。旦辞爷娘去,暮宿黄河边,不闻爷娘唤女声,但闻黄河流水鸣溅溅。旦辞黄河去,暮至黑山头,不闻爷娘唤女声,但闻燕山胡骑鸣啾啾。 万里赴戎机,关山度若飞。朔气传金柝,寒光照铁衣。将军百战死,壮士十年归。 归来见天子,天子坐明堂。策勋十二转,赏赐百千强。可汗问所欲,木兰不用尚书郎,愿驰千里足,送儿还故乡。 爷娘闻女来,出郭相扶将;阿姊闻妹来,当户理红妆;小弟闻姊来,磨刀霍霍向猪羊。开我东阁门,坐我西阁床。脱我战时袍,著我旧时裳。当窗理云鬓,对镜帖花黄。出门看火伴,火伴皆惊忙:同行十二年,不知木兰是女郎。 雄兔脚扑朔,雌兔眼迷离;双兔傍地走,安能辨我是雄雌? ♡https://so.gushiwen.cn/shiwenv_2d6b0c83a500.aspx月下独酌四首李白李白〔唐代〕花间一壶酒,独酌无相亲。举杯邀明月,对影成三人。月既不解饮,影徒随我身。暂伴月将影,行乐须及春。我歌月徘徊,我舞影零乱。醒时相交欢,醉后各分散。(另版本“相”为“同”)永结无情游,相期邈云汉。天若不爱酒,酒星不在天。地若不爱酒,地应无酒泉。天地既爱酒,爱酒不愧天。已闻清比圣,复道浊如贤。贤圣既已饮,何必求神仙。三杯通大道,一斗合自然。但得酒中趣,勿为醒者传。三月咸阳城,千花昼如锦。谁能春独愁,对此径须饮。穷通与修短,造化夙所禀。一樽齐死生,万事固难审。醉後失天地,兀然就孤枕。不知有吾身,此乐最为甚。穷愁千万端,美酒三百杯。愁多酒虽少,酒倾愁不来。所以知酒圣,酒酣心自开。辞粟卧首阳,屡空饥颜回。当代不乐饮,虚名安用哉。蟹螯即金液,糟丘是蓬莱。且须饮美酒,乘月醉高台。♡https://so.gushiwen.cn/shiwenv_301e41411279.aspx金缕衣杜秋娘杜秋娘〔唐代〕劝君莫惜金缕衣,劝君惜取少年时。(惜取 一作:须取)花开堪折直须折,莫待无花空折枝。(花开 一作:有花)♡https://so.gushiwen.cn/shiwenv_d5cea0c3607d.aspx不第后赋菊黄巢黄巢〔唐代〕待到秋来九月八,我花开后百花杀。冲天香阵透长安,满城尽带黄金甲。♡https://so.gushiwen.cn/shiwenv_32bfa9757c62.aspx忆江南词三首白居易白居易〔唐代〕江南好,风景旧曾谙。日出江花红胜火,春来江水绿如蓝。能不忆江南?江南忆,最忆是杭州。山寺月中寻桂子,郡亭枕上看潮头。何日更重游?江南忆,其次忆吴宫。吴酒一杯春竹叶,吴娃双舞醉芙蓉。早晚复相逢?♡https://so.gushiwen.cn/shiwenv_dca0ef1f12bf.aspx临江仙·梦后楼台高锁晏几道晏几道〔宋代〕梦后楼台高锁,酒醒帘幕低垂。去年春恨却来时。落花人独立,微雨燕双飞。记得小蘋初见,两重心字罗衣。琵琶弦上说相思。当时明月在,曾照彩云归。(蘋 通:苹)♡https://so.gushiwen.cn/shiwenv_47c89d71e6be.aspx献钱尚父贯休贯休〔唐代〕贵逼人来不自由,龙骧凤翥势难收。满堂花醉三千客,一剑霜寒十四州。鼓角揭天嘉气冷,风涛动地海山秋。东南永作金天柱,谁羡当时万户侯。♡https://so.gushiwen.cn/shiwenv_52940038c6ee.aspx登科后孟郊孟郊〔唐代〕昔日龌龊不足夸,今朝放荡思无涯。春风得意马蹄疾,一日看尽长安花。♡https://so.gushiwen.cn/shiwenv_6650a905deea.aspx
2023年06月24日
266 阅读
0 评论
0 点赞
1
...
4
5
6
...
11