先给楼主提一个建议!虽然楼主给出了网站、请求的 API 接口,但是没说怎么触发这个接口呀……
从楼主的描述来看,我也不清楚楼主到底做了什么工作,如果是通过 JSRPC 调用 l.a.HmacSHA1
是不够的,下面我完整的说明流程。
该 POST
需要的参数有请求头参数和提交的 payload
两个部分。
请求头的参数
可以确定的请求头参数有以下几个:
Apisign-Appid
Apisign-Nonce
Apisign-Sign
Apisign-Timestamp
App-Terminal-Type
Auth-Token
它的生成位置就是在 l.a.HmacSHA1
的位置,如下是图片对比:
各参数的生成逻辑如下:
// 该变量 w 对应上图中的 timestamp 参数,它是时间戳
var w = (new Date).getTime();
// 该变量 y 对应上图中的 nonce 参数,它是随机字符串
var y = Math.random().toString(36).substr(3);
// 该变量 f 就是 l.a.HmacSHA1 函数的第一个参数,注意它的形式:
// 这是 f 的值:/smartWriting/materiaDetail{"id":"q9D35YYBqqkzjz0QbJFN"}1718258710216yfg1bl7v2e
// 从结果来看,它的组成是如下:
var f = '/smartWriting/materiaDetail' + '{"id":"id值,这个 ID 值就是 POST 提交的 ID 值"}' + w + y
// 然后可以调用 l.a.HmacSHA1 生成 Q,从而生成 L,最后生成上图中的 signature 参数
所以,如果想要 JSRPC 调用 l.a.HmacSHA1
,需要的就是 POST
提交的那个 id
值!
POST 提交的数据
这个提交的数据其实就是要生成范文的 ID
,它是在第一次打开范文面板时加载的,用于唯一标识某一篇范文!图片展示:
JSRPC 实现的过程
测试结果
为了测试整个流程,我并没有搭建 jsrpc 环境,反而从 l.a.HmacSHA1
这个名称出发,在本地实现了。
使用 python 的标准库 hmac
进行 HmacShA1
加密。
import hmac
import hashlib
import base64
def get_signature(f: str, key: str):
# 创建一个新的 HMAC 对象
h = hmac.new(key.encode(), f.encode(), hashlib.sha1)
result = base64.b64encode(h.digest()).decode()
return result
# 经过测试,与网站加密结果一致
signature = get_signature(
'/smartWriting/materiaDetail{"id":"q9D35YYBqqkzjz0QbJFN"}1718260842263jm2r884t6e',
"wqKOwI3iZ46vVarlZhljNy8H9WPwmK61",
)
最后是完整的代码,注意,范文 ID 被固定了哈。
import requests
import json
import time
import hmac
import hashlib
import base64
import random
import string
from urllib.parse import quote
def get_w():
return str(int(time.time() * 1000))
def get_y():
# y 是随机的字符串,如果短时间内发出的请求中, y 是相同的,则会判定为重复请求
# 感谢 GPT 生成代码
result = "".join(random.choices(string.ascii_letters + string.digits, k=10))
return result
def get_f(url: str, id: str, w: str, y: str):
# 生成规律如:/smartWriting/materiaDetail{"id":"q9D35YYBqqkzjz0QbJFN"}1718258710216yfg1bl7v2e
return f'{url}{{"id":"{id}"}}{w}{y}'
def get_signature(f: str, key: str):
# 感谢 GPT 生成代码
# 创建一个新的 HMAC 对象
h = hmac.new(key.encode(), f.encode(), hashlib.sha1)
result = base64.b64encode(h.digest()).decode()
print(result)
return quote(result)
# 范文的 id 已经被固定了哈
materia_id = "q9D35YYBqqkzjz0QbJFN"
w = get_w()
y = get_y()
f = get_f(
url="/smartWriting/materiaDetail",
id=materia_id,
w=w,
y=y,
)
signature = get_signature(
f=f,
key="wqKOwI3iZ46vVarlZhljNy8H9WPwmK61",
)
headers = {
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en,zh-CN;q=0.9,zh;q=0.8,en-US;q=0.7",
# 从 cookie 获取
"Auth-Token": ". . .",
"Cache-Control": "no-cache",
"Channel-Customization-Id": "2",
"Connection": "keep-alive",
"Content-Type": "application/json;charset=UTF-8",
"Origin": "https://miaobi.xinhuaskl.com",
"Pragma": "no-cache",
"Referer": "https://miaobi.xinhuaskl.com/ai-writing?mode=writing",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
"apiSign-appId": "96aF61WQ", # 固定
"apiSign-nonce": y,
"apiSign-sign": signature,
"apiSign-timestamp": w,
"app-terminal-type": "pc",
"sec-ch-ua": '"Microsoft Edge";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
}
cookies = {
"Hm_lvt_bbacc385fc90fe61e409cc9099275f8a": "1718255506",
"Hm_lpvt_bbacc385fc90fe61e409cc9099275f8a": "1718255612",
"Auth-Token-Btmb": ". . .",
}
url = "https://miaobi.xinhuaskl.com/api/smartWriting/materiaDetail"
# 范文的 id 被固定了
data = {"id": materia_id}
data = json.dumps(data, separators=(",", ":"))
response = requests.post(url, headers=headers, cookies=cookies, data=data)
print(response.text)
print(response)