(转载)目前看到的最好但是无法突破长句子翻译的代码。待爬虫大神研究

 python爬取百度翻译结果,需要发送俩次请求。

一次是请求获取输入的语言类型,然后是拿着获取到的语言类型发送下一次请求,获取翻译的结果。

先输入英文“hello”,获取结果

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

可以发现,输入后返回的翻译结果在这个文件中,接着输入中文“爬虫”进行翻译

发现页面没有重新加载,所以这是由动态页面加载,网址只有from和to后面发生变化,可以猜测后面的元素就是原先语言的类型和想要翻译的类型,而且这是个post请求方式,所以查看一下post的数据部分

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_14,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_13,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_18,color_FFFFFF,t_70,g_se,x_16

 post的data部分俩个参数from和to,query就是自己输入的词语,查看上一个请求的内容:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_19,color_FFFFFF,t_70,g_se,x_16

 也是返回json数据,其中就有一个参数lan,对应值为zh,可以猜测这个请求是返回此次输入词语的语言类型的。

首先请求获取语言类型:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

post的data部分就是输入的词语:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_19,color_FFFFFF,t_70,g_se,x_16

 当我们输入中文时会返回zh,所以对应的from值就为zh,to值就为en


   
   
  1. def get_lang( self, lang_data): # 获取语言类型
  2. return lang_data[ "lan"], "en" if lang_data[ "lan"] == "zh" else "zh"

比较难的部分是翻译部分,请求获取到翻译后的结果:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

试了几次后发现,这次请求的post数据部分的sign值和token值是必须要加的,且每次输入要翻译的词语后,sign值都会不一样,这时候找一下sign值是哪来的。浏览器控制台打开搜索:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

很多都只是包含sign的词语而已,而不是sign,换成输入sign:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 第3个有from,to,query,和sign值,和获取翻译结果的请求结果key值一样,所以试着在这里打上断点调试,重新刷新页面,而不是点击翻译:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 执行到此处停下,然后进入这里的L函数里,一步一步执行:
watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 这里就跳转到了e函数,而这里传入的参数r就是我们输入的词语,猜测这里的e函数有可能就是把我们输入的词语进行了加密后再输出,把这里e函数整个复制出来,然后在node.js中运行

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

这里报错说i未定义,回到浏览器找到源码:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 这里的i值赋值给u,然后u的值为"320305.1313212101",不清楚i值是哪里来的,先看他是不是个变值,换了给词语搜索后重复步骤发先u值不变,所以就直接在js代码中直接定义一个i值给u,然后接着运行:

var i = "320305.131321201"
   
   

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 又说n未定义,回到浏览器继续执行下一步,找到了n函数,然后也复制进js代码,接着执行:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

这时候返回了一个值,比较一下,和输入“爬虫”是返回的sign值一样,这时候爬虫代码基本可以实现出来了。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_16,color_FFFFFF,t_70,g_se,x_16

当输入一个词语时,翻译的结果在["dict_result"]["simple_means"]["word_means"]中,返回一个列表,列表中是这个词语的多个翻译结果:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

但是当输入的是一句中文长句子时,程序会报KeyError错误,表明无法找到对应的key值,于是重新查看浏览器,发现原先的json数据中没有["dict_result"]["simple_means"]["word_means"]键值,猜测是百度翻译也对输入的内容进行了分类,如果输入的是句子,则定位到["trans_result"]["data"][0]["dst"]:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 这里我用异常处理这里无法翻译中文句子的问题:


   
   
  1. try:
  2. print( "翻译:" + str(html_dict[ "dict_result"][ "simple_means"][ "word_means"])) # 翻译单词:可以得到多个单词意思
  3. except KeyError:
  4. print( "翻译:" + str(html_dict[ "trans_result"][ "data"][ 0][ "dst"])) # 翻译句子

全部代码如下(代码中给了自己的注释):

BaiDuSpider.py:


   
   
  1. import requests
  2. import json
  3. import execjs
  4. """爬百度翻译实现中英互译单词和句子(解决了输入中文句子无法翻译的bug),全部代码封装进类里"""
  5. class BaiDuFanYi:
  6. def __init__( self):
  7. self.lang_url = "https://fanyi.baidu.com/langdetect"
  8. self.trans_url = "https://fanyi.baidu.com/v2transapi?from={}&to={}"
  9. self.headers = { "Accept": "*/*",
  10. "Accept-Encoding": "gzip, deflate, br",
  11. "Accept-Language": "zh-CN,zh;q=0.9",
  12. "Connection": "keep-alive",
  13. "Content-Length": "137",
  14. "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
  15. "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36",
  16. "Cookie": "BIDUPSID=6753787919BFC4FF60BAD5DC3900D4FA; PSTM=1646125121; BAIDUID=6753787919BFC4FF6E12938C140804C3:FG=1; FANYI_WORD_SWITCH=1; REALTIME_TRANS_SWITCH=1; HISTORY_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; APPGUIDE_10_0_2=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDUSS=JaMmUzTnhFVnFqS2JoUGJZQURVWkJuN3ZEM0lYU1cwWTZ5TC1UbUhLYmhta3BpSVFBQUFBJCQAAAAAAAAAAAEAAABBEVakZ3JlYXTC3dD91OUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOENI2LhDSNid1; BDUSS_BFESS=JaMmUzTnhFVnFqS2JoUGJZQURVWkJuN3ZEM0lYU1cwWTZ5TC1UbUhLYmhta3BpSVFBQUFBJCQAAAAAAAAAAAEAAABBEVakZ3JlYXTC3dD91OUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOENI2LhDSNid1; BDSFRCVID_BFESS=-pAOJexroG0RYrTD5hL5hMjtieKKUdrTDYLEOwXPsp3LGJLVgW2wEG0PtoWBG_u-K4eiogKK3gOTHxtF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tbke_It2tC03H48k-4QEbbQH-UnLqh8jJgOZ04n-ah02Vxo-5x8hjt0TM-cB-Pch-jnD-Jom3UTdsq76Wh35K5tTQP6rLt-J55Q4KKJxbpbAEJra5MckWMPOhUJiB5JMBan7XPbIXKohJh7FM4tW3J0ZyxomtfQxtNRJ0DnjtpChbC0RD5-hjTJM-l-X5to05TIX3b7EfKocKq7_bJ7KhUbQ0RrH2f0t2goMBp6_bnTqOpvabb5xQhFT5-nfXpOe-n7rKhc1QJ3Rh43HQT3m5-4iL4Jd-CriJIT0Wb3cWKOJ8UbS2bOPBTD02-nBat-OQ6npaJ5nJq5nhMJmb67JDMr0eGteJTttJbAs3t88KJjEe-Kk-PnVeIuQLtnZKRvHa2kjbfT-Qp-hjh4GMMc85-F8yPRPKnjn3N5rKl75yUJ5qKOsQU6d34-iDlJ405OTbIOU5q37b66vMb5YhPJvyTtsXnO7hn3lXbrtXp7_2J0WStbKy4oTjxL1Db3JKjvMtgDtVJO-KKCMMC0GDf5; BAIDUID_BFESS=9A8D3FB44C050878949771408EEDD45F:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1646570203,1646646587,1646646601,1646646834; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1646646834; ab_sr=1.0.1_NGNlMzYwMGM2Y2IyMmFhNzA2N2E1YTUwYmJjN2NkMDMyYTM5NjgyOTM3NmUwYzZjOWUwZGVjZDE0MzY2MGM0ODU4NGMwYzY1NGZhZmEyYzUzYjIzNWRjMDBlNzdhZTkyMDEyMzQ3OTdiZjQ2ZGMyM2U0ZGY4NDBmZDdjYjM5YzZkZTFkZjUzMGM1ZDE2YzZiNTIxYWQ2MTJjNWEwZWEwNWZiZjZhMmZiZTYwYTRhZWEzZWM0YzNmMmFmMGQxZmI5",
  17. "Host": "fanyi.baidu.com",
  18. "Origin": "https://fanyi.baidu.com",
  19. "Referer": "https://fanyi.baidu.com/?aldtype=16047",
  20. "sec-ch-ua": '"Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
  21. "sec-ch-ua-mobile": "?0",
  22. "sec-ch-ua-platform": '"Windows"',
  23. "Sec-Fetch-Dest": "empty",
  24. "Sec-Fetch-Mode": "cors",
  25. "Sec-Fetch-Site": "same-origin",
  26. "X-Requested-With": "XMLHttpRequest"}
  27. def parse_url( self, url, post_data):
  28. # print(url)
  29. response = requests.post(url, headers=self.headers, data=post_data)
  30. html_str = response.content.decode()
  31. return json.loads(html_str)
  32. def get_lang( self, lang_data): # 获取语言类型
  33. return lang_data[ "lan"], "en" if lang_data[ "lan"] == "zh" else "zh"
  34. def encryption_js( self, word): # 加密数据
  35. with open( "baidufanyisign.js", "r", encoding= 'utf-8') as f: # 读取js代码
  36. js_code = f.read()
  37. js_compile = execjs. compile(js_code) # 编译js代码
  38. return js_compile.call( "e", word) # 调用js代码中e函数,传入参数word,返回sign值
  39. def save( self, html_dict):
  40. try:
  41. print( "翻译:" + str(html_dict[ "dict_result"][ "simple_means"][ "word_means"])) # 翻译单词:可以得到多个单词意思
  42. except KeyError:
  43. print( "翻译:" + str(html_dict[ "trans_result"][ "data"][ 0][ "dst"])) # 翻译句子
  44. def run( self):
  45. while True:
  46. word = input( "请输入一个单词或句子:")
  47. if word == "!": # 输入!退出程序
  48. break
  49. # 构造post请求头的数据
  50. lang_post_data = { "query": word}
  51. # 构造url
  52. lang_data = self.parse_url(self.lang_url, lang_post_data)
  53. # 发送请求,获取语言类型
  54. lang_from, lang_to = self.get_lang(lang_data)
  55. # print("from:" + lang_from + "to:" + lang_to)
  56. # 加密数据,获取sign值
  57. sign = self.encryption_js(word)
  58. # 构造翻译结果post请求头的数据
  59. trans_post_data = { "from": lang_from,
  60. "to": lang_to,
  61. "query": word,
  62. "transtype": "translang",
  63. "simple_means_flag": "3", # 必须的参数。
  64. "sign": str(sign), # 必须的参数。关键值:通过sign.js加密
  65. "token": "63671731f58420a45480f5badfff7b2c",
  66. "domain": "common"}
  67. # 构造翻译url
  68. self.trans_url. format(lang_from, lang_to)
  69. # 发送请求,获取翻译结果
  70. html_dict = self.parse_url(self.trans_url, trans_post_data)
  71. # 提取数据,输出
  72. self.save(html_dict)
  73. if __name__ == '__main__':
  74. fanyi_spider = BaiDuFanYi()
  75. fanyi_spider.run()

baidufanyisign.js:


   
   
  1. var i = "320305.131321201"
  2. function n( r, o) {
  3. for ( var t = 0; t < o. length - 2; t += 3) {
  4. var a = o. charAt(t + 2);
  5. a = a >= "a" ? a. charCodeAt( 0) - 87 : Number(a),
  6. a = "+" === o. charAt(t + 1) ? r >>> a : r << a,
  7. r = "+" === o. charAt(t) ? r + a & 4294967295 : r ^ a
  8. }
  9. return r
  10. }
  11. function e( r) {
  12. var o = r. match( /[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
  13. if ( null === o) {
  14. var t = r. length;
  15. t > 30 && (r = "" + r. substr( 0, 10) + r. substr( Math. floor(t / 2) - 5, 10) + r. substr(- 10, 10))
  16. } else {
  17. for ( var e = r. split( /[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e. length, f = []; h > C; C++)
  18. "" !== e[C] && f. push. apply(f, a(e[C]. split( ""))),
  19. C !== h - 1 && f. push(o[C]);
  20. var g = f. length;
  21. 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( ""))
  22. }
  23. var u = void 0
  24. , l = "" + String. fromCharCode( 103) + String. fromCharCode( 116) + String. fromCharCode( 107);
  25. u = null !== i ? i : (i = window[l] || "") || "";
  26. for ( var d = u. split( "."), m = Number(d[ 0]) || 0, s = Number(d[ 1]) || 0, S = [], c = 0, v = 0; v < r. length; v++) {
  27. var A = r. charCodeAt(v);
  28. 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)),
  29. S[c++] = A >> 18 | 240,
  30. S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,
  31. S[c++] = A >> 6 & 63 | 128),
  32. S[c++] = 63 & A | 128)
  33. }
  34. 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++)
  35. p += S[b],
  36. p = n(p, F);
  37. return p = n(p, D),
  38. p ^= s,
  39. 0 > p && (p = ( 2147483647 & p) + 2147483648),
  40. p %= 1e6,
  41. p. toString() + "." + (p ^ m)
  42. }
  43. console. log( e( "爬虫"))

运行:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ2NzM5NTQ5,size_20,color_FFFFFF,t_70,g_se,x_16

 可以实现中英互译,并且可以支持翻译中英文句子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值