有道ai写作,突破免费限制,无限制使用

预览效果

  • 文末提供源码包及apk下载地址

有道ai写作python版

python 复制代码
import hashlib
import time
import json
import ssl
import base64
import uuid

from urllib.parse import quote
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from sseclient import SSEClient


# 生成唯一的用户id
yduuid=str(uuid.uuid4()).replace('-','')

session = requests.session()
lastModified = requests.get('https://fanyi.youdao.com/index.html').headers['last-Modified']
_nlmf = int(time.mktime(time.strptime(lastModified, "%a, %d %b %Y %H:%M:%S GMT")))
session.headers = {
    'Referer': 'https://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
}
session.get(f'https://rlogs.youdao.com/rlog.php?_npid=fanyiweb&_ncat=pageview&_ncoo=935962676.0432019&_nssn=NULL&_nver=1.2.0&_ntms={time.time()}&_nref=&_nurl=https%3A%2F%2Ffanyi.youdao.com%2Findex.html%23%2F&_nres=1920x1080&_nlmf={_nlmf}&_njve=0&_nchr=utf-8&_nfrg=%2F&/=NULL&screen=1920*1080')

# 获取md5加密结果
def get_md5(s,is_hex=True):
    md5=hashlib.md5()
    md5.update(s.encode())
    if is_hex:
      return md5.hexdigest()
    return md5.digest()

# AES-128-CBC解密
def decrypt(encrypted_data, key, iv):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_data = cipher.decrypt(base64.b64decode(encrypted_data))
    return decrypted_data.decode('utf-8')


def get_token_and_key():
    params = {
        'product': 'webdict', 
        'appVersion': '1.0', 
        'client': 'web', 
        'mid': '1', 
        'vendor': 'web',
        'screen': '1', 
        'model': '1', 
        'imei': '1',
        'network': 'wired', 
        'keyfrom': 'webdict',
        'keyid': 'ai-write',
        'mysticTime': str(int(time.time()*1000)),
        'yduuid': yduuid,
    }
    # 参数排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    sorted_params.append(("key","xuiC95RuooxC8Q51UJtdod1plLUhdAmt"))

    encoded_params = '&'.join([f"{key}={value}" for key, value in sorted_params])
    print("encoded_params:::::"+encoded_params)
    # 获取sign签名
    sign=get_md5(encoded_params)
    params.update({"sign":sign})
    params.update({"pointParam":"appVersion,client,imei,keyfrom,keyid,mid,model,mysticTime,network,product,screen,vendor,yduuid,key"})

    response = session.get('https://luna-ai.youdao.com/write/ai/web/ktf', params=params, verify=False)
    print(response.text)

    #============解密数据===============================
    e=response.text.replace("-","+").replace("_","/")
    key=get_md5("IIS0fzL@zGv1^zO2%NcZiTcM=98WYxdun$CJE1KUKFfEhz&zpEC0fdXfvGqy*N!r",is_hex=False)
    iv=get_md5("kG_oSxAXx#xjbiOKAkf9915Ko-XclOBP-GSgfo6E9ZB%9WvgcY6Y7dmje!+m5g#d",is_hex=False)

    s=decrypt(e,key,iv).replace('\x02', '')
    print("解密数据::::"+s)
    decode_data=json.loads(json.loads(s))
    return decode_data


def get_result(query):
    decode_data=get_token_and_key()
    params = {
        'product': 'webdict', 
        'appVersion': '1.0', 
        'client': 'web', 
        'mid': '1', 
        'vendor': 'web',
        'screen': '1', 
        'model': '1', 
        'imei': '1',
        'network': 'wired', 
        'keyfrom': 'webdict',
        'keyid': 'ai-write-web',
        'mysticTime': str(int(time.time()*1000)),
        'yduuid': yduuid,
        'functionId':'1',
        'query':quote(query),
        'userCustomize':quote(query),
        'token':decode_data["token"]
    }

    # 参数排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    sorted_params.append(("key",decode_data['sk']))

    encoded_params = '&'.join([f"{key}={value}" for key, value in sorted_params])
    print("encoded_params:::::"+encoded_params)
    # 获取签名字符串
    sign=get_md5(encoded_params)
    params.update({"sign":sign})
    print("签名字符串:"+sign)
    params.update({"pointParam":"appVersion,client,functionId,imei,keyfrom,keyid,mid,model,mysticTime,network,product,query,screen,token,userCustomize,vendor,yduuid,key"})

    # 数据为multipart/form-data格式
    multipart_data = MultipartEncoder(fields=params)
    # 修改请求头中的Content-Type
    session.headers['Content-Type']= multipart_data.content_type
    # 发送请求
    response = session.post('https://luna-ai.youdao.com/write/ai/template/sse', data=multipart_data, stream=True,verify=False)

    # 处理SSE流数据
    client=SSEClient(response)
    for event in client.events():
        # 判断事件类型
        if event.event=='message':
            # 不换行输出
            print(json.loads(event.data)['content'],end='')


if __name__=='__main__':
    keyword=input('请输入关键词:')
    get_result(keyword)

有道ai写作lua版

使用Aide lua打包为apk

  • 主要lua代码
lua 复制代码
require "import"
--import "androidx"
--import "androidx.appcompat.app.*"
--import "androidx.appcompat.view.*"
--import "androidx.appcompat.widget.*"
--import "android.app.*"
import "android.os.*"
import "android.widget.*"
import "android.view.*"
import "androidx.coordinatorlayout.widget.CoordinatorLayout"

local layout={
  CoordinatorLayout;
  layout_height="fill";
  layout_width="match_parent";
  {
    LinearLayout;
    layout_width="match_parent";
    orientation="vertical";
    layout_height="match_parent";
    {
      LinearLayout;
      layout_width="match_parent";
      orientation="horizontal";
      layout_height="wrap_content";
      {
        EditText;
        layout_marginTop="10";
        id="inputText";
        hint="请输入关键词";
        layout_weight=19;
        layout_marginLeft="5";
      };
      {
        Button;
        layout_marginTop="10";
        id="translateBtn";
        text="ai写作";
        layout_weight=1;
        layout_marginRight="5";
      };
    };
    {
      LinearLayout;
      layout_width="fill";
      layout_height="fill";
      {
        ScrollView;
        layout_width="fill";
        id="1";
        layout_height="fill";
        {
          TextView;
          layout_margin="10";
          layout_width="fill";
          id="resultView";
          layout_height="wrap_content";
        };
      };
    };
  };
};

--ui结束

activity.setContentView(loadlayout(layout))


-- 生成时间戳
function getTimestamp()
  local Date = luajava.bindClass "java.util.Date"
  return Date().getTime()
end

-- 字符串url编码
function urlEncode(s)
  -- url编码
  local s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)
  -- 逗号不编码
  return s:gsub(" ", "+"):gsub("%%2C",","):gsub("%%25","%%")
end


-- 字符串序列化
function tableToStr(tbl,sep)
  local str = ''
  local sep= sep or '&'
  for key, value in pairs(tbl) do
    str = str .. key .. '=' .. urlEncode(value) .. sep
  end
  return string.sub(str, 1, -2)
end

-- 拼接排序后的表为字符串
function tableToStr1(tbl)
  local str = ''
  for key, value in ipairs(tbl) do
    str = str .. value[1] .. '=' .. urlEncode(value[2]) .. '&'
  end
  return string.sub(str, 1, -2)
end

-- md5加密
function md5Encrypt(data,isHex)
  local MessageDigest = luajava.bindClass "java.security.MessageDigest"
  local md = MessageDigest.getInstance("MD5")
  local bytes = md.digest(String(data).getBytes())
  local isHex= (isHex==nil) and true or false
  if isHex ==false then
    return bytes
  end
  local result = ""
  for i = 0, #bytes - 1 do
    local temp = string.format("%02x", (bytes[i] & 0xff))
    result = result .. temp
  end
  return result
end

-- AES解密
function decrypt(encryptStr, key, iv)
  local String = luajava.bindClass "java.lang.String"
  local SecretKeySpec = luajava.bindClass "javax.crypto.spec.SecretKeySpec"
  local IvParameterSpec = luajava.bindClass "javax.crypto.spec.IvParameterSpec"
  local Cipher = luajava.bindClass "javax.crypto.Cipher"
  local Base64 = luajava.bindClass "android.util.Base64"
  local algorithm = "AES"
  local mode = "AES/CBC/PKCS5Padding"
  local raw=SecretKeySpec(key,algorithm)
  local ivBytes = IvParameterSpec(iv)
  local cipher = Cipher.getInstance(mode)
  cipher.init(Cipher.DECRYPT_MODE, raw, ivBytes)
  local encode_content = Base64.decode(encryptStr, Base64.DEFAULT)
  local byte_content = cipher.doFinal(encode_content)
  return String(byte_content, "utf-8")
end

-- 公共请求参数定义
local base = {
  Cookies = {
    ['OUTFOX_SEARCH_USER_ID_NCOO'] = '1536815481.8081024',
    ['OUTFOX_SEARCH_USER_ID'] = '1773118125@192.168.0.1',
  },
  Headers = {
    ['Accept'] = 'application/json, text/plain, */*',
    ['Accept-Language'] = 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    ['Connection'] = 'keep-alive',
    ['Origin'] = 'https://fanyi.youdao.com',
    ['Referer'] = 'https://fanyi.youdao.com/',
    ['Sec-Fetch-Dest'] = 'empty',
    ['Sec-Fetch-Mode'] = 'cors',
    ['Sec-Fetch-Site'] = 'same-site',
    ['User-Agent'] =
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
    ['sec-ch-ua'] = '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"',
    ['sec-ch-ua-mobile'] = '?0',
    ['sec-ch-ua-platform'] = '"Windows"',
  },
  Params = {
    ['product'] = 'webdict',
    ['appVersion'] = '1.0',
    ['client'] = 'web',
    ['mid'] = '1',
    ['vendor'] = 'web',
    ['screen'] = '1',
    ['model'] = '1',
    ['imei'] = '1',
    ['network'] = 'wired',
    ['keyfrom'] = 'webdict',
    ['keyid'] = 'ai-write',
    ['mysticTime'] = '',
    ['yduuid'] = '',
  }
}

-- 生成全局唯一用户id,同一id只有10次免费机会,每次生成不同id即可跳过免费限制
function genUUID()
  local UUID=luajava.bindClass 'java.util.UUID'
  return string.gsub(tostring(UUID.randomUUID()),'-','')
end


--复制表
function copyTable(original)
    local copy = {}
    for key, value in pairs(original) do
        if type(value) == "table" then
            copy[key] = copyTable(value) -- 递归复制子表
        else
            copy[key] = value
        end
    end
    return copy
end

-- 获得按键排序后的参数table
function getSortedParams(params)
  local function compare(a, b)
    return a[1] < b[1]
  end
  local sorted_params = {}
  for key, value in pairs(params) do
    table.insert(sorted_params, { key, value })
  end
  table.sort(sorted_params, compare)
  return sorted_params
end

-- 获取token和key
function getTokenAndKey()
  local JSON=require 'cjson'
  local url = 'https://luna-ai.youdao.com/write/ai/web/ktf'
  -- 复制公共表头和参数
  local headers = copyTable(base.Headers)
  local params = copyTable(base.Params)
  local cookies = tableToStr(base.Cookies,";")

  -- 设置参数
  params['mysticTime']=getTimestamp()
  -- 生成yduuid
  base.yduuid=genUUID()
  params['yduuid']=base.yduuid

  -- 按照table中键进行排序,并指定排序函数
  local sorted_params=getSortedParams(params)
  local encoded_params = tableToStr1(sorted_params)
  encoded_params = encoded_params .. "&key=xuiC95RuooxC8Q51UJtdod1plLUhdAmt"
  
  print("获取签名字符串"..encoded_params)

  local sign = md5Encrypt(encoded_params)
  print("获取签名的sign:"..sign)
  params['sign'] = sign
  params['pointParam'] =
  "appVersion,client,imei,keyfrom,keyid,mid,model,mysticTime,network,product,screen,vendor,yduuid,key"

  local finalUrl=url..'?'..tableToStr(params)
  print("请求地址"..finalUrl)
  -- 发送请求
  local httpTask=Http.get(finalUrl,cookies,nil,headers,function () end)
  local result=httpTask.get()
  local code,content,cookie,header=result[0],result[1],result[2],result[3]

  -- 解密数据
  local b64str=content:gsub(' ','+'):gsub('-','+'):gsub('_','/')

  -- des解密
  local key=md5Encrypt('IIS0fzL@zGv1^zO2%NcZiTcM=98WYxdun$CJE1KUKFfEhz&zpEC0fdXfvGqy*N!r',false)
  local iv=md5Encrypt('kG_oSxAXx#xjbiOKAkf9915Ko-XclOBP-GSgfo6E9ZB%9WvgcY6Y7dmje!+m5g#d',false)
  local s=tostring(decrypt(b64str,key,iv))
  s=string.gsub(s,'\x02','')
  print("token和sign"..s)
  local decodeData=JSON.decode(JSON.decode(s))
  return decodeData['sk'],decodeData['token']
end


-- 获取翻译结果
function getResult(query)
  local JSON=require 'cjson'
  local url = 'https://luna-ai.youdao.com/write/ai/template/sse'
  -- 复制公共表头和参数
  local headers = copyTable(base.Headers)
  local params = copyTable(base.Params)
  
  -- 获取token和key
  local key,token=getTokenAndKey()
  -- 设置参数
  params['mysticTime']=getTimestamp()
  params['yduuid']=base.yduuid
  params['keyid']='ai-write-web'
  params['functionId']='1'
  params['query']=urlEncode(query)
  params['userCustomize']=urlEncode(query)
  params['token']=token

  -- 设置头部
  local boundary="jeb3u3g5vh5v3hh2h2hg5g6v7vh4hehdjd"
  headers['Content-Type']='multipart/form-data;boundary='..boundary
  headers['Accept']='*/*, text/event-stream'
  headers["Referer"]="https://fanyi.youdao.com/aiwrite/document"

  -- 按照table中键进行排序,并指定排序函数
  local sorted_params=getSortedParams(params)
  local encoded_params=tableToStr1(sorted_params)

  encoded_params = encoded_params .. "&key="..key
  print('生成签名的参数字符串:::'..encoded_params)
  local sign = md5Encrypt(encoded_params)
  params['sign'] = sign
  print("签名结果:::"..sign)
  params['pointParam'] = 'appVersion,client,functionId,imei,keyfrom,keyid,mid,model,mysticTime,network,product,query,screen,token,userCustomize,vendor,yduuid,key'


  -- 处理sse事件流数据
  local OkHttpClient=luajava.bindClass 'okhttp3.OkHttpClient'
  local MultipartBody=luajava.bindClass 'okhttp3.MultipartBody'
  local Request=luajava.bindClass 'okhttp3.Request'
  local RealEventSource=luajava.bindClass 'okhttp3.internal.sse.RealEventSource'
  local EventSource=luajava.bindClass 'okhttp3.sse.EventSource'
  local EventSourceListener=luajava.bindClass 'okhttp3.sse.EventSourceListener'
  local TimeUnit=luajava.bindClass 'java.util.concurrent.TimeUnit'


  local client =OkHttpClient.Builder().connectTimeout(20,TimeUnit.SECONDS).readTimeout(20,TimeUnit.SECONDS).build()
  local requestBodyBuilder=MultipartBody.Builder().setType(MultipartBody.FORM)
  --添加请求参数
  for k,v in pairs(params) do
    requestBodyBuilder.addFormDataPart(String(k),String(tostring(v)))
  end
  local requestBody=requestBodyBuilder.build()

  local requestBuilder = Request.Builder().url(url)
  -- 添加请求头
  for k,v in pairs(headers) do
    requestBuilder.header(String(k),String(tostring(v)))
  end

  local request=requestBuilder.post(requestBody).build()
  -- 事件监听器
  local listener=EventSourceListener({
    onOpen=function(eventSource,response)
      print("建立sse链接")
      print(response)
    end,
    onEvent=function(eventSource,id,_type,data)
      -- 判断事件类型
      if _type=="message" then
        -- 更新ui
        activity.runOnUiThread(Runnable{
          run=function()
            local result=JSON.decode(data)
            resultView.append(result["content"])
          end
        })

      end
    end,
    onFailure=function(eventSource,t,response)
      print("打开链接失败")
    end,
    onClose=function(eventSource)
      print("连接关闭")
    end
  })

  local eventSource=RealEventSource(request,listener)
  --开启事件源连接
  eventSource.connect(client)
end


-- 测试
translateBtn.onClick=function()
  -- 清空上一次的结果
  resultView.setText("")
  local inputStr=tostring(inputText.getText())
  getResult(inputStr)
end

apk源码包及apk下载地址

相关推荐
数据智能老司机2 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机3 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i3 小时前
drf初步梳理
python·django
每日AI新事件3 小时前
python的异步函数
python
这里有鱼汤4 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook13 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室14 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三15 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试