qidao123.com技术社区-IT企服评测·应用市场

标题: Java实现单词的翻译(详解爬虫操纵) [打印本页]

作者: 天津储鑫盛钢材现货供应商    时间: 2024-12-20 19:22
标题: Java实现单词的翻译(详解爬虫操纵)
JAVA通过Crawler实现英语单词的翻译

首先声明一点,这种方法仅限于低频次的交互来获取翻译信息,一旦一秒内大量的哀求会被重定向,那就直接不能用了
如果希望可以批量查询英语单词翻译,可以查看我的下一篇博客。
接着我们上一讲Java如何用HaspMap统计次数并排序详解 - ivanlee717 - 博客园的末端,我们获取到了一个高频次排序好的列表,接下来的任务就是要把这么一大堆的单词举行翻译,我们想要得到每个单词的音标,有什么词性以及对应的翻译。如今我们就来讲讲通过网络来实现单词的翻译。
Java的HttpURLConnection类可以帮助我们发送HTTP哀求,并获取相应的HTTP相应。我们可以设置哀求头、哀求方法、哀求参数等信息,来模仿欣赏器行为。
  1. <dependency>
  2.     <groupId>org.apache.httpcomponents.client5</groupId>
  3.     <artifactId>httpclient5</artifactId>
  4.     <version>5.1</version>
  5. </dependency>
  6. <dependency>
  7.     <groupId>org.jsoup</groupId>
  8.     <artifactId>jsoup</artifactId>
  9.     <version>1.15.3</version>
  10. </dependency>
复制代码
private static final String TRANSLATE_URL = "http://www.baidu.com/s?wd=";这个网页就是我们寻常百度查词的地址

我就希望可以得到两种音标,还有对应的词性和翻译。具体用到的两个依赖,一个是对于网页的解析Jsoup,这个和python的BS4根本原理划一,还有一个就是用于网络哀求的http依赖。
  1. import org.jsoup.Jsoup;
  2. import java.net.URLEncoder;
  3. import org.jsoup.nodes.Document;
  4. import org.jsoup.nodes.Element;
  5. import org.jsoup.select.Elements;
  6. import java.net.HttpURLConnection;
  7. import java.net.URL;
复制代码
第一步我们首先要对查询的文字举行一个编码(这一步在项目里不必要有,因为前序操纵已经确定这个是String类型了)
  1. String encodedWord = URLEncoder.encode(word, StandardCharsets.UTF_8.toString());
  2. // 编码查询词,防止特殊字符导致的URL解析错误
复制代码
第二步是向url发起链接
  1. // 构建完整的URL,包括查询参数
  2. URL url = new URL(TRANSLATE_URL + encodedWord);
  3. // 打开连接
  4. HttpURLConnection connection = (HttpURLConnection) url.openConnection();
复制代码
这里我们将URL封装成了带有网络协议等信息的实例对象来方便我们调用Connection方法。


如今创建好连接之后,我们可以看一下连接里面的数据。

可以看到哀求体里面没有任何的数据段,如许去举行多次读取页面的操纵会让百度感觉很”陌生“,所以如今要去哀求头里加一些数据,让这个访问看起来就是真实的。
  1. // 创建一个可变的 Map 来存储请求头
  2.         Map<String, String> headers = new HashMap<>();
  3.         headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
  4.         headers.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
  5.         headers.put("Connection", "keep-alive");
  6.         headers.put("Cookie", "BIDUPSID=2BCC6FC9896B4237256E7EC335CECF0A; PSTM=1726058803....");
  7.         headers.put("Host", "www.baidu.com");
  8.         headers.put("Upgrade-Insecure-Requests", "1");
  9.         headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0");
复制代码
这些内容都可以直接在自己的网页端查到。我们用一个map来举行存储,然后一次添加到
  1. // 添加自定义请求头
  2. for (Map.Entry<String, String> entry : headers.entrySet()) {
  3.     connection.setRequestProperty(entry.getKey(), entry.getValue());
  4. // 设置请求方法为GET
  5. connection.setRequestMethod("GET");
复制代码
到这一步我们的哀求就算是发送完成了。接下来就是服务器的相应,200就是相应成功了
  1. // 获取响应码
  2. int responseCode = connection.getResponseCode();
  3. StringBuilder response = new StringBuilder();
  4. // 如果响应码为200,表示请求成功
  5. if (responseCode == HttpURLConnection.HTTP_OK) {
  6.     // 获取响应流
  7.     BufferedReader reader = new BufferedReader(
  8.         new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)
  9.     );
  10.     String line;
  11.     // 读取响应内容
  12.     while ((line = reader.readLine()) != null) {
  13.         response.append(line);
  14.     }
  15.     reader.close();
  16. }
复制代码
在 Java 的网络编程中,当创建了一个网络连接(比如通过 Socket 连接大概 HttpURLConnection 等创建的连接,这里的 connection 就是代表如许一个已创建的连接对象),可以通过调用 getInputStream() 方法获取这个连接对应的输入流。这个输入流里包含了对方(服务器等)发送过来的数据,不外它是以字节流的情势存在的,原始状态下不太方便直接按文本内容举行读取操纵。

又有一个题目,为什么不直接使用 connection.getInputStream() 创建 BufferedReader?
总之,reader读到的信息就是获取的那个页面的源码。我们把他存到一个String对象里面。
接下来才是真正意义上的爬取操纵。
  1. Document doc = Jsoup.parse(response.toString());
  2. Elements posElements = doc.select("span.part-name_3R3ee");
  3. Elements En_phoneticElements = doc.select("span.orginal-txt_3dDqw");
  4. Elements US_phoneticElements = doc.select("sapn.orginal-txt_3dDqw");
复制代码

能看到在html标签里面,英式的发音藏在一个span标签里面,相对应的翻译

我就不一一列举了,用doc.select方式找到对应的标签举行提取。我们可以定义一个DTO大概一个数据库按照类型把他们都存进来。
  1. wordModel.setWord(word);
  2. wordModel.setEnPronunciation(En_phoneticElements.first().text());
  3. wordModel.setUsPronunciation(US_phoneticElements.first().text());
复制代码

根据这种写法就得到了我们的音标。但是又有个题目,音标只有一个,但是单词的翻译可能会有很多个,所以单纯的提取词性和翻译就会有题目。

我们得到两个travel的词性,理论上我们必要通过一个for循环来获取。通太过析源码,我们可以看到代码一个词性和对应的翻译都放在一个大的div标签了。

但如今又有一个题目就是这个翻译并不是一个字符串,是一个列表,多个span标签组成的。所以我们想要把翻译搞到一起就得多写两句代码,把列表换成字符串。
  1. Elements translationElements = parent.select("span.mean-text_4MwRe");
  2. StringBuilder translations = new StringBuilder();
  3. for (Element element : translationElements) {
  4.     // 去除分号,避免重复
  5.     String text = element.text().replace(";", "").trim();
  6.     if (!text.isEmpty()) {
  7.         translations.append(text).append(";");
  8.     }
  9. }
复制代码

把数据格式安排明白之后,我们就可以继续存储数据了。
  1. for (Element posElement : posElements) {
  2.             // 获取当前词性的翻译和音标
  3.             Element parent = posElement.parent();
  4.             if (parent != null) {
  5.                 Elements translationElements = parent.select("span.mean-text_4MwRe");
  6.                 StringBuilder translations = new StringBuilder();
  7.                 for (Element element : translationElements) {
  8.                     // 去除分号,避免重复
  9.                     String text = element.text().replace(";", "").trim();
  10.                     if (!text.isEmpty()) {
  11.                         translations.append(text).append(";");
  12.                     }
  13.                 }
  14.                 // 创建一个结果映射
  15.                 Map<String, String> result = new HashMap<>();
  16.                 result.put("translation", translations.toString());
  17.                 result.put("pos", posElement.text());
  18.                 results.add(result);
  19.             }
  20.         }
复制代码
终极的results当然是多个map映射的列表了,不要嫌麻烦,我们继续转换数据,把得到的词性翻译列表转换成一个可以直观的字符串。
  1. StringBuilder combinedResult = new StringBuilder();
  2. for (Map<String, String> result : results) {
  3.     String pos = result.get("pos");
  4.     String translation = result.get("translation");
  5.     combinedResult.append(pos).append(translation).append(" ");
  6. }
  7. wordModel.setDescription(combinedResult.toString());
复制代码

如许的话,我们就把所有的一个浅易的爬虫式的单词翻译讲清楚了。我们后续会继续讲如何把查询到的翻译存到本地数据库。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4