场景
需要使用Form表单提交数据的请求。
import requests
headers = {"UserAgent":"xxx"}
data = {"user":"lauf","pw":"123"}
res = requests.post(url,headers=headers,data=data)
抓包工具
https://fanyi.youdao.com/
页面分析:
静态页面还是动态页面
静态页面,响应html文件,数据固定在页面中
动态页面,响应json数据,数据在页面中会变换
- 输入要翻译的中文,会返回英文
preview,预览
静态页面会渲染显示
json 数据会格式化输出
- F12 开发者模式/右键-检查
Network,抓网络数据包
All,所有的数据包
XHR,异步加载 的数据包
JS,CSS,… 相应的文件
Sources,格式化输出js代码,并打断点测试js 代码(点击执行的行号),分析js加密的参数
Console,控制台,交互式测试js,输入代码,查看结果
3.批量转为字典数据
批量的key-value 数据,转为字典形式
"""
i: 爱学习
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 16194411822602
sign: 4f332dd52402aa147cc451a6d0b37874
lts: 1619441182260
bv: 62c1eba97402d4ff4eb261254e974c27
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_REALTlME
"""
复制到pycharm中—>Ctrl+r—>regexp
如下:
请求头也可以完全模拟浏览器
POST提交的数据
看数据哪些是变化的,哪些是不变的
变化的数据:
javascript加密的
点击JS的网络数据包,查看js文件—>很多js文件,看哪个?
输入关键字搜索,如下:
断点测试:
输入单词,触发xhr,执行到断点处。恢复断点再次点击行号----resume script execute
解析出加密使用的算法,使用python 生成一遍,再放入程序中使用
解析结果
案例
需求分析
要求输入一个中文/英文
得到翻译的结果
"""
1.分析页面,动态还是静态
2.动态页面,抓XHR数据包 F12-->Network-->XHR
从中获取请求的url、请求头、表单数据
3.检查表单数据中的变与不变
4.解析表单数据中的变化的部分,通常是js加密-->JS-->搜索关键字
5.解析出加密算法,使用python生成加密数据,放入表单数据中
6.发送POST 请求,解析响应
"""
import requests
import time
import hashlib
import random
class FYSpider(object):
def __init__(self):
# 异步请求的url
self.url = "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
self.headers = {
"Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Content-Length": "252",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Cookie": "OUTFOX_SEARCH_USER_ID=-1357302210@171.9.140.217; OUTFOX_SEARCH_USER_ID_NCOO=1038748019.8050627; _ntes_nnid=5cc1dd34016abb2f5e1ccb332bf6366c,1616832815260; JSESSIONID=aaaD96LdPa6wu7JB14oKx; ___rl__test__cookies=1619452488346",
"Host": "fanyi.youdao.com",
"Origin": "https://fanyi.youdao.com",
"Referer": "https://fanyi.youdao.com/",
"sec-ch-ua": "Not A;Brand;v=99, Chromium;v=90, Google Chrome;v=90",\
"sec-ch-ua-mobile":"?0","Sec-Fetch-Dest": "empty",
"""Sec-Fetch-Mode""": """cors""",
"""Sec-Fetch-Site""": """same-origin""",
"""User-Agent""": """Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36""","""X-Requested-With""": """XMLHttpRequest"""} # 完全模拟浏览器/检查频率高的key
self.data = {
"i": None,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": None,
"sign": None,
"lts": None,
"bv": "62c1eba97402d4ff4eb261254e974c27",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
} # 先设置不变的部分
# 产生加密的数据
def get_ts_salt_sign(self, word):
# lts 毫秒级时间戳
lts = str(int(time.time() * 1000))
# salt 毫秒级时间戳+一个0-9的随机数
salt = lts + str(random.randint(0, 9))
# sign "fanyideskweb"+"你好"+salt+"Tbh5E8=16U3EXe+&L[4c@"-->md5加密
sign_ = "fanyideskweb" + word + salt + "Tbh5E8=q6U3EXe+&L[4c@"
# n.md5("fanyideskweb" + e + i + "Tbh5E8=q6U3EXe+&L[4c@"
m = hashlib.md5()
m.update(sign_.encode())
sign = m.hexdigest()
return lts, salt, sign
def request_yd(self, word):
lts, salt, sign = self.get_ts_salt_sign(word)
self.data["lts"] = lts
self.data["salt"] = salt
self.data["sign"] = sign
self.data["i"] = word
# 发请求
print(self.url)
print(self.headers)
print(self.data)
self.res = requests.post(self.url, headers=self.headers, data=self.data)
if self.res.status_code == 200:
print("响应OK")
print("响应内容",self.res.text)
else:
print("响应失败", self.res.status_code)
def run(self, word):
self.request_yd(word)
print(self.res.text) # 字符串
print(self.res.json()) # json数据
if __name__ == "__main__":
spider = FYSpider()
spider.run("你好")