0
点赞
收藏
分享

微信扫一扫

Hive 实现查询用户连续三天登录记录

前言

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

分析

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

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

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

代码实现

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

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

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

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")这一段代码

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

token与key

找到tokenkey的所在

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

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

代码实现
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填进表单中,就可发送完整的请求,伪装成正常的浏览器请求了。

请求与获取相应

代码实现

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解码后的数据完整打印出来,将会是:

[
    {
        "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

完整代码

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程序中,下一篇文章,我们将会把这个脚本整理一下,放到脚本工具包中供翻译器调用,且会加装一些网络状况的判断。

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

举报

相关推荐

0 条评论