Android 开发 有道翻译
Android 開發(fā) 有道翻譯
- 爬取有道翻譯api接口,定制專屬于你的翻譯官
- 抓取有道翻譯數(shù)據(jù)
- Android 網(wǎng)絡權(quán)限設置
- Android 邏輯代碼
- post請求
- (1)產(chǎn)生加密數(shù)據(jù)(補充:Android進行網(wǎng)絡請求是必須新開線程)
- (2)封裝MD5函數(shù)
- (3)http請求添加請求體和請求頭
- (5)解析返回的json數(shù)據(jù),通過正則表達式提取翻譯結(jié)果
- 調(diào)試,打包,簽名,加固,發(fā)布。
- 1.build 構(gòu)建apk
- 2.360加固簽名
- 完整代碼
- 效果圖
爬取有道翻譯api接口,定制專屬于你的翻譯官
1.首先是通過瀏覽器的開發(fā)者工具抓取有道翻譯的數(shù)據(jù)包,解析request與response。
2.然后會發(fā)現(xiàn)這個是一個post請求,而且居然數(shù)據(jù)還加密,而這就需要通過js逆向來分析,這里面有MD5,時間戳,隨機數(shù),然后再糅合在一起。
3.通過正則解析響應回來的json數(shù)據(jù)
4.最后就是安卓的UI設計以及業(yè)務邏輯代碼了。
抓取有道翻譯數(shù)據(jù)
打開有道翻譯網(wǎng)頁版開始抓取數(shù)據(jù)包,可以發(fā)現(xiàn)salt,sign,lts,bv,這幾個請求參數(shù)是加密了的,通過js逆向分析可以得出:
Android 網(wǎng)絡權(quán)限設置
問題:無法進行網(wǎng)絡請求;
原因:Android9.0以后只支持HTTPS請求了,所有的http請求都認為是不安全的,所以不能訪問。;
解決方法:
第一步:首先是最基本的網(wǎng)絡權(quán)限 在AndroidManif.xml中添加
第二步:在res文件夾中新建xml文件夾添加network_security_config.xml文件,文件內(nèi)容如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>第三步:在AndroidManif.xml文件中注冊寫命令文件:
android:networkSecurityConfig="@xml/network_security_config"Android 邏輯代碼
post請求
上面已經(jīng)說完邏輯了,現(xiàn)在就要實現(xiàn)okhttp向有道翻譯發(fā)送post請求,并返回翻譯結(jié)果。
我們剛剛已經(jīng)解析出加密的數(shù)據(jù)了,而我們現(xiàn)在要做的就是產(chǎn)生加密的數(shù)據(jù)并發(fā)送給
有道翻譯服務器。也就是post請求添加請求頭和表單請求體了。
(1)產(chǎn)生加密數(shù)據(jù)(補充:Android進行網(wǎng)絡請求是必須新開線程)
public void youdao_interpret(String arg){new Thread(){final String string = arg;@Overridepublic void run(){//時間戳 r = tsString ts = String.valueOf(System.currentTimeMillis());//隨機數(shù) i = saltRandom random = new Random();String salt = ts+String.valueOf(random.nextInt(10));//請求頭String ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36";// md5 t = bvString bv = "";try {bv = MD5(ua);} catch (Exception e) {e.printStackTrace();}// xString x="fanyideskweb" + this.string + salt + "Tbh5E8=q6U3EXe+&L[4c@";// signString sign = "";try {sign=MD5(x);} catch (Exception e) {e.printStackTrace();}(2)封裝MD5函數(shù)
//MD5函數(shù)public static String MD5(String data) throws Exception {java.security.MessageDigest md = MessageDigest.getInstance("MD5");byte[] array = md.digest(data.getBytes("UTF-8"));StringBuilder sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}return sb.toString().toUpperCase();}(3)http請求添加請求體和請求頭
//請求有道翻譯的完整網(wǎng)址String url="http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule";//創(chuàng)建請求體表單 >>填入請求翻譯的內(nèi)容FormBody formBody = new FormBody.Builder().add("i",this.string).add("smartresult","dict").add("salt",salt).add("sign",sign).add("lts",ts).add("bv",bv).add("client","fanyideskweb").add("doctype","json").add("version","2.1").add("keyfrom","fanyi.web").build();formBody.contentType();//創(chuàng)建請求對象 >>并填入form表單Request request = new Request.Builder().url(url).addHeader("User-Agent",ua) //請求頭.addHeader("Cookie","OUTFOX_SEARCH_USER_ID=-1876541902@10.169.0.84; OUTFOX_SEARCH_USER_ID_NCOO=2111552283.5701284; JSESSIONID=aaaNARG2_9FBJ-Ce81qBx; ___rl__test__cookies=1609821642788") //請求頭.addHeader("Referer","http://fanyi.youdao.com/") //請求頭.post(formBody).build();//準備請求對象 Client:客戶Call call = okHttpClient.newCall(request);(5)解析返回的json數(shù)據(jù),通過正則表達式提取翻譯結(jié)果
try{Response response = call.execute();//讀取響應String string = response.body().string(); //獲取響應的字符串 還有byteStream方法,獲取二進制數(shù)據(jù)Log.d(TAG, "post請求成功");//顯示返回的數(shù)據(jù)Log.d(TAG, "返回的全部:"+string);//提取數(shù)據(jù)Pattern compile =Pattern.compile("\"tgt\":\".*?\"");Pattern compile1 =Pattern.compile("entries\":\\[\"\",\".*");//匹配Matcher matcher = compile.matcher(string);while(matcher.find()){//輸出每個匹配的字符you_dao = matcher.group().substring(7,matcher.group().length()-1);}//更多翻譯匹配Matcher matcher1 = compile1.matcher(string);while(matcher1.find()){//輸出每個匹配的字符entries = matcher1.group().substring(14,matcher1.group().length()-17).replace("\\r\\n\",\""," ");Log.d(TAG, "詞根匹配的為"+entries);}}catch (IOException e ){String string = e.getMessage();Log.d(TAG, "post失敗");}}調(diào)試,打包,簽名,加固,發(fā)布。
1.build 構(gòu)建apk
2.360加固簽名
完整代碼
package com.example.translate;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView;import java.io.IOException; import java.security.MessageDigest; import java.util.Date; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern;import okhttp3.Call; import okhttp3.FormBody; import okhttp3.Request; import okhttp3.Response; import okhttp3.OkHttpClient;public class MainActivity extends AppCompatActivity {//debug調(diào)試String TAG = "mytag";//聲明組件componentButton button0;TextView text0,text1,text2;//創(chuàng)建全局OkHttp對象private OkHttpClient okHttpClient;//全局翻譯結(jié)果變量String you_dao ="";//更多翻譯的詞性String entries = "";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//找到組件button0 = findViewById(R.id.button0);text0 = findViewById(R.id.text0);text1 = findViewById(R.id.text1);text2 = findViewById(R.id.text2);//創(chuàng)建okhttp對象okHttpClient = new OkHttpClient();}//交互@Overrideprotected void onResume() {super.onResume();//翻譯按鈕監(jiān)聽事件button0.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//獲取文本框內(nèi)容String string = text0.getText().toString();//請求有道翻譯//interpret(string);youdao_interpret(string);//線程延時sleep(300);//通過全局變量在results顯示翻譯結(jié)果text1.setText(you_dao);text2.setText(entries);}});}//有道翻譯函數(shù)public void interpret(String arg){new Thread(){final String string = arg;@Overridepublic void run(){//請求有道翻譯的簡化網(wǎng)址String url="http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule";//創(chuàng)建請求體表單 >>填入請求翻譯的內(nèi)容FormBody formBody = new FormBody.Builder().add("i",this.string).add("doctype","json").build();formBody.contentType();//創(chuàng)建請求對象 >>并填入form表單Request request = new Request.Builder().url(url).addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36") //請求頭.post(formBody).build();//準備請求對象 Client:客戶Call call = okHttpClient.newCall(request);//response 是響應對象try{Response response = call.execute();//讀取響應String string = response.body().string(); //獲取響應的字符串 還有byteStream方法,獲取二進制數(shù)據(jù)Log.d(TAG, "post請求");//顯示返回的數(shù)據(jù)Log.d(TAG, string);//提取數(shù)據(jù)Pattern compile =Pattern.compile("\"tgt\":\".*?\"");//匹配Matcher matcher = compile.matcher(string);while(matcher.find()){//輸出每個匹配的字符you_dao = matcher.group().substring(7,matcher.group().length()-1);}}catch (IOException e ){String string = e.getMessage();Log.d(TAG, "post失敗");}}}.start();}//js逆向的完整請求函數(shù)public void youdao_interpret(String arg){new Thread(){final String string = arg;@Overridepublic void run(){//時間戳 r = tsString ts = String.valueOf(System.currentTimeMillis());//隨機數(shù) i = saltRandom random = new Random();String salt = ts+String.valueOf(random.nextInt(10));//請求頭String ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36";// md5 t = bvString bv = "";try {bv = MD5(ua);} catch (Exception e) {e.printStackTrace();}// xString x="fanyideskweb" + this.string + salt + "Tbh5E8=q6U3EXe+&L[4c@";// signString sign = "";try {sign=MD5(x);} catch (Exception e) {e.printStackTrace();}//請求有道翻譯的完整網(wǎng)址String url="http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule";//創(chuàng)建請求體表單 >>填入請求翻譯的內(nèi)容FormBody formBody = new FormBody.Builder().add("i",this.string).add("smartresult","dict").add("salt",salt).add("sign",sign).add("lts",ts).add("bv",bv).add("client","fanyideskweb").add("doctype","json").add("version","2.1").add("keyfrom","fanyi.web").build();formBody.contentType();//創(chuàng)建請求對象 >>并填入form表單Request request = new Request.Builder().url(url).addHeader("User-Agent",ua) //請求頭.addHeader("Cookie","OUTFOX_SEARCH_USER_ID=-1876541902@10.169.0.84; OUTFOX_SEARCH_USER_ID_NCOO=2111552283.5701284; JSESSIONID=aaaNARG2_9FBJ-Ce81qBx; ___rl__test__cookies=1609821642788") //請求頭.addHeader("Referer","http://fanyi.youdao.com/") //請求頭.post(formBody).build();//準備請求對象 Client:客戶Call call = okHttpClient.newCall(request);//response 是響應對象try{Response response = call.execute();//讀取響應String string = response.body().string(); //獲取響應的字符串 還有byteStream方法,獲取二進制數(shù)據(jù)Log.d(TAG, "post請求成功");//顯示返回的數(shù)據(jù)Log.d(TAG, "返回的全部:"+string);//提取數(shù)據(jù)Pattern compile =Pattern.compile("\"tgt\":\".*?\"");Pattern compile1 =Pattern.compile("entries\":\\[\"\",\".*");//匹配Matcher matcher = compile.matcher(string);while(matcher.find()){//輸出每個匹配的字符you_dao = matcher.group().substring(7,matcher.group().length()-1);}//更多翻譯匹配Matcher matcher1 = compile1.matcher(string);while(matcher1.find()){//輸出每個匹配的字符entries = matcher1.group().substring(14,matcher1.group().length()-17).replace("\\r\\n\",\""," ");Log.d(TAG, "詞根匹配的為"+entries);}}catch (IOException e ){String string = e.getMessage();Log.d(TAG, "post失敗");}}}.start();}//線程阻塞methodpublic void sleep(int ms){try{Thread.sleep(ms);}catch(InterruptedException e){e.getMessage();}}//MD5加密函數(shù)public static String MD5(String data) throws Exception {java.security.MessageDigest md = MessageDigest.getInstance("MD5");byte[] array = md.digest(data.getBytes("UTF-8"));StringBuilder sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}return sb.toString().toUpperCase();} }效果圖
總結(jié)
以上是生活随笔為你收集整理的Android 开发 有道翻译的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MFC应用的菜单,工具栏和状态栏(vs2
- 下一篇: android tv 云播放器,Andr