PyQt5实战——翻译的实现,成功爬取微软翻译(可长期使用)经验总结(九)

个人博客:苏三有春的博客

系类往期文章:
PyQt5实战------多脚本集合包,前言与环境配置(一)
PyQt5实战------多脚本集合包,UI以及工程布局(二)
PyQt5实战------多脚本集合包,程序入口QMainWindow(三)
PyQt5实战------操作台打印重定向,主界面以及stacklayout使用(四)
PyQt5实战------UTF-8编码器UI页面设计以及按钮连接(五)
PyQt5实战------UTF-8编码器功能的实现(六)
PyQt5实战------翻译器的UI页面设计以及代码实现(七)
PyQt5实战------翻译的实现,第一次爬取微软翻译经验总结(八)

前言

本文笔者吸取了第一次爬取微软翻译的经验,发现在对微软翻译进行请求的时候,URL会随着会话结束而重新生成,这一点是本文需要解决的内容,且除了URL中出现的IGIID两个数据外,在请求的表单数据中,还有keytoken两个数据也在动态变化。本文旨在追踪这几个数据在何时被发送,如何被获取。

分析

首先,重新打开浏览器自带的开发者工具,随便翻译一词,让客户端发送一次翻译请求ttranslatev3,可以发现,这次URL与前一篇文章PyQt5实战------翻译的实现,第一次爬取微软翻译经验总结(八)的又不一致

https://cn.bing.com/ttranslatev3?isVertical=1\&\&IG=DFFF2F46AAE0482491F67EEEB26C249C\&IID=translator.5025

笔者借助开发者工具自带的搜索框进行搜索,看看我们需要的数据在哪里出现过

除了上一篇文章中提到的IGIID两个数据外,我们还需要找到tokenkey两个数据,在ttranslatev3响应请求中,可以看到我们发送请求时,请求表单除了携带需要翻译的文本,翻译前的语种,翻译后的语种外,还需携带两个特殊的信息

至于tryFetchingGenderDebiasedTranslations一直为true,因此直接填写即可

IG

找到IG所在

首先看看IG在哪里出现过,将IG的数据DFFF2F46AAE0482491F67EEEB26C249C复制进搜索框查询,得到以下信息

可以发现,搜索出来的大部分请求中,这一串数据都是出现在URL与path中的,也就是说,这些请求中,IG数据也是被使用的,并不是出自于这些请求,继续向下滑动,找到了一个translator的包

如果你点击进去,就会发现,这其实就是访问该页面的第一个请求响应,它的html数据构建了整个页面

现在我们查看IG数据在这个响应的哪里,点击刚刚搜索的地方,会自动跳转到response出现了相同信息的地方,如下图所示:

因此,现在重新确认一下目标:目标从"找到IG数据的出处"变更为"获取IG数据"。

请求获取IG数据

来观察一下这个请求响应,回顾一下上一篇文章,我们在请求时需要些什么数据:

URLUser-Agent表单数据

那我们依次来找这个请求所需要的数据,首先看标头:

URL

这个URL携带的信息很好猜,https://cn.bing.com/translator是访问的主机,即微软搜索引擎bing的翻译页面,?表示后面携带了多个参数,ref=TThis这通常表示一个参考信息或来源标识符。可能是用来跟踪用户从哪个链接访问了翻译工具,text表示默认的翻译文本,from表示翻译前的语种,to表示目标语种。可以看到,这里后面携带的三个信息,正好是打开网页时的默认信息

"输入文本"是背景,实际上并没有东西在这里。

可以猜测,每次访问这个页面,URL大概率是不会发生变化的,没有携带什么特殊的信息。经过反复的刷新和测试,验证了这个猜想。

User-Agent

为什么User-Agent会是一样的?需不需要担心它会不会变化?来看一下User-Agent的定义:

在进行网页爬虫时,User-Agent 是一个非常重要的 HTTP 请求头字段,它的主要作用是向服务器提供有关请求者(通常是浏览器或爬虫)的一些信息。具体来说,它会告诉服务器,发出请求的客户端是什么类型的设备,操作系统,浏览器等。不同的服务器和网站可能根据 User-Agent 来决定如何响应请求,比如返回不同的内容、样式,或者限制对某些类型客户端的访问。

User-Agent 的作用总结:

  1. 识别客户端User-Agent 向服务器表明请求是由哪个客户端发出的。对于不同的浏览器、操作系统或设备,User-Agent 会有所不同。例如,Chrome、Firefox、Safari、IE 等不同浏览器会有不同的 User-Agent 字符串。
  2. 避免被识别为爬虫 : 网站可能会根据 User-Agent 来识别是否是爬虫程序。很多爬虫程序没有设置真实的 User-Agent,或者 User-Agent 字符串看起来像是一个自动化脚本(比如 Python 的 requests 库默认 User-Agent 是一个简单的字符串)。一些网站会使用这一点来检测并阻止爬虫请求。因此,为了模拟浏览器,爬虫通常会伪装成浏览器的 User-Agent,避免被网站识别为爬虫。
  3. 返回适配的内容 : 根据 User-Agent,服务器可以返回特定格式的内容。比如,移动设备和桌面设备通常会看到不同版本的网页,甚至不同的图片大小和样式。通过查看 User-Agent,服务器可以判断请求来自于手机、平板、桌面或其他设备,并返回不同的页面样式或功能。
  4. 分辨设备和浏览器版本User-Agent 可以帮助服务器确定访问者的设备类型、操作系统及浏览器版本,从而优化响应内容。比如,某些页面可能会针对不同的操作系统(如 Windows、macOS、Linux)或不同版本的浏览器提供特定的网页布局或 JavaScript 功能。

可以看出,一些服务器会根据User-Agent来判断访问请求是不是来自人类或自动化脚本,可做一些反爬虫操作。我们从浏览器获取的请求信息中包含的User-Agent,表明了这段请求时来自浏览器,而非自动化脚本,因此,我们可以回答上面的问题:1.User-Agent一样是因为我们今天与昨天用的都是同一个浏览器访问,它代表了"该请求来自Edge浏览器"。2.无需担心它会发生变化,除非浏览器更新会更改这项数据,而这大概率是不会发生的。

代码实现

首先,先获取整个response的html数据,把它写在一个单独的文件里,(数据量太大,操作台无法查找相应的数据),有些导入的模块会在后面的代码中用到,这仅是完整代码的一部分

python 复制代码
import requests
import re
from bs4 import BeautifulSoup
from urllib import response
import urllib.request
import json
url = "https://cn.bing.com/translator?ref=TThis&text=&from=zh-Hans&to=en"
header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"}
response = requests.get(url,headers=header,data={})
response.raise_for_status()
html = response.text
with open("translator.html", "w", encoding="utf-8") as f:
    f.write(html)

获取到相应的HTML,直接搜索IG

现在,我们找到了这个数据,用正则表达式将数据获取,其中re.search方法是调用第三方库re

python 复制代码
ig = re.search(r'IG:"(\w+)"',html).group(1) # 使用正则表达式在html文件中查找IG数据并获取

IID

我们用同样地办法查找IID的所在地并获取它

找到IID的所在

找到IID数据的所在,依然在translator请求响应中,这就好办了,因为该请求的完整相应已经被我们获取了,只要找到相应的位置即可。

刚刚获取的HTML文件中,你可以找到多个带有data-iid属性的<div>,因此,我们需要更加详细的信息来确认其位置,比如利用前面的id=" tta_outGDCont"

代码实现

可以使用第三方库BeautifulSoup,获取html格式数据中特定的属性,比如data-iid

python 复制代码
soup = BeautifulSoup(html, "html.parser")
dev_element = soup.find("div", id = "tta_outGDCont")
data_iid = dev_element.attrs["data-iid"]
print("data_iid:"+data_iid)

我们来解释一下soup = BeautifulSoup(html, "html.parser")这一段代码

1. BeautifulSoup

BeautifulSoup 是一个 Python 库,主要用于从 HTML 或 XML 文档中提取数据。它提供了许多方法来帮助你遍历、搜索和修改 HTML/XML 文档的内容。

2. html

html 是传入 BeautifulSoup 构造函数的参数,通常是一个包含 HTML 内容的字符串。它代表了待解析的 HTML 文档。可以是从文件读取的内容,或者是通过网络请求获取的 HTML 页面。

3. "html.parser"

"html.parser"BeautifulSoup 的一个解析器(parser)。它告诉 BeautifulSoup 使用 Python 内建的 HTML 解析器来解析传入的 HTML 文档。这个解析器是一个快速且有效的解析工具,但对于一些特殊的 HTML,可能处理得不如其他第三方解析器(如 lxmlhtml5lib)精准。

"html.parser" 选项是 Python 默认的解析器,但如果你安装了 lxmlhtml5lib 等库,也可以指定其他解析器。例如:

  • "lxml":使用 lxml 库的 HTML 解析器。
  • "html5lib":使用 html5lib 库,它更宽容于不规范的 HTML 代码。

4. 最终效果

这行代码的作用是:通过 BeautifulSoup 库,将传入的 HTML 字符串 html 解析成一个 BeautifulSoup 对象,并指定使用内建的 html.parser 解析器。解析后的 soup 对象可以用来方便地操作和提取 HTML 内容。

剩下的代码看方法名称也很好理解它是做什么的

token与key

找到tokenkey的所在

我们用相同的办法,通过搜索框查找token的所在地,发现,这个信息同样存在于translator请求响应中:

如果你仔细一点,你会发现,token前面那串数字,就是我们下一个要找的key!真是得来全不费工夫,剩下的两个数据被我们一次性找到了,接下来就是获取它们。

代码实现
python 复制代码
pattern = r'var params_AbusePreventionHelper = \[(\d+),"([^"]+)",\d+\];'
token = re.findall(pattern, html)
print("key:"+token[0][0])
print("token:"+token[0][1])

同样地,我们使用正则表达式,查找var params_AbusePreventionHelper后面的两个数据,放在token列表中。

小结

至此,我们找到了我们所需的全部数据,接下来只需要将IGIID填进URL中,将tokenkey填进表单中,就可发送完整的请求,伪装成正常的浏览器请求了。

请求与获取相应

代码实现

python 复制代码
url = "https://cn.bing.com/ttranslatev3?isVertical=1&&IG="+ig+"&IID="+data_iid
print(url)
header = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"}
data = {"fromLang":"zh-Hans","to":"en","token":token[0][1],"key":token[0][0],"text":"今天的天气","tryFetchingGenderDebiasedTranslations":"true"}
print(data)
data = urllib.parse.urlencode(data).encode("utf-8")
req = urllib.request.Request(url, data, headers=header)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
target = json.loads(html)
print(target[0]['translations'][0]['text'])

根据上一篇文章的经验,以及本文上述的分析:

  • URL需要根据上文所获取的IG与IID进行动态变换
  • data数据,将我们上面获取的token与key分别放入字典中
  • 对数据进行UTF-8编码转换格式
  • 发送请求
  • 获取响应并进行UTF-8解码
  • 转换JSON格式
  • 获取数据

如果将进行UTF-8解码后的数据完整打印出来,将会是:

json 复制代码
[
    {
        "translations":[
            {
                "text":"Today's weather",
                "to":"en",
                "sentLen":{
                    "srcSentLen":[
                        5
                    ],
                    "transSentLen":[
                        15
                    ]
                }
            }
        ],
        "detectedLanguage":{
            "language":"zh-Hans"
        }
    },
    {
        "inputTransliteration":"jīntiān de tiānqì"
    }
]

我们要的就是translations列表下的第一个字典中text对应的value

完整代码

python 复制代码
from csv import Error
from email.policy import HTTP
from tkinter import E
from urllib.error import URLError
import requests
import re
from bs4 import BeautifulSoup
from urllib import response
import urllib.request
import json


class Translation:
    def __init__(self,content):               
        self.translating(content)

    def translating(content,lfrom,lto): 
        if content == "":
            return "请输入内容"
        
        langfrom = {"自动检测":"auto-detect","中文":"zh-Hans","English":"en"}
        langto = {"中文":"zh-Hans","English":"en"}        
        url = "https://cn.bing.com/translator?ref=TThis&text=&from=zh-Hans&to=en"
        header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"}
        try:
            response = requests.get(url,headers=header,data={},timeout=5)
        except Exception as e:
            print(f"There are something wrong with the network: {e}")
            return "website is not reachable"
        html = response.text
        soup = BeautifulSoup(html, "html.parser")
        dev_element = soup.find("div", id = "tta_outGDCont")
        data_iid = dev_element.attrs["data-iid"]
        print("data_iid:"+data_iid)
        ig = re.search(r'IG:"(\w+)"',html).group(1)
        print("IG:"+ig)
        pattern = r'var params_AbusePreventionHelper = \[(\d+),"([^"]+)",\d+\];'
        token = re.findall(pattern, html)
        print("key:"+token[0][0])
        print("token:"+token[0][1])
        url = "https://cn.bing.com/ttranslatev3?isVertical=1&&IG="+ig+"&IID="+data_iid
        print(url)
        header = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"}
        data = {"fromLang":langfrom[lfrom],"to":langto[lto],"token":token[0][1],"key":token[0][0],"text":content,"tryFetchingGenderDebiasedTranslations":"true"}
        print(data)
        data = urllib.parse.urlencode(data).encode("utf-8")
        try:
            req = urllib.request.Request(url, data, headers=header)
            response = urllib.request.urlopen(req)
            html = response.read().decode("utf-8")
            target = json.loads(html)
        except Exception as e:
            print(f'There are something wrong with the network: {e}')
            return "website is not reachable"
        try:
            print("translations:"+target[0]['translations'][0]['text'])
        except KeyError:
            print(target)
            return "something was wrong"
        return target[0]['translations'][0]['text']

结语

这次,我们完成了对微软翻译的完整爬虫,且可以完美多次长时间地运行,这个脚本功能已经完善,只是还没有嵌入到GUI程序中,下一篇文章,我们将会把这个脚本整理一下,放到脚本工具包中供翻译器调用,且会加装一些网络状况的判断。

如果你看到这里,说明你又变强了!希望你变得更强,感谢你的观看,共同进步!

相关推荐
一行玩python18 分钟前
SQLAlchemy,ORM的Python标杆!
开发语言·数据库·python·oracle
数据小爬虫@1 小时前
利用Python爬虫获取淘宝店铺详情
开发语言·爬虫·python
编程修仙2 小时前
Collections工具类
linux·windows·python
芝麻团坚果2 小时前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
EterNity_TiMe_3 小时前
【论文复现】神经网络的公式推导与代码实现
人工智能·python·深度学习·神经网络·数据分析·特征分析
Stara05113 小时前
Git推送+拉去+uwsgi+Nginx服务器部署项目
git·python·mysql·nginx·gitee·github·uwsgi
hence..3 小时前
Vscode写markdown快速插入python代码
ide·vscode·python
DanielYQ4 小时前
LCR 001 两数相除
开发语言·python·算法
vener_5 小时前
LuckySheet协同编辑后端示例(Django+Channel,Websocket通信)
javascript·后端·python·websocket·django·luckysheet
封步宇AIGC5 小时前
量化交易系统开发-实时行情自动化交易-4.2.3.指数移动平均线实现
人工智能·python·机器学习·数据挖掘