ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 9721|回复: 45

[分享] 破解百度翻译 VBA调用 网抓 爬虫 详细步骤

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2022-1-18 15:05 | 显示全部楼层 |阅读模式
本帖最后由 wodewan 于 2022-1-19 16:49 编辑

说明:本例子只供交流学习,如有违规请版主删除。。。
效果图: 2.gif

百度翻译有如下几种接口:
1. 官方API接口,这个要注册,论坛已有例子。
2. Sug接口(如下图)
   优点:这个接口没啥限制,也无需认证即可获取数据,直接Post请求即可获取。
   缺点:查询的数据不全,其实是你输入时界面下方的提示的联想数据,所以没啥用。

image.jpg


3. 网站返回数据的接口  ,优缺点也很明显
    优点:数据很全,很全。。。。
    缺点:有各种限制。。。。
    这里涉及2个接口,一个自动检测语言种类,一个获取翻译数据,如下图:

image.jpg


所以,目标就是第3个接口,待续。。。

ps://fanyi.baidu.com/v2transapi


Baidu_fy.rar

86.18 KB, 下载次数: 215

评分

12

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-18 15:27 | 显示全部楼层
本帖最后由 wodewan 于 2022-1-18 15:53 编辑

继续。。。。。

接1楼,先看第一个接口获取语言语种:https://fanyi.baidu.com/langdetect
image.jpg

有了上图的数据就可以了,下面一大堆COOKIE什么的先不用管,接着在VBA中发一个Post请求,可以发现,可以正常返回所需的数据。
就可以实现网站上的自动判断输入的语言种类功能了。
image.png

代码如下:
  1. Sub test()
  2. Dim User_agent, Content, Post_data, Url
  3. User_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36"
  4. Content = "application/x-www-form-urlencoded; charset=UTF-8"

  5. With CreateObject("WinHttp.WinHttpRequest.5.1")
  6.     Url = "https://fanyi.baidu.com/langdetect": Post_data = "query=" + "你好"
  7.     .Open "post", Url, False
  8.     .SetRequestHeader "User-Agent", User_agent
  9.     .SetRequestHeader "Content-Type", Content
  10.     .send Post_data
  11.     Debug.Print .responsetext
  12. End With

  13. End Sub
复制代码


TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-18 15:43 | 显示全部楼层
接着来看最重要的一个接口:
image.jpg

目标,sign和token怎么获取???
先看看元素面板有啥内容,直接搜索即可,sign找不到,但找到了token,而且和post发送的数据是一样的,如下图:
image.jpg

到这一步,好像都挺好找,就剩下一个sign了,待续。。。
image.jpg

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-18 16:00 | 显示全部楼层
本帖最后由 wodewan 于 2022-1-18 16:05 编辑

token有了,接着找sign,如下图,先不写了,等上面的帖子审核好了再说,待续。。。:
image.jpg

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-18 18:06 | 显示全部楼层
继续,要找sign,肯定要先找到Post发给服务器的数据内容,这就要调试JS了,所以第一步:下断点
image.png F12下可以看到下断点的方法很多,代码下断,DOM下断,XHR下端,等等,

对于这个例子其实不需要多复杂的抓包要求,因为需求很明显就是要找到发出去的数据包,所以根本不用去找就可以知道,既然有数据请求,肯定要有个send方法,从调用堆栈中可以大概猜的出来一个逻辑,如下图:
image.jpg 然后跟进去下断点调试
image.jpg
对于参数3很好解决,EXCEL自带Application.WorksheetFunction.EncodeURL()即可,
到目前这一步,其他的参数都可以解决,sign虽然可以确定但不知道怎么赋值的,然后就可以模拟发包了。


TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-18 19:16 | 显示全部楼层
本帖最后由 wodewan 于 2022-1-18 19:17 编辑

继续写点,上面已经在send处下了断点,但在这个断点处的sign已经是经过处理的了,所以仍然无法知道这个sign怎么来的,怎么办?当然你可以使用搜索大法在JS的汪洋大海中慢慢找,运气好也很快能找到,这里换一种方法:

这时就要知道一个知识点了,就是堆栈,栈结构有个规则就是先进后出,既然这样就到send前面去找,看谁调用了send,发现整个url地址是属于一个名称叫 t 的对象下的data属性,而整个t对象又是以函数的参数方式传进来的,所以这一页肯定是找不到,所以必须找到拼接整个url地址的函数才能知道sign是怎么来的。

image.jpg

继续向下一栈找,也就是调用send的那个ajax,在整个调用函数处也下断,刷新,看看有没有
这时看到一个i.send(b,r)函数,又出现一个h对象,里面也有拼接好的url和sign,不管它,和上面同样的方法
既然还是拼接的字符串就继续向上找,直到找到在什么地方拼接的这些参数,于是在这个函数的顶部终于是发现了
不是拼接的sign了,如下图:
image.jpg
但是,既然不是拼接的,这个值又是从那里赋值的呢?同样的方法,继续向前跟栈,进入下一栈找找也就是langeisdetect函数判断语言的那个方法
于是发现,原来所有的参数都是在这赋值的,包括那个sign,是由一个叫L(e)的函数计算得到的,直接控制台试验一下看下结果,确实就是最后的sign值,而参数就是最初传入的翻译的原始值:
image.jpg

到此,就找到了sign的函数直接点进去,就找到了这个函数的原型了,如下图。。。
image.jpg

到这里,其实已经完成了一大半,剩下的就是把这个js提取出来,然后本地执行获取sign,下面就是JS部分,不知各位有无兴趣了。。。



TA的精华主题

TA的得分主题

发表于 2022-1-19 09:16 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
感谢大神分享!教程说明详细,留名学习

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-19 10:45 | 显示全部楼层

接上面,JS部分
这个sign的计算函数在提取的时候注意2点:
1. 要把上面2个附带的小函数一同取出(其实就是主函数的子函数)
2. 其中,参数是查询的值,但其内部还有取一个window全局变量中的一个值,具体如下:
image.jpg


在VBA中运行时,并没有浏览器环境,但可以取到window.gtk,所以,可以稍微改写下整个函数,然后测试一下:
image.jpg
整个改写后的Js代码如下:可调用函数e,例如:var sign =  e(查询的词 , 获取的gtk值)
  1. function a(r) {
  2.     if (Array.isArray(r)) {
  3.         for (var o = 0, t = Array(r.length); o < r.length; o++)
  4.             t[o] = r[o];
  5.         return t;
  6.     }
  7.     return Array.from(r);
  8. }

  9. function n(r, o) {
  10.     for (var t = 0; t < o.length - 2; t += 3) {
  11.         var a = o.charAt(t + 2);
  12.         a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),
  13.             a = "+" === o.charAt(t + 1) ? r >>> a : r << a,
  14.             r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a
  15.     }
  16.     return r;
  17. }

  18. function e(r, gtk) {
  19.     var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
  20.     var i = null;
  21.     if (null === o) {
  22.         var t = r.length;
  23.         t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))
  24.     } else {
  25.         for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)
  26.             "" !== e[C] && f.push.apply(f, a(e[C].split(""))),
  27.             C !== h - 1 && f.push(o[C]);
  28.         var g = f.length;
  29.         g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join(""))
  30.     }
  31.     var u = void 0,
  32.     u = null !== i ? i : (i = gtk || "") || "";
  33.     for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {
  34.         var A = r.charCodeAt(v);
  35.         128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)),
  36.                     S[c++] = A >> 18 | 240,
  37.                     S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,
  38.                 S[c++] = A >> 6 & 63 | 128),
  39.             S[c++] = 63 & A | 128);
  40.     }
  41.     for (var p = m, F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++)
  42.         p += S[b],
  43.         p = n(p, F);
  44.     return p = n(p, D),
  45.         p ^= s,
  46.         0 > p && (p = (2147483647 & p) + 2147483648),
  47.         p %= 1e6,
  48.         p.toString() + "." + (p ^ m);
  49. }

复制代码
至此,所有的Post数据就全部找到了,就可以进行下一步利用VBA发送请求了,待续。。。。。。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-1-19 11:02 | 显示全部楼层
完成了上述步骤后,就是VBA的请求了,按正常的套路就行

一楼附件中有2个模块,一个窗体
一个是主程序用于网络请求
一个是一个Github上的JSON处理包
窗体用于存放js源码和提供语言选择对话框

结果做成了函数形式,返回结果只取了返回值中第一项dst的结果,其他数据可按需求提取。
=baidu(参数1,参数2-可选参数,参数3-可选参数)
参数1:待查询的词或句
参数2:目标语言,可不填,若添入“zdy”则跳出语言选择对话框
参数2:源语言,可不填,若添入“zdy”则跳出语言选择对话框



TA的精华主题

TA的得分主题

发表于 2022-1-20 10:46 来自手机 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
感谢分享!学到了很多。奇怪怎么看不到js源码呢,怎么存放到窗体里面的呢?
测试出错了大佬,在没有填参数2和3的情况下、我调试看了一下、参数2和3的值显示丢失,代码没运行到第三次post就退出了
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-17 15:26 , Processed in 0.050193 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表