这个大数据时代,我们眼睛所看到的百分之九十的数据都是通过页面呈现出现的,不论是PC端、网页端还是移动端,数据渲染还是基于html/h5+javascript进行的,而大多数的数据都是通过请求后台接口动态渲染的。而想成功的请求成功互联网上的开放/公开接口,必须知道它的URL、Headers、Params、Body等数据是如何生成的。但是在此之前我们需要了解浏览器开发者工具的功能,入门JS逆向。
浏览器F12开发者工具面板
最常使用的功能,俗称抓包界面。可以捕获当前页面的所有资源请求,包括URL、协议、端口、请求和响应等
存放网页源代码的地方,这里可以看到访问站点所有依赖的域名资源,包括html、css、js等
断点
1. 跳过子函数(次态函数)执行(只在主函数内一步一步执行,不进入子函数内部);
2. 进入子函数(次态函数)执行(在主函数内部一步一步执行,如果遇到子函数,会跳转到子函数内部一步一步执行);
3. 跳出当前函数,回到调用位置;
4. 单步执行,会进入到函数内部 更加的细致;
最后一个图标:屏蔽断点
相当于一个浏览器本地数据库,可查看本地会话存储、Cookies等信息
如果想要逆向网页的某个API,需要以下关键信息:
请求信息
断点的主要作用是对数据进行监听,就跟平时开发代码Debug调试一样,跟值进行分析
网站运行时间轴:
数据流程
注意:非XHR发送的就断不住
栈是一种先进后出的特殊线性表结构
调用栈是解析器的一种机制,可以在脚本调用多个函数时,跟踪每个函数在完成执行时应该返回控制的点
栈
无限debbugger不会真正得死循环,而是有规律得执行逻辑,一般用定时器
Function("debugger;").call()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<h1 id="IMS"></h1>
<body>
<script>
var ss=document.getElementById('IMS')
function test() {
debugger;
}
setInterval(test,100);
ss.innerHTML="HELLO WORLD";
</script>
</body>
</html>
当定义器运行到这个debugger这个代码的时候,可以点击“一律不再此处暂停”
Debugger断点处理
写个1===0的先验条件,永远为假,就永远不会进入这个断点了。
无限debugger产生的原因是代码里 test 这个函数造成的,所以我们可以重写这个函数,使无限debugger失效.在控制台中输入function test(){}即可
注:一定要在debugger进入之前
setInterval=function test(){}
Function.prototype.__constructor_back=Function.prototype.constructor;
Function.prototype.constructor=function() {
if(arguments && typeof arguments[0]==='string'){
if("debugger"===arguments[0]){
return
}
}
return Function.prototype.__constructor_back.apply(this,arguments);
}
Hook 是一种钩子技术,在系统没有调用函数之前,钩子程序就先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,也可以强制结束消息的传递。简单来说,修改原有的 JS 代码就是 Hook。
Hook 技术之所以能够实现有两个条件:
注意:JS 变量是有作用域的,只有当被 hook 函数和 debugger 断点在同一个作用域的时候,才能 hook 成功。
注:最常用的是hook cookie
WebAPI地址:https://developer.mozilla.org/zh-CN/docs/Web/API
Object.defineProperty为对象的属性赋值,替换对象属性
基本语法:Object.defineProperty(obj, prop, descriptor),它的作用就是直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,接收的三个参数含义如下:
Object.defineProperty(user,"uuid",{
get:function(){
console.log("xxx来获取值了!!");
return count;
},
set:function(newVal){
console.log("xxx来设置值了!!");
count=newVal+1;
}
})
cookie 示例
cookie 钩子用于定位 cookie 中关键参数生成位置,以下代码演示了当 cookie 中匹配到了 v, 则插入断点:
(function () {
var cookieTemp='';
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.indexOf('v') !=-1) {
debugger;
}
console.log('Hook捕获到cookie设置->', val);
cookieTemp=val;
return val;
},
get: function () {
return cookieTemp;
},
});
})();
注:正常hook cookie操作的时候需要清除下cookie
我们知道在 JavaScript 中 JSON.stringify() 方法用于将 JavaScript 对象或值转换为 JSON 字符串,JSON.parse() 方法用于将一个 JSON 字符串转换为 JavaScript 对象,某些站点在向 web 服务器传输用户名密码时,会用到这两个方法
(function() {
var stringify=JSON.stringify;
JSON.stringify=function(params) {
console.log("Hook JSON.stringify ——> ", params);
debugger;
return stringify(params);
}
})();
首先定义了一个变量 stringify 保留原始 JSON.stringify 方法,然后重写 JSON.stringify 方法,遇到 JSON.stringify 方法就会执行 debugger 语句,会立即断下,最后将接收到的参数返回给原始的 JSON.stringify 方法进行处理,确保数据正常传输
(function () {
var open=window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open=function (method, url, async) {
if (url.indexOf("analysis") !=1) {
debugger;
}
return open.apply(this, arguments);
};
})();
定义了一个变量 open 保留原始 XMLHttpRequest.open 方法,然后重写 XMLHttpRequest.open 方法,判断如果 rnd 字符串值在 URL 里首次出现的位置不为 -1,即 URL 里包含 analysis字符串,则执行 debugger 语句,会立即断下。
模块地址:https://github.com/doloopwhile/PyExecJS
PyExecJS 是使用最多的一种方式,底层实现方式是:在本地 JS 环境下运行 JS 代码
pip install PyExecJS
读取JS代码
with open(file_name, 'r', encoding='UTF-8') as file:
result=file.read()
execjs 类的compile()方法编译加载上面的 JS 字符串,返回一个上下文对象
context1=execjs.compile("JS代码")
调用上下文对象的call() 方法执行 JS 方法
result1=context1.call("函数", "参数1", "参数2")
注意:由于 PyExecJS 运行在本地 JS 环境下,使用之前会启动 JS 环境,最终导致运行速度会偏慢
eval执行
eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行
print(execjs.eval('Date.now()'))
document={
cookie:'uuid_tt_dd=10_29360271920-1658044222535-945484; __gads=ID=5b925b796ab29466-22740a5938d50041:T=1658044224:RT=1658044224:S=ALNI_MYZZ3qnATdjgh4YHRlZaBk3TnwTFw; p_uid=U010000',
location : {
href:'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=87135040_oem_dg&wd=eval%20JS%20&fenlei=256&oq=eval&rsv_pq=e1b3f2520003297e&rsv_t=7e58%2ByqRgVEysyNAVRctyGmKUct9An%2B6da7wzdVJDXgo7qaAS1DKyn86mLazGA1IqBPpY359&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_btype=t&inputT=860&rsv_sug3=56&rsv_sug1=35&rsv_sug7=100&rsv_sug2=0&rsv_sug4=1037'
}
}
navigator={userAgent:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'}
window={
document : document,
navigator:navigator
}
console.log(document.location.href);
document.getElementsByTagName=function(){};
用阳光乐观的心态去面对生活和工作,它们一样也会回报给你阳光。
习Python的人绝大部分都是在用Python做爬虫,毕竟对于爬虫而言Python是不二选。
但是一般简单的静态页面网站还是很好爬取的,对于很多动态加载的网站就不知道怎么办了,今天小编就给大家介绍两种爬取js加载的动态数据,希望对爬虫方面有所帮助!
如何知道这个网站是动态加载的数据?
用浏览器,这里小编建议使用火狐或者谷歌这个想必大家都知道的
打开你网页,右键查看页面源代码,ctrl +F 查询输入293,源代码里面并没有这个值,说明是动态加载数据。
它的网址是: 数字代表的第几页。它一共是165页
所以想要获取全部的url地址就非常简单了
对于动态加载数据,我们常用的两个方法:
为什么要这么写,代码里面表明了注释!
既然要分析网页元素,首先我们肯定是要用到了开发者工具,按F12就可以打开浏览器自带的开发者工具。如下图
分析得知类型为json的那一栏即是我们需要的数据
查看消息头里面的请求网站:
https://data-gkcx.eol.cn/soudaxue/queryProvince.html?messtype=jsonp&callback=jQuery183005011523805365803_1512185796058&luqutype3=&province3=&year3=&luqupici3=&page=2&size=10&_=1512185798203
真正的请求网站:
https://data-gkcx.eol.cn/soudaxue/queryProvince.html
参数 :
messtype=jsonp&callback=jQuery183005011523805365803_1512185796058&luqutype3=&province3=&year3=&luqupici3=&page=2&size=10&_=1512185798203
也可以点击右侧的参数栏参看参数
方法很简单,主要还是自己动手去实践,实践才能出真知,在岸上学游泳是永远也学不会的。就这么简单的两种方法就可以爬取JS加载的动态数据了,方法都挺简单的,你学会了么?赶紧去试试吧!
avaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
JavaScript 显示数据
JavaScript 可以通过不同的方式来输出数据:
使用 window.alert() 弹出警告框。
使用 document.write() 方法将内容写到 HTML 文档中。
使用 innerHTML 写入到 HTML 元素。
使用 console.log() 写入到浏览器的控制台。
使用 window.alert()
你可以弹出警告框来显示数据:
实例
nbsp;html>
我的第一个页面
我的第一个段落。
操作 HTML 元素
如需从 JavaScript 访问某个 HTML 元素,您可以使用 document.getElementById(id) 方法。
请使用 “id” 属性来标识 HTML 元素,并 innerHTML 来获取或插入元素内容:
实例
nbsp;html>
我的第一个 Web 页面
"demo">我的第一个段落
以上 JavaScript 语句(在 标签中)可以在 web 浏览器中执行:
document.getElementById(“demo”) 是使用 id 属性来查找 HTML 元素的 JavaScript 代码 。
innerHTML=“段落已修改。” 是用于修改元素的 HTML 内容(innerHTML)的JavaScript 代码。
在本教程中
在大多数情况下,在本教程中,我们将使用上面描述的方法来输出:
上面的例子直接把 id=”demo” 的
元素写到 HTML 文档输出中:
写到 HTML 文档
出于测试目的,您可以将JavaScript直接写在HTML 文档中:
实例
nbsp;html>
我的第一个 Web 页面
我的第一个段落。
Fri Apr 22 2022 16:20:12 GMT+0800 (中国标准时间)
请使用 document.write() 仅仅向文档输出写内容。
如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖。
实例
nbsp;html>
我的第一个 Web 页面
我的第一个段落。
"MYFUNCTION()">点我
写到控制台
如果您的浏览器支持调试,你可以使用 console.log() 方法在浏览器中显示 JavaScript 值。
浏览器中使用 F12 来启用调试模式, 在调试窗口中点击 “Console” 菜单。
nbsp;html>
我的第一个 Web 页面
实例 console 截图:
您知道吗?
程序中调试是测试,查找及减少bug(错误)的过程。
*请认真填写需求信息,我们会在24小时内与您取得联系。