auto.js自动化处理插件 - 葡萄浏览器多账号签到

作者:matrix 发布时间:2020年2月11日星期二 分类:零零星星

这些天在家研究autojs操作,完全可以用它来模拟手动点击滑动app的各种操作,这个自动化是真的香~
ios端的Jsbox没这么友好,毕竟系统完全不同,也有很多限制。

https://hyb1996.github.io/AutoJs-Docs

目前要使用多个账号登录,然后进行点击签到,看广告的需求。

环境:mi8 Android9 AutoJs[4.1.1] 葡萄浏览器com.qwh.grapebrowser

AutoJs在应用市场都被下架了,留个下载的渠道:

https://github.com/SuperMonster002/Hello_Sockpuppet/raw/master/%5Bauto.js%5D%5B4.1.1_alpha2%5D%5Barm-v7%5D(b69a4e23).apk

https://www.hhtjim.com/wp-content/uploads/2020/02/auto.js4_.1.1_alpha2arm-v7b69a4e23.apk_.zip

鼓捣了几天,差不多完工。测试的app是葡萄浏览器com.qwh.grapebrowser,最终效果是运行后自动切换账号来签到。
第一次编写的确是各种懵逼,为啥子不动了,日志在哪里怎么看,每次都手动复制代码到手机好麻烦。。。

开发环境vscode

vscode插件来开发很方便。如果没有开发调试环境,我每次都要微信发送代码的消息,toast,再上app清空粘贴运行,累死。给hyb1996好评,相当不容易。

  1. command + shift + p运行Start Server命令来开启远程环境。

  2. auto.js APP设置里打开连接电脑,填入电脑端内网ip。当然手机和电脑是要一个内网环境

图片5130-auto.js插件 - 葡萄浏览器多账号签到

  1. 运行Run命令就可以在app端运行插件脚本。注意默认模式需要打开在Auso.js界面中启动。

开发

文档:

https://hyb1996.github.io/AutoJs-Docs/

要操作的控件基本信息都需要用 autojs app的悬浮窗设置里面找到分析

"auto"
console.show();//开启log窗口

//等待打开app
launchApp('葡萄浏览器');
waitForPackage("com.qwh.grapebrowser");

const LOGIN_ACTIVITY = 'com.qwh.grapebrowser.mvp.base.login.LoginActivity';
const MAIN_ACTIVITY = 'com.qwh.grapebrowser.mvp.navigation.NavigationActivity';
const SETTING_ACTIVITY = 'com.qwh.grapebrowser.ui.main.activity.mineview.SystemSettingActivity';
const BASEDIALOG = 'com.qwh.base.BaseDialog';

var  iv_cancel = id("iv_cancel"); //粘贴板搜索窗口的取消按钮
var ad = id('skip_view');//跳过广告按钮
var my = id("ll_mine");//我的按钮
var sign = id("iv_sign");//签到图标
var sign_in = id("iv_sign_in");//签到按钮
var profile_photo = id("iv_pic").className("android.widget.ImageView").clickable(true);//头像
var exit_btn = id('ll_exit');//退出登录的按钮. 不可点击 只能获取坐标来操作
var exit_ac = id('tv_dialog_message_confirm'); //同意执行退出
var login_btn = id('tv_login');//登录按钮 

var accounts = {
    "131***1110": "123123"
};

cance_list = [ad , iv_cancel];

//监听弹窗事件(异常界面处理)
threads.start(function(){
    while(true){
        sleep(100);
        for (i in cance_list){
            //toast(cance_list[i]);
            if(cance_list[i].exists()){
                cance_list[i].click();
            }
        }

    };
});

//监听音量下键
threads.start(function(){
  isKeyDown();
})

//id("iv_pic").className("android.widget.ImageView").clickable(true)  .findOne().click();


//根据控件布局点击
function click_btn_func (widget_list,time ){
  if(widget_list instanceof Array){
    for(var i in widget_list){
      var widget = widget_list[i];
      if(widget.exists()){
        if(time){
          while(!widget.findOne(time).click());
        }else{
          while(!widget.findOne().click());
        }

        // if(widget_list[i].clickable()){//可点击判断  测试没有用。
        //   toast('aaaa');
        // }
      }
    }
  }else{
    if(time){
      while(!widget_list.findOne(time).click());
    }else{
      while(!widget_list.findOne().click());
    }
  }
}

//根据坐标点击控件
function click_coord_func(widget_list){
  if(widget_list instanceof Array){
    for(var i in widget_list){
      let widget = widget_list[i];
      if(widget.exists()){
        widget = widget.findOne();
          //获取其中心位置并点击
        while( !click(widget.bounds().centerX(), widget.bounds().centerY()) );
      }
    }
  }else{
    let widget = widget_list.findOne();
          //获取其中心位置并点击
    while( !click(widget.bounds().centerX(), widget.bounds().centerY()) );
  }
}

// 我的界面中判断是否登录
function is_login_of_my_activity(){
    return !!profile_photo.exists();
}

function logout(){
  console.log('function: logout')

  //已经进入我的界面
    // waitForActivity(MAIN_ACTIVITY);//入口主界面 activity
  if(is_login_of_my_activity()){//如果已登录,则点击退出
    console.log('发现有登录账号')
    //切记等待界面响应
    click_btn_func([profile_photo]);
    waitForActivity(SETTING_ACTIVITY);//等待界面响应
    click_coord_func([exit_btn]);
    waitForActivity(BASEDIALOG);
    console.log('返回到登录界面');
    click_btn_func([exit_ac]);
  }else{//已经是退出了 进入登录界面
    console.log('发现已经退出');
      //我的界面点击登录按钮操作
  // if(id('tv_btn').exists()){
  //   .findOne().click();
  // }
  console.log('查找「登录/注册」按钮 进入登录界面')
  click_btn_func( id('tv_btn'),4000);
  }
}

function login(phone,pwd){
  //已进入登录界面
    waitForActivity(LOGIN_ACTIVITY);
    setText(0,phone);
    setText(1,pwd);
  click_btn_func([login_btn]);
  console.log('登录完成')
}

//检测是否点击了音量下键的方法
function isKeyDown(){
  //按键时不会弹出音量框
  events.setKeyInterceptionEnabled("volume_down",true);
  //监听按键
  events.observeKey();
  events.on("key_down",function(volume_down,event){
      toast("正在关闭此脚本");
      //退出脚本
      sleep(500);
      engines.stopAll();
      //直接返回桌面
      home();
  });
}

//每秒执行检测操作 超时退出
function await_callback(callback,timeout_second){
  let _n = 0;
  while(true){
    if(_n > timeout_second){// 最长等待n秒检测
      console.log('await_callback最长等待超时 break')
      break;
    }
    if(callback()){//执行回调 返回true
      return true;//返回true标记给外部
      // break;
    }
    sleep(1000);//步长 1秒
    _n++;
  }
  return false
}

console.log('查找关闭按钮');
await_callback(function(){
    if(className("android.widget.ImageView").depth(5).bounds(55,130,137,212).exists()){
        className("android.widget.ImageView").findOne().click();
        console.log('完成 关闭广告按钮');
        return true
    }
    return false
},3);

  //确定图片 领取报销额度
  console.log('等待界面 准备领取');
  // waitForActivity('com.qwh.grapebrowser.dialog.s');//等待领取报销额度的页面
  var pull_down = await_callback(function(){
    if(className("android.widget.FrameLayout").exists()){
      console.log('点击确定FrameLayout 领取');
      click_coord_func(className("android.widget.FrameLayout"));
      return true;
        }
        return false;
  },30);

console.log('done');

说明:
上面成品修改下账户密码可以直接运行。
需要注意的是代码中很多时候卡住不动都需要判断控件或者按钮是否存在,否者findOne()会一致做轮询。
用log输出,查看运行状态
有些控件无法触发click()方法,需要查看其clickable属性是否为true,意即为是否可点击
不能正常按照控件布局点击的话只能用坐标进行点击操作

安卓是真的香,以后想拥有一台一加😂

参考:

https://hyb1996.github.io/AutoJs-Docs

https://github.com/SuperMonster003/auto.js_Projects/tree/Ant_Forest

https://www.jianshu.com/p/d2ad3ce9cf87

https://thbelief.coding.me/2019/04/02/Auto-js-Script%E5%BC%80%E5%8F%91-%E4%BA%8C/

https://www.autojs.org/

https://www.autojs.org/topic/1651/%E5%BD%93%E6%8E%A7%E4%BB%B6-clickable-false-%E6%97%B6-%E6%80%8E%E4%B9%88%E8%BF%9B%E8%A1%8C%E7%82%B9%E5%87%BB%E6%88%96%E8%80%85%E8%A7%A6%E6%91%B8

PEACE~

ifttt推送gmail新邮件提醒

作者:matrix 发布时间:2020年2月8日星期六 分类:零零星星

今天临时想用ifttt来发送新邮件提醒服务的推送,查了下才知道19年初google就取消了对ifttt的api调用。不过看到可以使用其他三方应用来解决这个问题。

目的:新gmail邮件->tg消息通知

需要Gmail,IFTTT,automate.io,Trello,telegram相关账户

后续两天使用发现automate.io的免费版配额调用次数只有250次,所以说下面的操作对于想使用免费版本的人来说,可行性很低

[Alert] Action Quota about to Expire

This is to notify you that your account has consumed 80% of the total Action quota (250) in the Free plan. As and when it crosses the limit, your Bots will be paused automatically.

Please upgrade your plan if you anticipate more usage within the current billing cycle.

方法

类似于IFTTT的automate.io可以设置处理条件,自由度也更高,可以接收处理gmail邮件,但是没找到telegram私有频道的接收app。但是可以用trello来中转达到转发效果。

调用链形式:gmail->automate->Trello->ifttt->telegram

绑定授权的automate.io应用

设置automate.io,进入app界面 授权gmail和Trello应用。注意授权gmail时要选着权限更高的gmail app要不然没有权限读取邮件。

图片5117-ifttt推送gmail新邮件提醒

添加Trello相关List用于接收邮件

  • 在Trello中添加私有看板boards命名为gmail

    图片5118-ifttt推送gmail新邮件提醒

  • 进入gmail看板再添加一个列表List命名为新邮件提醒用来接收邮件

设置automate.io BOT

创建bot

  • 添加gmail触发器

    触发应用Trigger app选择绑定了的Gmail,操作应用Action app选择Trello。
    触发事件Event选择新New EmailLable为Gmail邮件的分类,我这里选择INBOX,也就是所有收件箱。还可以设置Search Filter达到关键字过滤的效果。

  • 添加Trello操作

    选择Add or Update a Card事件,Board和List选择Trello中创建好的名称,gmail和新邮件提醒。title中设置显示的标题[From Email] - [From Name] - [Subject],
    Description描述我这里写入邮件的url https://mail.google.com/mail/u/0/#inbox/[Message ID],方便tg中点击查看。
    其他还有时间,标签的配置都可以自定义。
    如果想要预览邮件内容的话再添加个Trello的Add a Comment操作。

    个人版本不能分享bot,可以参照下面图片配置:

    图片5120-ifttt推送gmail新邮件提醒

automate.io的配置自由度很高,甚至都有存在or不存在的逻辑判断,真的好方便。免费版应该有很多限制,不过足够个人使用了。
这里添加完成之后进行automate.io的BOT测试,发送个邮件,如果Trello的gmail看板中有邮件就算成功一半。

每次有新邮件,让系统自动添加Card到List就好了。邮件标题和email等基本信息作Card名,方便可读。

图片5119-ifttt推送gmail新邮件提醒

上面就是接收新邮件到Trello的List的效果

设置IFTTT

到这里完成最后一步的IFTTT设置就可以把Trello的新Card发送到TG私有频道。如果是第一次使用IFTTT的tg频道的话还需要去关联

  • 设置This为Trello,之后选择Card added to list事件触发

  • 选择看板board,默认个人私有看板是My Boards

  • List name填入新邮件提醒

  • 选择IFTTT的thatTarget chat 选择绑定的tg ifttt频道。

  • 之后再设置tg频道的message消息内容格式

    GMAIL新邮件提醒: <a href="{{Description}}">{{Title}}</a><br>
    <a href="{{CardURL}}">View on Trello</a>
    

实现接收gmail提醒的方式还有很多路径,类似于automate的还可以用Zapier

参考:

Gmail is being removed from IFTTT from ifttt

https://if404.com/archives/2019/04/09/use-ifttt-gmail-dropbox-auto-push-ebook-to-kindle

Matlab一些简单的操作tips

作者:matrix 发布时间:2019年8月12日星期一 分类:零零星星

由于matlab编程偏向于学术方面,对于我这种😍喜欢OOP以及普通字符串操作来说多少的不熟悉和麻烦。
遂记录。

timer定时器操作

类似于javascript的setInterval操作

myTimer = timer('Name','MyTimer',               ...
    'Period',2,                 ... % 2秒钟间隔
    'StartDelay',0,                 ...
    'TasksToExecute',inf,           ...
    'ExecutionMode','fixedSpacing', ...
    'TimerFcn',@myTimerCallback,...
    'ErrorFcn',@(~,thisEvent)exit);%  如果报错 则推出程序

start(myTimer);%启动

function myTimerCallback(hObject, eventdata)
     disp(['run time:: ', datestr(datetime('now'),'yyyy-mm-dd HH:MM:SS') ])
end

删除所有定时器:

delete(timerfindall());

手动抛异常

baseException = MException('MYFUN:BadParameter','Parameter miss');
throw(baseException);

throw函数需要传入异常类。
MException类第一个参数为msgID。必须要有冒号:,名称都可以自定义。
参考:
https://ww2.mathworks.cn/help/matlab/ref/mexception.html

字符串比较

使用strcmp函数进行字符串比较。
不同于使用双等号==,双等号会对字符串中的每个字符进行比较相等,最终返回逻辑数组logical array

if strcmp(str,'timestr')%判断字符串相等
        dis('Content is equal');
   end

多行注释

单行注释使用百分号%
多行注释使用%{...%}

%{
  ...some thing
%}

函数默认参数判断以及设置值

function rel = func(arg1,arg2)
    if exist('arg2', 'var') && ~isempty(arg2)%如果传入arg2参数 且不为空
      bla bla
    end
end

function [result] = func(format)
    if ~exist('format', 'var') %不存在默认参数
        result = '默认参数';
    else
        result = format;
    end
end

exist函数中var表示(变量)类型

https://blog.csdn.net/liuxiabing150/article/details/46519785

删除数组指定下标

list(1) = [];%删除指定的下标的元素

del_index_list = [1 2 9 18]
list(del_index_list) = [];%删除多个下标元素

检测struct结构体字段是否存在

isfield(struct('a','1'),'a1') #判断a1字段是否存在

all(isfield(struct('field1','val1'),{'a','b'}))#判断a,b字段是否都存在

参考:
https://ww2.mathworks.cn/matlabcentral/answers/260295-dynamically-name-a-struct

动态添加struct数据key名称

data = struct();
name = 'Dynamic_Name';
data.(name) = 990;

匿名函数

匿名函数最为回调的处理和调用


% 回调函数的执行 function rel = func(arg1,callback) cb = callback(data);%执行回调函数,传入data数据作为参数 if ~cb bla bla end end %回调函数作为参数来使用 func(arg1,@(data)deal(1)); func(arg1,@(data)[a=1;deal(a);]);%匿名函数执行多条语句 %普通函数作为回调函数 func(arg1,@cb); function rel = cb(data) rel = 1 end

说明:
使用@操作符
deal函数类似于java中的return操作
方括号[]最为数组操作可以防置多条语句来执行

追加保存数据到文件

now = 1583237214;
data_diff = 1;
data_uni_diff = 2;
res = [res;now,data_diff,data_uni_diff];

dlmwrite('chech_diff_time.txt',res,'-append');

-append参数表示追加处理

判断数据类型

class(123) % double
ischar('') % logic true

修改matlab编码集到utf-8

作者:matrix 发布时间:2019年8月11日星期日 分类:零零星星

默认matlab安装会根据系统语言环境来设置文件编码,想设置为utf-8编码反而是件麻烦事。
网上大多都说直接修改lcdata就可以,但是我找了一大圈都没看到里面出现的关键字内容,也试了很多方法都没用。
2017之后版本的lcdata.xml都只是空白的注释文件,其实就需要把lcdata_utf8改为lcdata或者把里面的内容放到lcdata.xml就可以了。

环境: matlab_R2018a for Mac

修改lcdata.xml

Mac lcdata.xml路径:/Applications/MATLAB_R2018a.app/bin/lcdata.xml
windows的话找到安装目录的bin文件夹

<?xml version="1.0" encoding="UTF-8" ?>
<!-- MathWorks Locale Database -->
<!-- File Name: lcdata.xml -->
<!-- Copyright 2007-2016 The MathWorks, Inc. -->
<lcdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="lcdata.xsd" >
<!-- Note: -->
<!-- This locale database is used to customize the MathWorks locale database. -->

<!-- Codeset entry example -->
<!--    <codeset> -->
<!--        <encoding name="StandardEncodingName" jvm_encoding="JavaEncodingName"> -->
<!--            <encoding_alias name="AliasName"/> -->
<!--        </encoding> -->
<!--    </codeset> -->

<!-- Locale entries example -->
<!--    <locale name="StandardLocaleName" encoding="EncodingName" xpg_name="XpgLocaleName"> -->
<!--        <alias name="AliasName"/> -->
<!--    "region_alias" is only for Mac -->
<!--        <region_alias name="RegionAliasName"/> -->
<!--    </locale> -->

<locale name="zh_CN" encoding="UTF-8" xpg_name="zh_CN.UTF-8"> </locale>

</locale>

在locale标签里面添加<locale name="zh_CN" encoding="UTF-8" xpg_name="zh_CN.UTF-8"> </locale>
之后再重启matlab就好了。

参考:
https://blog.csdn.net/qq_34241498/article/details/90168924

matlab调用python库函数和自定义脚本函数

作者:matrix 发布时间:2019年7月15日星期一 分类:零零星星

本来只是想获取字符串的MD5hash值,结果发现麻烦。首先去mathworks找到的DataHash,GetMD5这些函数要么无法使用,要么就是计算出来的md5值是错误的,反正达不到效果。
刚开始以为mathworks的代码必须登录账户才能下载,现在才发现,点击Overview旁边的Functions选项卡就能看到源代码。 😂
图片4928-matlab MD5函数
当初就算是找到了一些函数也是不能使用,最后还是使用python库来解决。好在matlab对python的调用非常简单。直接使用py库就好了,唯一的问题就是有些python的语法和matlab不同,比如切片[:::]操作这些。

安装python3环境

2019-08-19测试发现macos中3.7版本可以,但是在centOS中就调用失败。所以就centOS中测试安装3.5的版本了。
后面发现应该是编译时的enable-shared参数问题。

2020-02-18centos中测试可以直接用conda来安装python3.5使用,3.6,3.7测试调用失败!

开始手动编译安装

cd ~
yum install zlib-devel bzip2-devel openssl-devel ncurese-devel
wget https://www.python.org/ftp/python/3.5.0/Python-3.5.0.tgz
tar xf  Python-3.5.0.tgz
cd Python-3.5.0
./configure --enable-shared #matlab要求必须设置enable-shared参数
make &&  make install

参考:
https://ww2.mathworks.cn/help/matlab/matlab_external/undefined-variable-py-or-function-py-command.html#buialof-67
https://ww2.mathworks.cn/help/matlab/getting-started-with-python.html?lang=en

切换默认的python解释器

matlab输入pyversion`可以查看python解释器路径,如果需要修改:

 pyversion /usr/local/bin/python3 %切换到python3.7指定路径

直接调用python内置函数

计算字符串md5函数

使用python的hashlib库进行操作

function[re]=md5(str)
    %{
        依赖python进行md5 hash
    %}
    m2 = py.hashlib.md5();
    m2.update(py.str(str).encode('utf-8'));
    re = char(m2.hexdigest());

说明:
此函数依赖python环境,确保系统中有安装。
兼容Linux,Mac,Windows

最后char函数是将py.str类型转换为matlab的str
知道了这个操作,以后很多操作就会非常简单。
比如

获取当前时间戳:

str2num(char(py.int(py.time.time())))

直接用py库来调用即可,最后再使用matlab函数str2num,char处理成number类型。

调用自定义.py脚本函数

上面的方法倒是可以解决一部分难题,但是遇到方括号[]、百分号%操作符这些直接在.m文件中就不会执行了。毕竟matlab是以它的语法来解析,这样只得起调.py文件来操作。

新建test.py文件位于当前工作目录

def func():
    return '123'[::-1]

载入python脚本:


%脚本所在路径,空字符串表示当前目录 path = '' %当前目录 %path = 'a/' %当前的子目录a if count(py.sys.path,path) == 0 insert(py.sys.path,int32(0),path); end %清除脚本缓存,执行重载操作 clear classes; mod = py.importlib.import_module('test');%载入的脚本模块 %mod = py.importlib.import_module('a.test');%载入的子目录下的脚本模块 py.importlib.reload(mod);

调用py.test.func即可得到切片结果321,注意为py.str类型。
子目录形同:py.子目录.文件名.函数名

当修改py文件之后再调用会发现还是之前的结果,matlab缓存了之前的python脚本,所以这里需要clear classes...这类操作。

参考:
MATLAB 调用 Python

https://www.cnblogs.com/zknublx/p/6212590.html

https://blog.csdn.net/jnulzl/article/details/51170859

https://zhuanlan.zhihu.com/p/42598340

https://blog.csdn.net/x5675602/article/details/52134981

http://www.1cae.com/a/MatLab/52/python-matlab-8943.htm

matlab循环遍历struct结构体

作者:matrix 发布时间:2019年6月27日星期四 分类:零零星星

图片4911-matlab循环遍历struct结构体
matlab网络请求操作完成之后需要对返回数据读取,操作时候出现的问题就是无法循环struct数据。
因为接口一般以json数据格式返回,matlab会把Object结构处理为struct数据而无法循环读取。很多字段的时候我可不希望看到手写矩阵声明。
取struct长度的sizelength都无法正常返回其元素个数,听说它不是向量。

办法

fieldnames函数获取struct的字段field数据(返回为cell元胞数组)
之后用structName.(expression)这种操作获取动态的struct数组数据。比如struct.a等同于动态操作的struct.('a')
现在才知道文档上有,我TM竟然随便点括号猜出来的~

%声明方式1
%s = struct('a',11,'b',222)

%声明方式2
s=struct
s.a = 11
s.b = 222

% https://ww2.mathworks.cn/help/matlab/ref/struct.html

fileds = fieldnames(s);

for i=1:length(fileds)
    k = fileds(i);
    key = k{1};
    value = s.(key);

    disp(key)
    disp(value)
    disp('---')
end

% s.('a') %动态结构体引用

升级操作:自动生成对应变量

按照Struct字段自动生成对应的变量名和值

s = struct('a',11,'b',222)

fileds = fieldnames(s);

for i=1:length(fileds)
    k = fileds(i);
    key = k{1};
    value = s.(key);
    eval(['variable_',num2str(key) ' = ' num2str(value)])
end

说明:
使用eval函数动态创建variable_%s的变量。
本来在mathworks上看到有人发布过Structure fields to variables方法来自动处理struct,但是没有正版授权码 所以无法下载使用。

参考:
https://ww2.mathworks.cn/help/matlab/learn_matlab/types-of-arrays.html
https://ww2.mathworks.cn/help/matlab/ref/struct.html
https://www.ilovematlab.cn/thread-317868-1-1.html

https://ww2.mathworks.cn/matlabcentral/fileexchange/26216-structure-fields-to-variables

PEACE~

Matlab网络请求操作

作者:matrix 发布时间:2019年6月22日星期六 分类:零零星星

matlab这个学术界的编程语言我是几个月前听说,有些基本操作是真的麻烦,当然在其他方面matlab是相当🐂🍺

使用Matlab进行GET/POST请求调用接口,提交参数。

之前苦于没有将get请求的query参数进行变量提取,好在www.mathworks.com找到有文档说明

GET请求操作函数封装

get网络请求封装成函数get_request

%GET网络请求
function [result]=get_request(uri,query)

    import matlab.net.* %导入Matlab网络请求库
    import matlab.net.http.*

    uri = URI(uri);%请求地址;
    uri.Query = matlab.net.QueryParameter(query);%get  附加请求参数 

    r = RequestMessage;
    r.Method = 'GET';%使用GET请求类型

    response = send(r,uri);%发送请求
    status = response.StatusCode%获取服务器响应的状态码
    if (status==200) %一般成功响应的状态码为200 表示ok 即成功
        content = response.Body.Data; %获取服务器响应的内容
        result = content;
    else
        disp('请求失败')
    end

说明:

参数1 uri: 请求url, 如:http://hhtjim.com
参数2 query: get请求参数 传入struct类型数据
还有就是接口返回json数据(response响应头有指定type json),matlab会自动解析json数据,最后用response.Body.Data调用就好,不方便查看的那就debug。

如果要手动处理json字符串的话使用jsonencode, jsondecode进行编解操作。

调用举例:
请求:http://hhtjim.com?arg=123

get_request('http://hhtjim.com',struct('arg', '123'))

或者

query.arg = '123'
get_request('http://hhtjim.com',query)

上面两种方式的调用都可以完成操作。matlab内部会自己封装拼接为http://hhtjim.com?arg=123进行请求。

如果想要更简单的ge请求可以使用webread进行操作。

POST请求

这里测试的POST的请求更为复杂,会添加自定义请求头,post body表单内容,cookie的涉及。所以没有封装成统一调用的函数,需要的自行修改咯~

import matlab.net.* %倒入Matlab网络请求库
import matlab.net.http.*

uri = URI('http://localhost:8080/testOrder/double_param/');%请求地址

%添加请求参数
qStruct.K=1;
qStruct.d2=2;
qStruct.d1=3;
qStruct.L=4;
qStruct.order_switch=1;%1开 0关
qStruct.order_size=2;
qStruct.diff_earnings=1.00009;



r = RequestMessage;
r.Method = 'POST'%使用POST请求类型
csrf = 'YYC0e8GICcEroZGDuL8THJ4ZQdwQpDqNtkBsfnaBP0XpH3rqYVNXADJGpWdo53o0'%Djabgo框架表单中防止跨站请求的参数,其实这是服务器生成的伪随机字符
qStruct.csrfmiddlewaretoken=csrf;
r.Body = matlab.net.QueryParameter(qStruct)%放入请求参数

%添加请求头
r = addFields(r,'Content-Type','application/x-www-form-urlencoded');
r = addFields(r,'Cookie',sprintf('csrftoken=%s',csrf));


response = send(r,uri);%发送请求
status = response.StatusCode%获取服务器响应的状态码
if (status==200) %一般成功响应的状态码为200 表示ok 即成功
    content = response.Body.Data %获取服务器响应的内容
    disp('请求成功:')
    disp(content)
else
    disp('请求失败')
end

%参考:
%https://ww2.mathworks.cn/help/matlab/http-interface.html
%https://ww2.mathworks.cn/help/matlab/ref/matlab.net.http.requestmessage.send.html#bu199af-6
%https://www.mathworks.com/help/matlab/ref/matlab.net.http.message.addfields.html
%https://ww2.mathworks.cn/help/matlab/ref/matlab.net.queryparameter-class.html

最后我真想说术业有专攻,用matlab进行网络请求是的自讨苦吃。

参考:

https://ww2.mathworks.cn/help/matlab/ref/matlab.net.uri-class.html#bvflp65-2

https://ww2.mathworks.cn/help/matlab/http-interface.html
https://ww2.mathworks.cn/help/matlab/ref/matlab.net.http.requestmessage.send.html#bu199af-6
https://www.mathworks.com/help/matlab/ref/matlab.net.http.message.addfields.html
https://ww2.mathworks.cn/help/matlab/ref/matlab.net.queryparameter-class.html

记第一卷胶片

作者:matrix 发布时间:2019年5月31日星期五 分类:零零星星

对于胶片感兴趣想尝试主要源于腹肌蓝波湾的XT20,虽然XT20之前没有摄影的经历 不过还是能感受到一丁点的胶片模拟复古静谧的感觉。
相机用的VILIA Soviet,两个月前ebay海淘的前苏联造物。这个相机需要全部手动操作,估焦、测光这些我都对比手上的xt20进行拍摄,最终效果还算不错,个别照片有点糊和低曝。总体来说很满意啦,毕竟第一次用这玩意拍。不错 不错 以后还得缴学费。 :mrgreen:
胶卷是淘宝买的iso200柯达彩色135,选的最便宜的一个18块一卷的。起初会担心过安检的X光会让胶片曝光,实际上测试完全没问题,或许iso高的胶卷会有影响。
把胶卷冲洗为电子档的照相馆还真不好找,在成都听朋友说环球中心大概25可以弄。在昆明问了好多家照相馆都不可以,最后找到的是云南师大西南联大校区正门口的大红门照相馆可以冲洗,30块钱搞定等了2周。

总体效果非常满意,浓重的复古感。毕竟手动估焦还不是很熟悉,曝光也是。 🙈

第一卷胶片

1

图片4629-记第一卷胶片

图片4628-记第一卷胶片

图片4627-记第一卷胶片

图片4626-记第一卷胶片

图片4625-记第一卷胶片

图片4624-记第一卷胶片

图片4623-记第一卷胶片

图片4622-记第一卷胶片

图片4621-记第一卷胶片

图片4620-记第一卷胶片

图片4618-记第一卷胶片