从开始接触Novel AI开始我就想写让他自动生成,然后存到电脑里。

今天终于把程序写出来了。

官方说在/docs里面可以看到API接口,但是我进去什么有用的信息也没找到,即便是加上运行参数"--api"也一样。

所以···

抓包分析

前端与后端之间用的是https通信 废话,直接Fiddler抓包。

我需要通过分析前后端的通信得到后端供前端调用的接口。

在进行之前,先确定目标:

  • 记录登录状态的方法
  • 登录的接口
  • 判断是否需要等待的接口
  • 运行计算的接口
  • 获取进度的接口
  • 获取输出的接口

记录登录状态的方法

在每一次提交计算都会传递过去一个参数,叫做“session_hash=XXXX”,所以我怀疑这个就是记录登录状态的,倘若是这样的话,这个值就应该是后端传递过来的,完完整整找了之前的信息也没有找到它的值出现,此时注意到它的名字中有个“hash”,但是尝试把一些信息计数哈希无果。

假如上面那个参数就是记录登录状态的参数的话,那么这个参数应该是由JavaScript记录的,只要刷新网页就会丢失,但是并不会丢失登录状态。

为什么呢?因为Cookie!但是我最不明白的就是cookie了,一直在扣静态网页,完全不懂,不过这一次任务比较简单,技术够用了。

完全禁用浏览器cookie,果然登录不上了。

分析登录的包,登录失败了的话会返回Json的错误信息,成功的话会302跳转,跳转到首页,cookie就藏在回应的http头里面,回应http头里有个修改cookie的信息。

我只需要分析回应头,然后取出cookie信息,下次请求的时候作为请求头

无论是Python还是Go还是什么,http客户端对象都是能记录cookie的,只需要开启cookie记录,其余的事情什么也不用做。

登录的接口

登录的接口非常简单,POST请求,发送帐号和密码,完成。

POST请求与GET请求不同,主要是客户端提交什么到服务器用的,往服务器发送的容量比GET大,比GET复杂一些。

POST请求有格式,在头里面写着。
“Content-Type: XXX”

格式有四种

  • application/x-www-form-urlencoded
  • application/json
  • multipart/form-data
  • text/xml

登录用的是“application/x-www-form-urlencoded”。

地址: /login

这个格式的标准到底是什么,我也不知道,但是照着葫芦画瓢就好了,把抓的包替换掉账号密码。

后面四个接口

这四个是同一个接口,比意想中简单得多。

地址: /api/predict

请求

请求方法是POST,格式是“application/json”

14请求的正文

内容是:

{
    "fn_index": int,    
    "data":array,
    "session_hash":string
}
  • fn_index 请求类型代码
  • data 携带的信息(应该是解码之后直接交给Python的函数执行)
  • session_hash 回话ID(不知道起到了什么具体作用)

fn_index抓包抓到之后,已知有用的有两个:

  • 3: 获取任务进度。data为空。
  • 14: 请求AI计算,最后计算完成才会返回,计算期间一直挂着。data里面是参数。

返回

返回同样是“application/json”

里面的信息很多,很不条理,大多数信息都用不到。

对于3请求,它返回的进度不是一个值,是一段html代码。

对于14请求,返回生成的文件名,除此之外还有很多无用数据。

调用接口

在进行14请求的时候,页面上可以设置的这些参数全部放进data里面发给后端了。我把其中的生成种子换成%s占位符,放入Go代码。

14请求在最后计算完成才会返回,计算期间一直挂着,这也免去了查询是否完成的麻烦。

我还不会用多线程,所以就只用14请求,不显示进度了。

14请求最终返回一段Json,这段Json很长,垃圾很多,很不规则,其中包括了生成出的文件名。

获取文件的接口

上面成功得到文件路径之后需要下载下来,但是直接访问的话会404,界面以外的文件不允许访问。

根据抓包,获取的方法还是通过接口。

地址: /file

这似乎有点不合标准。

请求方法是GET

直接请求 /file=XXX 就可以了。

Go程序

从登录开始。

发送POST登录请求。

"username=%s&password=%s"

开cookie:

var client = &http.Client{}
jar, err0 := cookiejar.New(nil)
client.Jar = jar

只要cookie记录了,请求一次成功了就不用管了。

然后直接开始请求AI绘图接口。

最终返回的Json Go语言不好解析,所以,我不解析了,直接搜索 "name":"/ 这个字符串,找到就是成功,没有就是失败。

strings.Index(restr, "\"name\":\"/")

可能会生成出来纯黑的图,这样的图在png压缩之后会比一般的图片小很多,所以只要接收到长度小于两万字节的文件直接丢弃就好了。


好了,现在AI就可以无人监督运作了。

项目已开源到Github: https://github.com/FFeng123/stable-diffusion-webui-request-tool

我能想到的,最大的成功就是无愧于自己的心。