這個大數據時代,我們眼睛所看到的百分之九十的數據都是通過頁面呈現出現的,不論是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小時內與您取得聯系。