14-补环境-2
补环境系列-2
学习目标:
- 掌握 自动吐环境操作
- 掌握 Selenium 加载环境
- 熟悉 jsdom 加载环境
一 .吐环境脚本
1. 简介
Proxy可以理解为,在目标对象之前设一层"拦截",外界对该对象的访问,都必须通过这层拦截,可以对外界的访问进行过滤和改写(表示可以用它"代理"某些操作,可以翻为“代理器")。
api 地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Proxy 对象由两个部分组成:target、handler
target:目标对象 handler:是一个对象,声明了代理 target 的指定行为,支持的拦截操作,一共 13 种:
get(target,propKey,receiver):拦截对象属性的读取。target: 目标对象propKey: 被获取的属性名。receiver: Proxy 或者继承 Proxy 的对象
set(target,propKey,value,receiver):拦截对象属性的设置,返回一个布尔值(修改成功)。target: 目标对象propKey: 被获取的属性名。value: 新属性值。receiver: Proxy 或者继承 Proxy 的对象
一般的补环境的是通过运行程序后的 undefined 报错去一点一点分析,一点一点的去补一些环境,是非常掉头发的。
所以我们使用 Proxy 对全局遍历 window、document、navigator 等常见环境检测点进行代理,拦截代理对象的读取、函数调用等操作,并通过控制台输出,这样的话我们就能够实现检测环境自吐的功能,后续我们再针对吐出来的环境统一的进行补环境,这样就会方便的多。
2. 基础使用方法
var target = {
name: 'JACK',
age: 18,
};
var p = new Proxy(target, {
get: function (target, propertyKey, receiver) {
// 1 原对象
// 2 访问属性
// 3 代理器处理对象
console.log(target, propertyKey, receiver)
},
set: function(target,propertyKey,value,receiver){
// 1. 原对象
// 2. 设置的属性
// 3. 设置的值
// 4. 代理器代理的对象
console.log(target, propertyKey, value, receiver)
}
})
p.age
p.user = 'aa'注意:
我们现在写的代码,已经能够去拦截到取值和设置的操作,但是这个代码会打乱代码的后续运行,还并没有把对应的操作作用在原对象上,怎么解决呢?
3.数据返回
Reflect.get(target, propertyKey, receiver); //查找并返回target对象的name属性,receiver绑定this
Reflect.set(target, propertyKey, value, receiver); //设置target对象的name属性等于valueReflect.set(target, name, value, receiver) 是 JavaScript 中的 Reflect 对象的一个方法。它用于设置指定对象的属性值,并返回一个布尔值,表示设置是否成功。
参数的含义如下:
target:要设置属性值的目标对象。propertyKey:要设置的属性名。value:要设置的属性值。receiver(可选):设置属性时绑定的this值。
4. 完整代理使用
var target = {
name: "JACK",
age: 18,
};
var p = new Proxy(target, {
get: function (target, propertyKey, receiver) {
temp = Reflect.get(target, propertyKey, receiver); //查找并返回target对象的name属性,receiver绑定this
// 1 原对象
// 2 访问属性
// 3 代理器处理对象
// console.log(target, propertyKey, receiver)
console.log(`对象${target}--> get了属性--> ${propertyKey} 值是--> ${temp}`);
return temp;
},
set: function (target, p, value, receiver) {
temp = Reflect.set(target, p, value, receiver);
// 1. 原对象
// 2. 设置的属性
// 3. 设置的值
// 4. 代理器代理的对象
// console.log(target, propertyKey, value, receiver)
console.log("set: ", target, p, target[p]);
return temp;
},
});
// console.log(p.age);
p.user = "aa";
console.log(p.user);5. 代理封装
// 目标对象(被代理对象)
var target = {
name: 'JACK',
age: 18,
lili:{
zs:'nana'
}
};
function XlProxy(obj,name){
return new Proxy(obj,{
get(target, p, receiver) {
temp = Reflect.get(target,p,receiver)
console.log(`对象${name}--> get了属性--> ${p} 值是--> ${temp}`);
if (typeof temp == 'object'){
// 对于对象套对象进行挂代理
temp = XlProxy(temp,name + '-->' + p)
}
return temp
}
})
}
sss = XlProxy(target,'target')
sss.name
sss.lili.zs6. 封装所有使用方法
// 代理器封装
function get_enviroment(proxy_array) {
for(var i=0; i<proxy_array.length; i++){
handler = '{\n' +
' get: function(target, property, receiver) {\n' +
' console.log("方法:", "get ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return target[property];\n' +
' },\n' +
' set: function(target, property, value, receiver) {\n' +
' console.log("方法:", "set ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return Reflect.set(...arguments);\n' +
' }\n' +
'}'
eval('try{\n' + proxy_array[i] + ';\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}catch (e) {\n' + proxy_array[i] + '={};\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}')
}
}
proxy_array = ['window', 'document', 'location', 'navigator', 'history','screen']
get_enviroment(proxy_array)7.吐环境实战案例
1. 逆向目标
- 地址:https://www.toutiao.com/
- 参数:_signature
2. 逆向结果
window = global;
// 代理器封装
function get_enviroment(proxy_array) {
for(var i=0; i<proxy_array.length; i++){
handler = '{\n' +
' get: function(target, property, receiver) {\n' +
' console.log("方法:", "get ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return target[property];\n' +
' },\n' +
' set: function(target, property, value, receiver) {\n' +
' console.log("方法:", "set ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
// '" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return Reflect.set(...arguments);\n' +
' }\n' +
'}'
eval('try{\n' + proxy_array[i] + ';\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}catch (e) {\n' + proxy_array[i] + '={};\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}')
}
}
proxy_array = ['window', 'document', 'location', 'navigator', 'history','screen','aaa','target' ]
get_enviroment(proxy_array)
document = {}
document.referrer = ''
location = {}
location.href = 'https://www.toutiao.com/'
location.protocol = 'https:'
navigator.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
document.cookie = 'ttcid=0e14d7148cdb49eab083c6c3e91e0af423; _tea_utm_cache_24={%22utm_source%22:%22weixin%22%2C%22utm_medium%22:%22toutiao_android%22%2C%22utm_campaign%22:%22client_share%22}; csrftoken=05669b8011ce491783b441081b064f6c; _ga=GA1.1.910991427.1693382146; passport_csrf_token=8a241fbb55ef2ab48abea14e30e67548; s_v_web_id=verify_logwp5j9_GkE6IbXA_dJ7X_4l0P_Aj5Z_E2uOXbMZWsjV; local_city_cache=%E5%8C%97%E4%BA%AC; tt_scid=N0NYTxk1C9pMgvcI18G1bIgpcYCURGbYtDB4AkiQwsAj9d9.xFzvx7MqgzuETjec448f; _ga_QEHZPBE5HH=GS1.1.1699710472.15.0.1699710484.0.0.0'
console.log(window.byted_acrawler.sign({
"url": "https://www.toutiao.com/toutiao/api/pc/info"
}));二.Selenium 补环境
1. 简介
Selenium就是一个真实的环境地址,对于我们拿下来的 js 代码,在 node 是需要补环境的,但是在浏览器去执行的话,他就是一个真实的浏览器环境,所以可以节省我们扣代码的时间,我们可以把扣下来的代码直接用 Selenium 来进行访问
2.实战案例
1. 逆向目标
- 网址:https://q.10jqka.com.cn/
- 参数:cookie :v
2. 实现代码
我们把同花顺的 js 代码直接放到 html 文件
python 代码
import os
from selenium import webdriver
PRO_DIR = os.path.dirname(os.path.abspath(__file__))
def driver_sig(html_file):
option = webdriver.ChromeOptions()
option.add_argument('--disable-blink-features=AutomationControlled')
option.add_argument('headless')
driver = webdriver.Chrome(options=option)
driver.get(PRO_DIR +'\\'+ html_file)
# time.sleep(2)
# sig = driver.execute_script('return window.aaa()')
# print(sig)
return driver
html_file = 'index.html'
driv = driver_sig(html_file)
print(driv.execute_script('return window.aaa()'))3.实现接口
pip install flaskfrom flask import Flask
# 创建 Flask 应用实例
app = Flask(__name__)
# 定义路由和视图函数
@app.route('/')
def hello():
return 'Hello, Flask!'
# 启动应用
if __name__ == '__main__':
app.run()Flask 是一个基于 Python 的轻量级、简单易用的 Web 应用框架。它提供了一个灵活且容易扩展的方式来构建 Web 应用程序。以下是一个简单的示例展示了如何使用 Flask 框架创建一个简易的 Web 应用:
在上述示例中,我们首先导入了 Flask 模块,并创建了一个 Flask 应用实例
app。然后,使用@app.route()装饰器定义了一个路由以及对应的视图函数。在本例中,根路由'/'对应的视图函数是hello(),它返回了一个简单的字符串'Hello, Flask!'。最后,通过调用app.run()来启动应用。要运行这个应用,你需要确保已经安装了 Flask 模块。运行应用后,在浏览器中访问
http://localhost:5000/,你将看到输出的'Hello, Flask!'。
1.实际使用
# -*- coding: utf-8 -*-
from flask import Flask, request
from selenium import webdriver
import os
from selenium.webdriver.common.by import By
# pip install flask
from flask import Flask, jsonify
PRO_DIR = os.path.dirname(os.path.abspath(__file__))
def driver_sig(html_file):
option = webdriver.ChromeOptions()
option.add_argument('--disable-blink-features=AutomationControlled')
option.add_argument('headless')
driver = webdriver.Chrome(options=option)
driver.get(PRO_DIR + '\\' + html_file)
# time.sleep(2)
# sig = driver.execute_script('return window.aaa()')
# print(sig)
return driver
html_file = 'index.html'
driv = driver_sig(html_file)
# 创建 Flask 应用实例
app = Flask(__name__)
# 定义路由和视图函数
@app.route('/s', methods=['get', 'post'])
def hello():
context = {
# 加载本地地址 生成cookie值
'v': driv.execute_script('return window.aaa()')
}
# 返回cookie值
return jsonify(context=context)
# 启动应用
if __name__ == '__main__':
app.run()三.jsdom 补环境
参考地址:https://github.com/jsdom/jsdom/wiki/jsdom-中文文档
jsdom是一个纯粹由 javascript 实现的一系列 web 标准,特别是 WHATWG 组织制定的DOM和 HTML 标准,用于在nodejs中使用。大体上来说,该项目的目标是模拟足够的 Web 浏览器子集,以便用于测试和挖掘真实世界的 Web 应用程序
1. 环境安装
npm install jsdom --save2. 基本使用
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
title = dom.window.document.querySelector("p").textContent;
console.log(title);3. 添加参数形式
const dom = new JSDOM(``, {
url: "http://q.10jqka.com.cn/",
referrer: "http://q.10jqka.com.cn/",
contentType: "text/html",
includeNodeLocations: true,
storageQuota: 10000000,
});