爬虫——控制台抓包和requests.post()发送请求
控制台抓包
打开方式及常用选项
1、打开浏览器,F12打开控制台,找到Network选项卡
2、控制台常用选项
1、Network: 抓取网络数据包
1、ALL: 抓取所有的网络数据包
2、XHR:抓取异步加载的网络数据包
3、JS : 抓取所有的JS文件
2、Sources: 格式化输出并打断点调试JavaScript代码,助于分析爬虫中一些参数
3、Console: 交互模式,可对JavaScript中的代码进行测试
3、抓取具体网络数据包后
1、单击左侧网络数据包地址,进入数据包详情,查看右侧
2、右侧:
1、Headers: 整个请求信息 General、Response Headers、Request Headers、Query String、Form Data
2、Preview: 对响应内容进行预览
3、Response:响应内容
requests.post()
适用于Post类型请求的网站,比例:网易翻译
参数-data
response = requests.post(url,data=data,headers=headers)
# data :post的数据(Form表单数据,字典格式)
请求方式的特点
GET请求 : 参数在URL地址中有显示
POST请求: Form表单提交数据
有道翻译破解案例(post)
1、目标
破解有道翻译接口,抓取翻译结果
# 结果展示
请输入要翻译的词语: elephant
翻译结果: 大象
**************************
请输入要翻译的词语: 喵喵叫
翻译结果: mews
2、实现步骤
- 浏览器F12开启网络抓包,Network-All,页面翻译单词后找Form表单数据
- 在页面中多翻译几个单词,观察Form表单数据变化(有数据是加密字符串)
- 刷新有道翻译页面,抓取并分析JS代码(本地JS加密)
- 找到JS加密算法,用Python按同样方式加密生成加密数据
- 将Form表单数据处理为字典,通过requests.post()的data参数发送
具体实现
1、开启F12抓包,找到Form表单数据如下:
i: 喵喵叫
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 15614112641250
sign: 94008208919faa19bd531acde36aac5d
ts: 1561411264125
bv: f4d62a2579ebb44874d7ef93ba47e822
doctype: json
version: 2.1
keyfrom: fanyi.web
action: FY_BY_REALTlME
2、在页面中多翻译几个单词,观察Form表单数据变化,我们发现每次查询单词,只有salt、sign和ts的值会变化。其他的值都不会改变。
salt: 15614112641250
sign: 94008208919faa19bd531acde36aac5d
ts: 1561411264125
3、salt、sign和ts的值一般为本地js文件加密,刷新页面,找到js文件并分析JS代码
方法1:Network - JS选项 - 打开一个js文件,左下角格式化符号{},ctrl+F搜索关键词salt,如果存在关键词则找到了加密的js文件。
方法2:控制台右上角 - Search - 搜索salt - 跳转到Sources,查看文件 - 把js文件代码复制到在线js格式化网站,格式化代码,变成有缩进的可读代码。
4、打开JS文件,分析js加密算法,用Python实现
# ts : 经过分析为13位的时间戳,字符串类型
js代码实现: r = "" + (new Date).getTime()
python实现: str(int(time.time()*1000))
# salt
js代码实现: r + parseInt(10 * Math.random(), 10);
python实现: ts + str(random.randint(0,9))
# sign(设置断点调试,来查看 e 的值,发现 e 为要翻译的单词)
js代码实现: n.md5("fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj")
python实现:
from hashlib import md5
s = md5()
s.update("fanyideskweb" + e + salt + "n%A-rKaT5fb[Gy?;N5@Tj".encode())
sign = s.hexdigest()
python中正则处理header和formdata
1、pycharm进入方法 :Ctrl + r ,选中 Regex
2、处理headers和formdata
(.*): (.*)
"$1": "$2",
3、点击 Replace All
5、代码实现
import requests
import time
import random
from hashlib import md5 class YdSpider(object):
def __init__(self):
# url一定为F12抓到的 headers -> General -> Request URL
self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
self.headers = {
# 检查项最高 - 3个
"Cookie": "OUTFOX_SEARCH_USER_ID=970246104@10.169.0.83; OUTFOX_SEARCH_USER_ID_NCOO=570559528.1224236; _nt\
es_nnid=96bc13a2f5ce64962adfd6a278467214,1551873108952; JSESSIONID=aaae9i7plXPlKaJH_gkYw; td_cookie=1844\
6744072941336803; SESSION_FROM_COOKIE=unknown; ___rl__test__cookies=1565689460872",
"Referer": "http://fanyi.youdao.com/",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.\
0.3809.100 Safari/537.36", } # 获取,ts、salt、sign
def get_salt_sign_ts(self, word):
ts = str(int(time.time() * 1000)) # ts
salt = ts + str(random.randint(0, 9)) # salt
string = "fanyideskweb" + word + salt + "n%A-rKaT5fb[Gy?;N5@Tj" # sign
s = md5()
s.update(string.encode('utf-8'))
sign = s.hexdigest() return salt, sign, ts def attack_yd(self, word):
# 1. 先拿到salt,sign,ts
salt, sign, ts = self.get_salt_sign_ts(word)
# 2. 定义form表单数据为字典: data={}
# 检查了salt sign
data = {
"i": word,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": salt,
"sign": sign,
"ts": ts,
"bv": "7e3150ecbdf9de52dc355751b074cf60",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME",
}
# 3. 直接发请求:requests.post(url,data=data,headers=xxx)
res = requests.post(url=self.url, data=data, headers=self.headers)
# res.json() 将json格式的字符串转为python数据类型
html = res.json()
result = html['translateResult'][0][0]['tgt']
print(result)
# html:{'translateResult': [[{'tgt': '你好', 'src': 'hello'}]], 'errorCode': 0, 'type': 'en2zh-CHS',
# 'smartResult': {'entries': ['', 'n. 表示问候, 惊奇或唤起注意时的用语\r\n', 'int. 喂;哈罗\r\n', 'n.
# (Hello)人名;(法)埃洛\r\n'], 'type': 1}} def main(self):
word = input('请输入要翻译的单词:') # 输入翻译单词
self.attack_yd(word) if __name__ == '__main__':
spider = YdSpider()
spider.main()
百度翻译破解案例(post)
破解百度翻译接口,抓取翻译结果数据
实现步骤
1、F12抓包,先翻译几个单词,查看异步数据包,找到翻译结果的json的地址,观察查询参数
1、POST地址: https://fanyi.baidu.com/v2transapi
2、Form表单数据(多次抓取在变的字段)
from: zh
to: en
sign: 54706.276099 #这个是如何生成的?
token: a927248ae7146c842bb4a94457ca35ee # 基本固定,但也想办法获取
2、抓取相关JS文件
右上角 - 搜索 - sign: - 找到具体JS文件(index_c8a141d.js) - 格式化输出
3、在JS中寻找sign的生成代码
1、在格式化输出的JS代码中搜索: sign: 找到如下JS代码:sign: m(a),
2、通过设置断点,找到m(a)函数的位置,即生成sign的具体函数
1. a 为要翻译的单词
2. 鼠标移动到 m(a) 位置处,点击上方可进入具体m(a)函数代码块
4、生成sign的m(a)函数具体代码如下(在一个大的define中),我们复制了里面的3个函数在下面
function a(r) {
if (Array.isArray(r)) {
for (var o = 0, t = Array(r.length); o < r.length; o++)
t[o] = r[o];
return t
}
return Array.from(r)
}
function n(r, o) {
for (var t = 0; t < o.length - 2; t += 3) {
var a = o.charAt(t + 2);
a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),
a = "+" === o.charAt(t + 1) ? r >>> a : r << a,
r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a
}
return r
}
function e(r) {
var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
if (null === o) {
var t = r.length;
t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))
} else {
for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)
"" !== e[C] && f.push.apply(f, a(e[C].split(""))),
C !== h - 1 && f.push(o[C]);
var g = f.length;
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(""))
}
// var u = void 0
// , l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);
// u = null !== i ? i : (i = window[l] || "") || "";
// String.fromCharCode(103)="g"
// String.fromCharCode(103)="t"
// String.fromCharCode(103)="k"
// window.gtk也就是从网页源码中取值
// 进入函数断点调试
var u = '320305.131321201'
for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {
var A = r.charCodeAt(v);
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)),
S[c++] = A >> 18 | 240,
S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,
S[c++] = A >> 6 & 63 | 128),
S[c++] = 63 & A | 128)
}
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++)
p += S[b],
p = n(p, F);
return p = n(p, D),
p ^= s,
0 > p && (p = (2147483647 & p) + 2147483648),
p %= 1e6,
p.toString() + "." + (p ^ m)
}
5、因为js代码太复杂,我们很难用js复现算法,因此我们采用第二种方案,直接将这段代码写入本地js文件,利用pyexecjs模块执行js代码进行调试
import execjs
with open('translate.js', 'r') as f:
js_data = f.read()
# 创建对象
js_obj = execjs.compile(js_data)
sign = js_obj.eval('e("monkey")') # 把monkey调入e函数
print(sign) # 546500.833013
6、获取token
在js中 token=window.common.token,在响应(响应即网页源码)中想办法获取此值,百度翻译的网页地址为token_url = 'https://fanyi.baidu.com/?aldtype=16047'。用正则去匹配 regex: "token: '(.*?)'"
代码实现
import requests
import re
import execjs class BaiduTranslateSpider(object):
def __init__(self):
self.token_url = 'https://fanyi.baidu.com/?aldtype=16047'
self.post_url = 'https://fanyi.baidu.com/v2transapi'
self.headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
# 'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'no-cache',
'cookie': 'BAIDUID=52920E829C1F64EE98183B703F4E37A9:FG=1; BIDUPSID=52920E829C1F64EE98183B703F4E37A9; PSTM=1562657403; to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; delPer=0; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BCLID=6890774803653935935; BDSFRCVID=4XAsJeCCxG3DLCbwbJrKDGwjNA0UN_I3KhXZ3J; H_BDCLCKID_SF=tRk8oIDaJCvSe6r1MtQ_M4F_qxby26nUQ5neaJ5n0-nnhnL4W46bqJKFLtozKMoI3C7fotJJ5nololIRy6CKjjb-jaDqJ5n3bTnjstcS2RREHJrg-trSMDCShGRGWlO9WDTm_D_KfxnkOnc6qJj0-jjXqqo8K5Ljaa5n-pPKKRAaqD04bPbZL4DdMa7HLtAO3mkjbnczfn02OP5P5lJ_e-4syPRG2xRnWIvrKfA-b4ncjRcTehoM3xI8LNj405OTt2LEoDPMJKIbMI_rMbbfhKC3hqJfaI62aKDs_RCMBhcqEIL4eJOIb6_w5gcq0T_HttjtXR0atn7ZSMbSj4Qo5pK95p38bxnDK2rQLb5zah5nhMJS3j7JDMP0-4rJhxby523i5J6vQpnJ8hQ3DRoWXPIqbN7P-p5Z5mAqKl0MLIOkbC_6j5DWDTvLeU7J-n8XbI60XRj85-ohHJrFMtQ_q4tehHRMBUo9WDTm_DoTttt5fUj6qJj855jXqqo8KMtHJaFf-pPKKRAashnzWjrkqqOQ5pj-WnQr3mkjbn5yfn02OpjPX6joht4syPRG2xRnWIvrKfA-b4ncjRcTehoM3xI8LNj405OTt2LEoC0XtIDhMDvPMCTSMt_HMxrKetJyaR0JhpjbWJ5TEPnjDUOdLPDW-46HBM3xbKQw5CJGBf7zhpvdWhC5y6ISKx-_J68Dtf5; ZD_ENTRY=baidu; PSINO=2; H_PS_PSSID=26525_1444_21095_29578_29521_28518_29098_29568_28830_29221_26350_29459; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1563426293,1563996067; from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1563999768; yjs_js_security_passport=2706b5b03983b8fa12fe756b8e4a08b98fb43022_1563999769_js',
'pragma': 'no-cache',
'upgrade-insecure-requests': '',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',} # 获取token和gtk
def get_token(self):
# 定义请求头
r = requests.get(self.token_url, headers=self.headers)
token = re.findall(r"token: '(.*?)'", r.text)
window_gtk = re.findall(r"window.*?gtk = '(.*?)';</script>", r.text)
if token:
return token[0], window_gtk[0] # 获取sign
def get_sign(self, word, gtk):
with open('translate.js', 'r') as f:
js_data = f.read() exec_object = execjs.compile(js_data)
sign = exec_object.eval('e("{}","{}")'.format(word, gtk)) return sign # 主函数
def main(self, word, fro, to):
token, gtk = self.get_token()
sign = self.get_sign(word, gtk)
# 找到form表单数据如下,sign和token需要想办法获取
form_data = {
'from': fro,
'to': to,
'query': word,
'transtype': 'realtime',
'simple_means_flag': '',
'sign': sign,
'token': token
}
r = requests.post(self.post_url, data=form_data, headers=self.headers)
print(r.json()['trans_result']['data'][0]['dst']) if __name__ == '__main__':
spider = BaiduTranslateSpider()
choice = input('1. 英译汉 2. 汉译英 : ')
word = input('请输入要翻译的单词:')
if choice == '':
fro, to = 'en', 'zh'
elif choice == '':
fro, to = 'zh', 'en' spider.main(word, fro, to)
爬虫——控制台抓包和requests.post()发送请求的更多相关文章
- 一步步教你为网站开发Android客户端---HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView
本文面向Android初级开发者,有一定的Java和Android知识即可. 文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新List ...
- 十分钟学会Charles抓包(iOS的http/https请求)
### 原文地址,感谢作者 : http://www.jianshu.com/p/5539599c7a25 Charles安装 HTTP抓包 HTTPS抓包 1. Charles安装 官网下载安装Ch ...
- 43.Charles抓包(iOS的http/https请求)
Charles安装 HTTP抓包 HTTPS抓包 1. Charles安装 官网下载安装Charles: https://www.charlesproxy.com/download/ 2. H ...
- Charles抓包(iOS的http/https请求)
Charles抓包(iOS的http/https请求) Charles安装 HTTP抓包 HTTPS抓包 1. Charles安装 官网下载安装Charles:https://www.charlesp ...
- python爬虫——论抓包的正确姿势和学好Javascript的重要性(1)
没事想爬下数据,就入了scrapy坑,跟着https://zhuanlan.zhihu.com/data-factory这篇教程走,中间被小数量的网站坑过,不过还是写出了爬虫~~ 切糕王子:毫无防御, ...
- 抓包神器Fiddler之Https请求随心转
随着AppleStore对APP的审核越来越严格,客户端请求服务端API的方式大多数都变更为了https,在更安全的同时又引起了另外一个问题——本地抓包开发调试的不便. 一般来说,我们在开发API的时 ...
- Python 使用 requests 模块发送请求的使用及封装
一.requests 模块基本使用 1.准备接口的URL.请求参数.请求头 # 1. 构造注册.登录.充值请求的url register_url = "注册url" login_u ...
- Mac 下抓包工具 Charles 修改特定请求
Charles 是 Mac 下常用的抓包工具,它通过将自己设置成系统的代理服务器,从而完成了抓包的工作. 同类的工具还有 fiddler 和 Wireshark,其中 fiddler 是微软公司使用 ...
- Android利用Fiddler进行网络数据抓包【怎么跟踪微信请求】
主要介绍Android及IPhone手机上如何利用Fiddler进行网络数据抓包,比如我们想抓某个应用(微博.微信.墨迹天气)的网络通信请求就可以利用这个方法. Mac 下请使用 Charles 代替 ...
随机推荐
- 【JS】JS数组添加元素的三种方法
1.push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度. 1).语法: arrayObject.push(newelement1,newelement2,....,newelement ...
- Numpy数值类型与数值运算-03
什么是NumPy? NumPy是Python中科学计算的基本软件包.它是一个Python库,提供多维数组对象,各种派生对象(例如蒙版数组和矩阵) 以及各种例程,用于对数组进行快速操作,包括数学,逻辑, ...
- 直接命令行中执行PHP代码(PHP CLI模式)
一般执行PHP代码,需要把PHP代码写成一个文件,但是有时候查一些PHP配置没有这个必要,能不能直接执行PHP代码呢? 答案是可以的. 在命令行下,采用CLI方式执行PHP代码,这里列出几个常用的命令 ...
- 【Ajax】Ajax入门总结
目录 Ajax( Asynchronous JavaScript and XML ) 向服务器发送请求 服务器回应请求 本文内容总结自 w3cschool: https://www.w3school. ...
- Java学习笔记 DbUtils数据库查询和log4j日志输出 使用
DbUtils使用 QueryRunner DbUtils中定义了一个数据库操作类QueryRunner,所有的数据库操作CRUD都是通过此类来完成. 此类是线程安全的 方法名 对应sql语句 exc ...
- Razor_02 第一个应用程序+Model+EF 添加
第一个应用程序+Model+EF 添加 小试牛刀 今天 也试了试 边说边写,但是 有时候 编辑器不给力,或者网路不给力,倒是浪费大家时间,所以今天录制完了就裁切了 部分视频,如果有不清楚的地方,可以留 ...
- 关于EFCore线程内唯一
EntityFramework的线程内唯一 EntityFramework的线程内唯一是通过httpcontext来实现的 public static DbContext DbContext() { ...
- Python切片中的误区与高级用法
众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice)就是一种截取索引片段的技术,借助切片 ...
- Linux网络——配置网络之iproute家族命令
Linux网络——配置网络之iproute家族命令 摘要:本文主要学习了iproute家族用来配置网络的命令. ip命令 ip命令用于查看和管理IP地址.接口.路由.隧道等.用来取代ifconfig命 ...
- Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战
Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战 Java生鲜电商平台- 什么是秒杀 通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定 ...