Java批量下载有道单词发音+与Anki卡片整合

it2026-03-05  3

起因

用Anki背单词,Android手机上面用AnkiHelp往AnkiDroid添加单词的时候,发音用的是有道的api

之前在PC/MacOS/Android三端都可以正常使用,正常发音。之后各端分别更新了几个版本之后,渐渐发音不好用了。发现只有保存了mp3附件的单词才能够正常发音。 当然首先我是去修改anki卡片,改了半天终于能够让PC端的Anki调用有道api发音了,但是到Android手机上面又不能发音了,手机上面还不好调试。又去官网看了看。 Anki官网Api

大意是说,Anki只是部分支持JavaScript,由于JavaScript太丰富了,Anki不保证现在能用JavaScript实现的功能,在未来Anki更新后还能继续使用,所以建议避免使用JavaScript。

So,PC能发音,Android不能发音大概就是这个锅了。既然用Mp3音频的能够正常发音,那就手动全都修改成Mp3的音频吧!

下载准备

首先,有道的Api:

api仅有两个参数,就是发音类型和单词,在audio=后面加上单词就ok了,type=0为美国发音,type=1为英国发音。

例子,美音 king 发音(点击链接): http://dict.youdao.com/dictvoice?type=0&audio=king

例子,英音 king 发音(点击链接): http://dict.youdao.com/dictvoice?type=1&audio=king

由于主要语言用的是Java,就用参考了网上部分的代码,改了改。 参考: https://blog.csdn.net/sinat_42483341/article/details/96342364 https://blog.csdn.net/humanking7/article/details/88630856

从Anki导出需要下载的单词列表

第三步:可以发现每一行的第一个单词就是我们需要的单词,后面都是不需要的内容。我们可以用正则表达式,筛选出我们要的单词。

^\b\w*\b

解释一下这个正则表达式:匹配字符串开头,单词开头,匹配字母数字无数个,单词结尾

Java代码

Application

import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 爬取指定链接的一组MP3 文件 * * 放入指定的目录中 * * @author XuDong * */ public class Application { public static void main(String[] args) { System.out.println("请输入需要的单词发音类型:0-美式 1-英式"); Scanner scanner = new Scanner(System.in); String targetType = scanner.next(); if(targetType.equals("1") && targetType.equals("0")){ System.out.println("您输入的是"+ targetType +",请输入0或1,不支持其他类型!"); return; } //有道api 美式:type=0 英式:type=0 String baseUrl = "http://dict.youdao.com/dictvoice?type=" + targetType + "&audio="; System.out.println("请输入单词txt地址,如: E:\\YouDaoDownload\\ankiword.txt"); scanner = new Scanner(System.in); String targetWordTxt = scanner.next(); File file = new File(targetWordTxt); if(!file.exists()){ System.out.println(targetWordTxt + "\t 文件目录不存在,请重新确认!"); return; } if(!file.getName().endsWith(".txt")){ System.out.println(targetWordTxt + "\t 不是txt结尾,请重新确认"); return; } //获取单词列表 BufferedReader reader = null; String lineWord = null; int line =1; try { System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new FileReader(file)); while ((lineWord = reader.readLine()) != null) { System.out.print("Line"+ line); String word = ""; //正则表达式 匹配每行的第一个单词 String patt = "^\\b\\w*\\b"; Pattern pattern = Pattern.compile(patt); Matcher matcher = pattern.matcher(lineWord); while (matcher.find()){ word = matcher.group();//返回匹配的字符串 } //匹配每行的单词 if(word.equals("")){ System.out.print("\t \t \t单词匹配失败"); continue; } System.out.print("\t" + word); String wordUrl = baseUrl+ word; DownloadUtils downloadUtils = new DownloadUtils(wordUrl, word, "mp3",file.getParent()+"\\words"); try { downloadUtils.httpDownload(); System.out.print("\t \t \t下载成功"); } catch (Exception e) { System.out.print("\t \t \t下载失败"); e.printStackTrace(); } System.out.println(); line ++ ; } reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(reader != null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

DownloadUtils

import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class DownloadUtils { // 目标链接字符串 private String wordUrl; // 单词字符串 private String wordString; // 目标文件的格式 private String targetType; // 存放文件路径 private File rootDir; public DownloadUtils(String wordUrl, String wordString, String targetType, File rootDir) { super(); this.wordUrl = wordUrl; this.wordString = wordString; this.targetType = targetType; this.rootDir = rootDir; } public DownloadUtils(String wordUrl, String wordString, String targetType, String rootDir) { super(); this.wordUrl = wordUrl; this.wordString = wordString; this.targetType = targetType; this.rootDir = new File(rootDir); } public DownloadUtils() { super(); } /** * 开始下载 * * @throws Exception */ public void httpDownload() throws Exception { validate(); final String urls = wordUrl; HttpURLConnection urlConnection; urlConnection = (HttpURLConnection) new URL(urls) .openConnection(); // 开启链接 urlConnection.connect(); InputStream inputStream = urlConnection.getInputStream(); if(!rootDir.exists()){ rootDir.mkdirs(); } File temp = new File(rootDir, wordString + "." + targetType); //if (!temp.exists()) { temp.createNewFile(); //} FileOutputStream fileOutputStream = new FileOutputStream(temp, true); int tem; while (-1 != (tem = inputStream.read())) { fileOutputStream.write(tem); fileOutputStream.flush(); } fileOutputStream.close(); inputStream.close(); } private void validate() throws Exception { if (wordUrl == null || wordUrl.equals("")) { throw new Exception("下载路径不能为空!"); } if (null == rootDir ) { throw new Exception("目标文件夹不存在!"); } } }

运行

运行步骤

输入需要的发音类型输入刚刚导出的txt文件地址

运行结果

单词与Anki匹配

参考: https://blog.csdn.net/weixin_30933531/article/details/96396564

将下载的音频复制到:C:\Users\User\AppData\Roaming\Anki2\Anki用户名\collection.media

选中所有需要匹配的单词,进行查找替换

把有道的url替换成本地音频,分两步

先替换前面的,注意限定替换的字段,不勾选"以正则表达式"

替换后面的,用正则表达式 &type=\d ,试了半天发现这里面的查找居然是用的html的转义字符,不能直接用 & 查找。

再用正常的 & 替换一下,似乎字段里面有的是html标记的,有的就是正常的&,头大!

替换完成后,确保字段里面的内容在 C:\Users\XuDong\AppData\Roaming\Anki2\用户名\collection.media 中能够匹配。

最后试一下发音,完美!


懒人jar包

为了方便不会Java的人,这里附上一个可以直接使用的jar包

链接:https://pan.baidu.com/s/1_3Q2exgvDlcO3HgUzyB7ow 提取码:cpp1

懒人jar包使用方法

Win+R ,打开cmd窗口

输入 java -jar (-jar后面需要一个空格),然后拖入jar包

选择发音

输入txt文本地址

最新回复(0)