【Python】【进阶篇】十七、Python爬虫实现实时翻译

目录

  • 十七、Python爬虫实现实时翻译
    • 17.1 JS代码slat与sign
    • 17.2 Python代码表示参数
    • 17.3 完整程序实现

十七、Python爬虫实现实时翻译

YD翻译是以异步方式实现数据加载的,要实现数据抓取,其过程极其繁琐。

上一节《Python爬虫的浏览器实现抓包》,通过浏览器上控制台抓包,我们得知了 POST 请求的参数以及相应的参数值,并发现以下了一定规律:salt、sign、lts 总是变化的,而 bv 等其他参数是不变化的。

如果想要实现实时地抓取,就需要将 salt 和 sign 转换为 用 Python 代码表示的固定形式。最后将所有参数放入到
requests.post() 中,如下所示:

    response = requests.post(url,data=data,headers=headers)

其中 data 是字典格式参数,它用来构建 POST 请求方法的参数和参数值。

17.1 JS代码slat与sign

salt、sign 加密有两种实现方式:一种是通过前端 JS实现,另一种是后台服务器生成加密串,并在返回响应信息时,将加密信息交给接浏览器客户端。但是,通过预览响应信息可知,并没有涉及 salt、sign的信息,因此可以排除这种方法。
在这里插入图片描述

预览响应信息

那么要如何找到关于salt、sign 的 JS 代码呢?此时就要用到另外一个调试工具选项卡—— JS。如下图所示:

在这里插入图片描述

js文件

点击上图所示的搜索按钮来检索 JS 代码,输入 “salt”,结果如图所示:

在这里插入图片描述

找到相关js文件

或者您也可以使用 Sources 选项卡将 fanyi.min.js 文件中的 JS 代码格式化输出,并使用 Ctrl+F 找到相应的 "salt"位置,如下图所示:

在这里插入图片描述

Sources选项卡应用

提示:将所有 JS 代码 copy
下来,通过站长工具也可以实现格式化输出。

通过上述方法就找到了 salt 与 sign(两个参数项是在一起的)JS 代码,如下所示:

var r = function(e) {
    var t = n.md5(navigator.appVersion),
    r = "" + (new Date).getTime(),
    i = r + parseInt(10 * Math.random(), 10);
    return {
        ts: r,
        bv: t,
        salt: i,
        sign: n.md5("fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@")
    }
};

注意,找到上述代码是解决本节问题的关键,大家一定要要掌握方法。

17.2 Python代码表示参数

通过上述 JS 代码的简单分析可知: r 变量等同于 lts,salt 变量等同于 i,而 sign 是一个经过 md5 加密的字符串。接下来使用
Python 代码来表示上述参数,如下所示:


#lts毫秒时间戳
str(int(time.time()*1000))

#salt, lts+从0-9的随机数
lts+str(random.randint(0,9))

#sign加密字符串
from hashlib import md5
#word为要翻译的单词等同于js代码中的"e"
string = "fanyideskweb" + word + salt + "Tbh5E8=q6U3EXe+&L[4c@"
s = md5()
#md5的加密串必须为字节码
s.update(string.encode())
#16进制加密
sign = s.hexdigest()

17.3 完整程序实现

完整代码如下所示:

#coding:utf8
import random
import time
from hashlib import md5
import requests


class YoudaoSpider(object):
    def __init__(self):
        # url一定要写抓包时抓到的POST请求的提交地址,但是还需要去掉 url中的“_o”,
        # “_o”这是一种url反爬策略,做了页面跳转,若直接访问会返回{"errorCode":50}
        self.url='http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
        self.headers={
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
        }
    # 获取lts时间戳,salt加密盐,sign加密签名
    def get_lts_salt_sign(self,word):
        lts=str(int(time.time()*1000))
        salt=lts+str(random.randint(0,9))
        string = "fanyideskweb" + word + salt + "Tbh5E8=q6U3EXe+&L[4c@"
        s=md5()
        s.update(string.encode())
        sign=s.hexdigest()
        print(lts,salt,sign)
        return lts,salt,sign

    def attack_yd(self,word):
        lts,salt,sign=self.get_lts_salt_sign(word)

        #构建form表单数据
        data={
            "i": word,
            "from": "AUTO",
            "to": "AUTO",
            "smartresult": "dict",
            "client": "fanyideskweb",
            "salt": salt,
            "sign": sign,
            "lts": lts,
            "bv": "cda1e53e0c0eb8dd4002cefc117fa588",
            "doctype": "json",
            "version": "2.1",
            "keyfrom": "fanyi.web",
            "action": "FY_BY_REALTlME"
        }
        #使用 reqeusts.post()方法提交请求
        res = requests.post(
            url=self.url,
            data=data,
            headers=self.headers,

        )
        # res.json() 将json格式的字符串转为python数据类型
        # 客户端与服务器数据交互以json字符串传递,因此需要将它转换为python数据类型
        html=res.json()
        print(html)
        # 查看响应结果response  html:{"translateResult":[[{"tgt":"hello","src":"你好"}]],"errorCode":0,"type":"zh-CHS2en"}
        result=html["translateResult"][0][0]["tgt"]
        print('翻译结果:', result)

    def run(self):
        try:
            word=input('请输入要翻译的单词:')
            self.attack_yd(word)
        except Exception as e:
            print(e)

if __name__ == '__main__':
    spider=YoudaoSpider()
    spider.run()

输出结果:

请输入要翻译的单词:大家好,这里是C语言中文网Python爬虫教程

lts,salt,sign 输出结果:
1616472092090 16164720920902 fcc592626aee42e1067c5195cf4c4576

html 响应内容:
{'type': 'ZH_CN2EN', 'errorCode': 0, 'elapsedTime': 25, 'translateResult': [[{'src': '大家好,这里是C语言中文网Python爬虫教程', 'tgt': 'Everybody is good, here is the Chinese Python crawler C language tutorial'}]]}

翻译结果: Everybody is good, here is the Chinese Python crawler C language tutorial

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10103.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【hello Linux】Linux开发工具

目录 1. vim:文本编辑器 1.1 各种模式的切换 补充:ctrl r命令 1.2 命令模式的操作 1.3 插入模式的操作 1.4 底行模式的操作 1.5 配置vim环境 1.6 配置亲属关系 2. gcc/g:编译器 2.1 预处理: 2.2 编译: 2.3 汇编&#x…

如何利用ChatGPT辅助优化刷题性能

根据土著刷题共建群里的一个小伙伴反馈,刷题会出现切题卡顿的情况,有时会出现滑不动的情况。 定位问题 为了定位切题卡顿问题的具体原因,测试了高低端手机📱、切换2G、3G、4G低网络状态等各种影响切题的现实情况,经过借…

STM32F4_定时器精讲(TIM)

目录 1. 什么是定时器? 2. STM32定时器简介 2.1 高级控制定时器 TIM1和TIM8 2.1.1 TIM1和TIM8简介 2.1.2 时基单元 2.1.3 计数器模式 2.1.4 重复计数器 2.1.5 时钟选择 2.1.6 捕获/比较通道 2.1.7 输入捕获模式 2.1.8 其他功能 2.2 通用定时器 TIM2到TI…

Mysql 你还在一个字段一个索引吗

今天看到某系统的mysql在某时段存在thread_running线程数飙高触发告警,挤时间分析了该异常时间段的慢日志记录,并进行了sql优化 慢日志记录主要归为3个慢sql (编号1,2,3) 一、 1号sql原文 select * from feeds where topics_id &…

【MySQL数据库原理】MySQL Community安装与配置

目录 安装成功之后查看版本验证1、介绍、安装与配置数据库2、操作MySQL数据库3、MySQL数据库原理安装成功之后查看版本验证 SELECT VERSION();查看mysql版本号 1、介绍、安装与配置数据库 下载安装包:https://download.csdn.net/download/weixin_41194129/87672588 MySQL…

Visual studio C#中通过nuget安装sqlite库及C#中sliqte的用法

以前在Visual studio 的2017版中讲过如何使用sqlite,这里我们再次说说如何使用sqlite,以前Nuget使用还不是很流行很普及,大多数人不知道,但随着VS的升级,Nuget成为安装插件或者引用库文件标准的获取手段,所…

Qt Quick - TabBar

Qt Quick - TabBar使用总结一、概述二、调整选项卡三、Flickable标签三、定制化一、概述 TabBar其实就是选项卡,TabBar是由TabButton控件填充,TabBar可以与任何提供currentIndex属性的布局或容器控件一起使用,如StackLayout或SwipeView。Tab…

Vector - CAPL - CAN x 总线信息获取

在CAN&CANFD测试中,我们经常需要获取到CAN总线的负载、错误帧、过载帧、发送错误等等CAN总线上面的信息,这些信息如此重要,但是如果真的要写代码去实现也是相当不易的,那我们该如何去获取到的呢?下面我们就来一起看…

Object方法

私人博客 许小墨のBlog —— 菜鸡博客直通车 系列文章完整版,配图更多,CSDN博文图片需要手动上传,因此文章配图较少,看不懂的可以去菜鸡博客参考一下配图! 系列文章目录 前端系列文章——传送门 JavaScript系列文章—…

柔性数组【结构体和动态内存的结合】

全文目录前言柔性数组的定义语法柔性数组的特点柔性数组的使用柔性数组的优势前言 很多人可能没有听过柔性数组这个概念,但是在C99中柔性数组是确实存在的。我个人感觉有点像动态内存和结构体的结合。 柔性数组的定义语法 结构中的最后一个元素允许是未知大小的数…

NumPy 秘籍中文第二版:三、掌握常用函数

原文:NumPy Cookbook - Second Edition 协议:CC BY-NC-SA 4.0 译者:飞龙 在本章中,我们将介绍许多常用函数: sqrt(),log(),arange(),astype()和sum()ceil(),modf()&…

《Java8实战》第1章 Java 8、9、10 以及 11 的变化

如想了解 Oracle 公司对 JDK 的最新支持情况,请访问https://www.oracle.com/technetwork/java/java-se-supportroadmap.html。所有的示例代码均可见于图灵社区本书主页 http://ituring.com.cn/book/2659“随书下载”处。 1.1 为什么要关心 Java 的变化 Java8做的…

[MAUI 项目实战] 手势控制音乐播放器(三): 动画

文章目录吸附动画确定位置平移动画回弹动画使用自定义缓动函数多重动画点击动画项目地址上一章节我们创建了手势容器控件PanContainer,它对拖拽物进行包装并响应了平移手势和点击手势。拖拽物现在虽然可以响应手势操作,但视觉效果较生硬,一个…

总结一下Redis的缓存雪崩、缓存击穿、缓存穿透

缓存是提高系统性能的一种常见手段,其中Redis是一种常用的高性能缓存数据库。但是在使用缓存时,可能会遇到一些问题,比如缓存击穿、缓存穿透、缓存雪崩等问题,本文将介绍这些问题的概念、原因以及解决方案。 缓存击穿 缓存击穿指…

SQL Server 连接查询和子查询

提示: 利用单表简单查询和多表高级查询技能,并且根据查询要求灵活使用内连接查询、外连接查询或子查询等。同时还利用内连接查询的两种格式、三种外连接查询语法格式和子查询的语法格式。 文章目录前言1.查询所有学生的学号、姓名、选修课程号和成绩方法…

Vue学习——【第四弹】

前言 上一篇文章 Vue学习——【第三弹】 中我们了解了MVVM模型,这篇文章接着学习Vue中的数据代理。 简单介绍 数据代理就是**一个对象(A)来代理对另一个对象(B)的属性操作(A一定要包含B)。**直接看定义大家可能觉得有些抽象,我们可以用代码来实现。 …

全景丨0基础学习VR全景制作,后期篇:嵌入视频前期注意事项及后期处理

大家好,欢迎观看蛙色官方系列全景摄影课程! 一、前期拍摄要点 嵌入视频的简介和用途 livepano即完全无缝融合到全景图中的热点嵌入视频。 这种无缝融合是真正无缝,从而让观者产生沉浸感和真实感。例如在场景中放入宠物、让喷泉动起来、灯光…

MPAM中PARTID的虚拟化(Virtualization)

MPAM支持对PARTID的virtualization,需要在满足所有以下条件下才能使用: 在当前的security状态下有实现EL2;支持MPAM virtualization,也就是MPAMIDR_EL1.HAS_HCR等于1; 以下是MPAM中使用virtual-to-physical PARTID ma…

Scala之面向对象

目录 Scala包: 基础语法: Scala包的三大作用: 包名的命名规范: 写包的好处: 包对象: 导包说明: 类和对象: 定义类: 封装: 构造器: 主从…

Spark 之 解析json的复杂和嵌套数据结构

本文主要使用以下几种方法: 1,get_json_object():从一个json 字符串中根据指定的json 路径抽取一个json 对象 2,from_json():从一个json 字符串中按照指定的schema格式抽取出来作为DataFrame的列 3,to_j…