只用firefox
代码
from playwright.async_api import async_playwright
import asyncio
import time
async def main():
async with async_playwright() as playwright:
browser = await playwright.firefox.launch(
proxy={
'server': 'http://74.x1.x1.xx:xxx',
'username': '0a06ab468ab8xxxxxx',
'password': '5070cd44e888xxxx',
},
headless=False # 改成 False,就能看到浏览器界面
)
context = await browser.new_context()
page = await context.new_page()
# 访问一个测试 IP 的网站,验证代理是否生效
await page.goto("https://httpbin.org/ip")
html_content = await page.content()
time.sleep(10000)
print(html_content)
await context.close()
await browser.close()
asyncio.run(main())
指纹库的代码
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
import asyncio
import time
async def main():
async with Stealth().use_async(async_playwright()) as playwright:
browser = await playwright.chromium.launch(
headless=False,
proxy={
'server': 'http://74.xx.xx.xx:xxx',
'username': '0a06ab468ab80exxxxx',
'password': '5070cd44e88xxxxx',
}
)
context = await browser.new_context(
viewport={"width":1920, "height":1080}, # 屏幕分辨率伪装
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/145.0.0.0 Safari/537.36"
)
# 注入脚本伪装硬件信息
await context.add_init_script("""
// CPU 核心数伪装
Object.defineProperty(navigator, 'hardwareConcurrency', {
get: () => 8
});
// 内存大小伪装
Object.defineProperty(navigator, 'deviceMemory', {
get: () => 4
});
// 外设数量伪装
navigator.mediaDevices.enumerateDevices = async () => {
return [
{ kind: "audioinput", label: "Fake Microphone", deviceId: "mic1" },
{ kind: "audiooutput", label: "Fake Speaker", deviceId: "spk1" },
{ kind: "videoinput", label: "Fake Camera", deviceId: "cam1" }
];
};
// 电池状态伪装
navigator.getBattery = async () => {
return {
charging: false,
chargingTime: 0,
dischargingTime: 3600,
level: 0.55
};
};
// 蓝牙支持伪装
Object.defineProperty(navigator, 'bluetooth', {
get: () => ({ fake: true })
});
// ========== Canvas 指纹随机化 ==========
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(type) {
const result = originalToDataURL.apply(this, arguments);
// 添加微小的随机噪声
if (type && type.startsWith('image/')) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
ctx.fillStyle = 'rgba(0,0,0,' + (Math.random() * 0.01) + ')';
ctx.fillRect(0, 0, 1, 1);
}
return result;
};
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
CanvasRenderingContext2D.prototype.getImageData = function() {
const imageData = originalGetImageData.apply(this, arguments);
// 随机微调像素
if (imageData.data && imageData.data.length > 0) {
const idx = Math.floor(Math.random() * (imageData.data.length / 4)) * 4;
imageData.data[idx] = (imageData.data[idx] + Math.floor(Math.random() * 2)) % 256;
}
return imageData;
};
// ========== WebGL 指纹随机化 ==========
const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameterCode) {
// 随机化供应商和渲染器
if (parameterCode === 37445) {
return 'Intel Inc.';
}
if (parameterCode === 37446) {
return 'Intel Iris OpenGL Engine';
}
return originalGetParameter.apply(this, arguments);
};
// WebGL2
if (WebGL2RenderingContext) {
const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter;
WebGL2RenderingContext.prototype.getParameter = function(parameterCode) {
if (parameterCode === 37445) {
return 'Intel Inc.';
}
if (parameterCode === 37446) {
return 'Intel Iris OpenGL Engine';
}
return originalGetParameter2.apply(this, arguments);
};
}
// ========== 插件列表伪装 ==========
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
// ==========MimeType伪装 ==========
Object.defineProperty(navigator, 'mimeTypes', {
get: () => []
});
""")
# 禁用图片和CSS加载,大幅提升速度
await context.route("**/*.{png,jpg,jpeg,gif,svg,ico,webp}", lambda route: route.abort())
await context.route("**/*.css", lambda route: route.abort())
# 跳过分析脚本和广告
await context.route("**/*analytics*.js", lambda route: route.abort())
await context.route("**/*googletagmanager*.js", lambda route: route.abort())
# 允许视频(如果需要看视频)
# await context.route("**/*.mp4", lambda route: route.continue_())
page = await context.new_page()
# 验证 stealth 生效
webdriver = await page.evaluate("navigator.webdriver")
print(f"navigator.webdriver = {webdriver}") # 应该是 undefined/False
await page.goto("https://www.deviceinfo.me/")
await page.wait_for_timeout(1000)
await page.goto("https://ip111.cn/")
await page.wait_for_timeout(1000)
await page.goto("https://www.youtube.com/")
await page.wait_for_timeout(1000)
print(await page.title())
time.sleep(10000)
await browser.close()
asyncio.run(main())
Firefox反检测完整代码
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
import asyncio
import time
async def main():
async with Stealth().use_async(async_playwright()) as playwright:
browser = await playwright.firefox.launch(
headless=False,
proxy={
'server': 'http://74.81.xxx.xxx:823',
'username': '0a06ab468ab80e3exxxx__cr.kr',
'password': '5070cd44e888xxxx',
}
)
context = await browser.new_context(
viewport={"width":1920, "height":1080},
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0",
timezone_id="Asia/Seoul",
locale="ko-KR",
permissions=["geolocation"],
extra_http_headers={
"Accept-Language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7"
}
)
# 注入脚本伪装硬件信息
await context.add_init_script("""
// CPU 核心数伪装
Object.defineProperty(navigator, 'hardwareConcurrency', {
get: () => 8
});
// 内存大小伪装
Object.defineProperty(navigator, 'deviceMemory', {
get: () => 4
});
// 外设数量伪装
navigator.mediaDevices.enumerateDevices = async () => {
return [
{ kind: "audioinput", label: "Fake Microphone", deviceId: "mic1" },
{ kind: "audiooutput", label: "Fake Speaker", deviceId: "spk1" },
{ kind: "videoinput", label: "Fake Camera", deviceId: "cam1" }
];
};
// 电池状态伪装
navigator.getBattery = async () => {
return {
charging: false,
chargingTime: 0,
dischargingTime: 3600,
level: 0.55
};
};
// 蓝牙支持伪装
Object.defineProperty(navigator, 'bluetooth', {
get: () => ({ fake: true })
});
// ========== Canvas 指纹随机化 ==========
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(type) {
const result = originalToDataURL.apply(this, arguments);
// 添加微小的随机噪声
if (type && type.startsWith('image/')) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
ctx.fillStyle = 'rgba(0,0,0,' + (Math.random() * 0.01) + ')';
ctx.fillRect(0, 0, 1, 1);
}
return result;
};
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
CanvasRenderingContext2D.prototype.getImageData = function() {
const imageData = originalGetImageData.apply(this, arguments);
// 随机微调像素
if (imageData.data && imageData.data.length > 0) {
const idx = Math.floor(Math.random() * (imageData.data.length / 4)) * 4;
imageData.data[idx] = (imageData.data[idx] + Math.floor(Math.random() * 2)) % 256;
}
return imageData;
};
// ========== WebGL 指纹随机化 ==========
const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameterCode) {
// 随机化供应商和渲染器
if (parameterCode === 37445) {
return 'Intel Inc.';
}
if (parameterCode === 37446) {
return 'Intel Iris OpenGL Engine';
}
return originalGetParameter.apply(this, arguments);
};
// WebGL2
if (WebGL2RenderingContext) {
const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter;
WebGL2RenderingContext.prototype.getParameter = function(parameterCode) {
if (parameterCode === 37445) {
return 'Intel Inc.';
}
if (parameterCode === 37446) {
return 'Intel Iris OpenGL Engine';
}
return originalGetParameter2.apply(this, arguments);
};
}
// ========== AudioContext 伪造 ==========
const originalAudioContext = window.AudioContext;
const originalWebkitAudioContext = window.webkitAudioContext;
// 创建伪造的 AudioContext
function createFakeAudioContext() {
const ctx = originalAudioContext ? new originalAudioContext() : new originalWebkitAudioContext();
// 伪造 getChannelData - 添加随机噪声
const originalGetChannelData = ctx.createBufferSource ? ctx.getChannelData : null;
if (ctx.getChannelData) {
ctx.getChannelData = function(channel) {
const data = originalGetChannelData.call(this, channel);
// 添加微小随机噪声
for (let i = 0; i < data.length; i += 100) {
data[i] += (Math.random() - 0.5) * 0.0001;
}
return data;
};
}
// 伪造 AnalyserNode
if (ctx.createAnalyser) {
const originalCreateAnalyser = ctx.createAnalyser;
ctx.createAnalyser = function() {
const analyser = originalCreateAnalyser.call(this);
// 伪造 getByteFrequencyData
const originalGetByteFrequencyData = analyser.getByteFrequencyData;
analyser.getByteFrequencyData = function(array) {
const result = originalGetByteFrequencyData.call(this, array);
// 添加随机偏移
for (let i = 0; i < array.length; i++) {
array[i] = Math.max(0, Math.min(255, array[i] + Math.floor(Math.random() * 3) - 1));
}
return array;
};
// 伪造 getFloatFrequencyData
const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
analyser.getFloatFrequencyData = function(array) {
const result = originalGetFloatFrequencyData.call(this, array);
// 添加随机偏移
for (let i = 0; i < array.length; i++) {
array[i] = array[i] + (Math.random() - 0.5) * 0.5;
}
return array;
};
return analyser;
};
}
return ctx;
}
// 替换 window 上的 AudioContext
window.AudioContext = createFakeAudioContext;
window.webkitAudioContext = createFakeAudioContext;
// 同时禁用旧的
Object.defineProperty(window, 'AudioContext', {
get: () => createFakeAudioContext
});
Object.defineProperty(window, 'webkitAudioContext', {
get: () => createFakeAudioContext
});
// ========== 移除自动化特征 ==========
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Object;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Proxy;
// 覆盖 navigator.webdriver
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// 移除 chrome.runtime
if (window.chrome) {
window.chrome.runtime = undefined;
}
// ========== WebRTC IP 泄露防护 ==========
// 禁用 WebRTC
window.RTCPeerConnection = undefined;
window.webkitRTCPeerConnection = undefined;
window.mozRTCPeerConnection = undefined;
// 伪装 RTCPeerConnection
window.RTCPeerConnection = function(config) {
return {
createOffer: function(success, error) {
success({
type: 'offer',
sdp: 'v=0\r\n' +
'o=- 123456789 2 IN IP4 127.0.0.1\r\n' +
's=-\r\n' +
't=0 0\r\n' +
'a=msid-semantic: WMS\r\n'
});
},
createAnswer: function(success, error) {
success({
type: 'answer',
sdp: 'v=0\r\n' +
'o=- 123456789 2 IN IP4 127.0.0.1\r\n' +
's=-\r\n' +
't=0 0\r\n'
});
},
setLocalDescription: function(desc, success, error) {
success();
},
setRemoteDescription: function(desc, success, error) {
success();
},
addIceCandidate: function(candidate, success, error) {
success();
},
close: function() {}
};
};
window.webkitRTCPeerConnection = window.RTCPeerConnection;
window.mozRTCPeerConnection = window.RTCPeerConnection;
// 禁用 getUserMedia
navigator.getUserMedia = undefined;
navigator.webkitGetUserMedia = undefined;
navigator.mozGetUserMedia = undefined;
navigator.msGetUserMedia = undefined;
// 禁用 enumerateDevices 返回真实设备信息
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
navigator.mediaDevices.enumerateDevices = async () => {
return [
{ kind: "audioinput", label: "Microphone", deviceId: "default" },
{ kind: "audiooutput", label: "Speaker", deviceId: "default" },
{ kind: "videoinput", label: "Camera", deviceId: "default" }
];
};
}
""")
# 跳过分析脚本和广告(可选)
# await context.route("**/*analytics*.js", lambda route: route.abort())
# await context.route("**/*googletagmanager*.js", lambda route: route.abort())
page = await context.new_page()
# 验证 stealth 生效
webdriver = await page.evaluate("navigator.webdriver")
print(f"navigator.webdriver = {webdriver}") # 应该是 undefined/False
await page.goto("https://pixelscan.net/")
#await page.goto("https://www.deviceinfo.me/")
print(await page.title())
time.sleep(10000)
await browser.close()
asyncio.run(main())
谷歌反检测(Profile加载+全绿)但是不能打开google
from playwright.async_api import async_playwright
import asyncio
import os
import json
import random
CONFIG = {
"profile_dir": "user_data/chrome_profile",
"proxy": {
'server': 'http://74.81.81.81:823',
'username': '0a06ab468ab80e3e6d6c__cr.gb',
'password': '5070cd44e888f480',
},
"fp": {
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"locale": "en-GB",
"tz": "Europe/London",
"screen": {"width": 1920, "height": 1080},
}
}
COMPLETE_STEALTH = """
(() => {
'use strict';
// ===== 1. webdriver:更彻底的原型链级改写(不可配置) =====
(function () {
const define = (obj) => {
try {
Object.defineProperty(obj, 'webdriver', {
get: () => false,
configurable: false
});
return true;
} catch (e) {
return false;
}
};
if (typeof Navigator !== 'undefined' && Navigator.prototype) {
if (define(Navigator.prototype)) return;
}
if (typeof navigator !== 'undefined') {
if (define(navigator)) return;
const p = Object.getPrototypeOf(navigator);
if (p) define(p);
}
})();
// ===== 2. 移除 Playwright 特征 =====
const toDelete = [
'cdc_adoQpoasnfa76pfcZLmcfl_Array',
'cdc_adoQpoasnfa76pfcZLmcfl_Object',
'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
'cdc_adoQpoasnfa76pfcZLmcfl_Proxy',
'__playwright_init_script__'
];
toDelete.forEach(key => {
if (window[key]) delete window[key];
});
if (window.chrome) window.chrome.runtime = undefined;
// ===== 3. 时区:重写 Intl 核心方法 =====
Date.prototype.getTimezoneOffset = function() { return 0; };
window.Intl = window.Intl || {};
const originalDateTimeFormat = Intl.DateTimeFormat;
Intl.DateTimeFormat = function(...args) {
const dtf = new originalDateTimeFormat(...args);
const originalResolved = dtf.resolvedOptions;
dtf.resolvedOptions = function() {
const opts = originalResolved.call(this);
opts.timeZone = 'Europe/London';
return opts;
};
return dtf;
};
Intl.DateTimeFormat.prototype.resolvedOptions = function() { return { timeZone: 'Europe/London' }; };
// ===== 4. 语言/系统信息 =====
Object.defineProperty(navigator, 'language', {value: 'en-GB', writable: false});
Object.defineProperty(navigator, 'languages', {value: ['en-GB','en-US','en'], writable: false});
Object.defineProperty(navigator, 'platform', { get: () => 'Win32' });
Object.defineProperty(navigator, 'vendor', { get: () => '', configurable: false });
Object.defineProperty(navigator, 'hardwareConcurrency', {value: 8, configurable: true});
Object.defineProperty(navigator, 'deviceMemory', {value: 4, configurable: true});
// ===== 5. MimeTypes/Plugins 伪装为空 =====
const createEmptyList = function() {
const arr = []; arr.length = 0;
arr.item = function(i) { return null; };
arr.namedItem = function(name) { return null; };
return arr;
};
Object.defineProperty(navigator, 'mimeTypes', { get: createEmptyList, configurable: false });
Object.defineProperty(navigator, 'plugins', { get: createEmptyList, configurable: false });
// ===== 6. Canvas 指纹随机化 =====
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function(type) {
const result = originalToDataURL.apply(this, arguments);
if (type && type.startsWith('image/')) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1; canvas.height = 1;
ctx.fillStyle = 'rgba(0,0,0,' + (Math.random() * 0.01) + ')';
ctx.fillRect(0, 0, 1, 1);
}
return result;
};
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
CanvasRenderingContext2D.prototype.getImageData = function() {
const imageData = originalGetImageData.apply(this, arguments);
if (imageData.data && imageData.data.length > 0) {
const idx = Math.floor(Math.random() * (imageData.data.length / 4)) * 4;
imageData.data[idx] = (imageData.data[idx] + Math.floor(Math.random() * 2)) % 256;
}
return imageData;
};
// ===== 7. WebGL 指纹伪装 =====
const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameterCode) {
if (parameterCode === 37445) return 'Intel Inc.';
if (parameterCode === 37446) return 'Intel Iris OpenGL Engine';
return originalGetParameter.apply(this, arguments);
};
if (WebGL2RenderingContext) {
const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter;
WebGL2RenderingContext.prototype.getParameter = function(parameterCode) {
if (parameterCode === 37445) return 'Intel Inc.';
if (parameterCode === 37446) return 'Intel Iris OpenGL Engine';
return originalGetParameter2.apply(this, arguments);
};
}
// ===== 8. 外设/电池伪装 =====
navigator.mediaDevices.enumerateDevices = async () => {
return [
{ kind: "audioinput", label: "Fake Microphone", deviceId: "mic1" },
{ kind: "audiooutput", label: "Fake Speaker", deviceId: "spk1" },
{ kind: "videoinput", label: "Fake Camera", deviceId: "cam1" }
];
};
navigator.getBattery = async () => { return { charging: false, chargingTime: 0, dischargingTime: 3600, level: 0.55 }; };
// ===== 9. WebRTC 伪装 =====
window.RTCPeerConnection = function(config) {
return {
createOffer: function(success, error) { success({ type: 'offer', sdp: 'v=0\r\no=- 123456789 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n' }); },
createAnswer: function(success, error) { success({ type: 'answer', sdp: 'v=0\r\no=- 123456789 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n' }); },
setLocalDescription: function(desc, success, error) { success(); },
setRemoteDescription: function(desc, success, error) { success(); },
addIceCandidate: function(candidate, success, error) { success(); },
close: function() {}
};
};
window.webkitRTCPeerConnection = window.RTCPeerConnection;
// ===== 10. 权限伪装 =====
const originalQuery = window.navigator.permissions?.query;
if (originalQuery) {
window.navigator.permissions.query = (parameters) => {
const name = parameters.name || parameters;
if (name === 'notifications') {
return Promise.resolve({
state: Notification.permission,
onchange: null,
addEventListener: () => {},
removeEventListener: () => {},
dispatchEvent: () => false
});
}
return originalQuery.apply(window.navigator.permissions, arguments);
};
}
window.__complete_stealth_done = true;
})();
"""
async def basic_check(page):
return await page.evaluate("""() => ({
webdriver: navigator.webdriver,
userAgent: navigator.userAgent,
platform: navigator.platform,
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
chrome: !!window.chrome,
stealth_done: !!window.__complete_stealth_done,
})""")
async def human_behavior(page):
await page.wait_for_timeout(random.randint(2000, 4000))
for i in range(15):
t = i / 14
x = 500 + 900 * t + random.randint(-5, 5)
y = 400 + 300 * t + random.randint(-5, 5)
await page.mouse.move(x, y)
await page.wait_for_timeout(random.randint(30, 80))
await page.mouse.wheel(0, random.randint(100, 300))
await page.wait_for_timeout(random.randint(200, 600))
async def main():
profile_dir = CONFIG["profile_dir"]
os.makedirs(profile_dir, exist_ok=True)
async with async_playwright() as playwright:
# ✅ 这里改成:直接用持久化上下文加载 profile
context = await playwright.chromium.launch_persistent_context(
user_data_dir=profile_dir, # 🔥 核心:加载本地profile
headless=False,
proxy=CONFIG["proxy"],
viewport=CONFIG["fp"]["screen"],
user_agent=CONFIG["fp"]["ua"],
timezone_id=CONFIG["fp"]["tz"],
locale=CONFIG["fp"]["locale"],
extra_http_headers={"Accept-Language": "en-GB,en;q=0.9"},
permissions=[],
args=[
'--disable-blink-features=AutomationControlled',
'--disable-features=IsolateOrigins,site-per-process,WebRTCHideLocalIpsWithMdns',
'--disable-web-security',
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-webrtc-hide-local-ips-with-mdns',
]
)
# 注入隐身脚本
await context.add_init_script(COMPLETE_STEALTH)
page = context.pages[0] if context.pages else await context.new_page()
# 自检
print("🔍 [注入后] 核心指纹:")
check1 = await basic_check(page)
print(json.dumps(check1, indent=2, default=str))
await human_behavior(page)
print("\n🌐 访问 pixelscan.net...")
await page.goto("https://pixelscan.net/", wait_until="networkidle")
await page.wait_for_timeout(15000)
print("\n🔍 [站点加载后] 核心指纹:")
check2 = await basic_check(page)
print(json.dumps(check2, indent=2, default=str))
await page.screenshot(path="debug_complete.png", full_page=True)
print("\n📸 截图: debug_complete.png")
print("\n📊 核心验证:")
results = [
("webdriver", not check2.get('webdriver'), "✅" if not check2.get('webdriver') else "❌"),
("timezone", check2.get('timezone') == 'Europe/London', "✅" if check2.get('timezone') == 'Europe/London' else "❌"),
("chrome", check2.get('chrome') == True, "✅" if check2.get('chrome') else "❌"),
]
for name, passed, icon in results:
print(f" {icon} {name}: {'PASS' if passed else 'FAIL'}")
print("\n✅ Profile 已加载。按 Ctrl+C 退出...")
await asyncio.Event().wait()
await context.close()
if __name__ == "__main__":
asyncio.run(main())
能打开谷歌,firefox反检测(全绿+profile) 但是不能google登录
from playwright.async_api import async_playwright
import asyncio
import os
import random
# 🔥 核心:复刻真实英国Firefox用户的指纹(无手动篡改,无伪装痕迹)
REAL_FIREFOX_FP = {
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0",
"locale": "en-GB",
"tz": "Europe/London",
"screen": {"width": 1920, "height": 1080},
# 真人硬件指纹(从真实英国用户Firefox提取)
"hardwareConcurrency": 8,
"deviceMemory": 8,
"platform": "Win32",
"vendor": "",
"product": "Gecko",
"productSub": "20100101"
}
# 🔥 无篡改痕迹的脚本:只做「隐藏自动化标识」,不修改指纹(关键)
STEALTH_NO_MASK = """
(() => {
// 1. 静默隐藏webdriver(无篡改痕迹)
const navProto = Navigator.prototype;
Object.defineProperties(navProto, {
webdriver: {
get: () => undefined,
configurable: false,
enumerable: false
}
});
// 2. 关闭自动化协议(无篡改痕迹)
delete window.marionette;
delete window.__mozilla__;
// 3. 保持原生指纹不变(核心:不修改language/platform等)
// 所有指纹由Firefox原生配置提供,无手动修改痕迹
})();
"""
async def main():
profile_dir = "user_data/real_firefox_profile"
os.makedirs(profile_dir, exist_ok=True)
async with async_playwright() as playwright:
# 🔥 启动原生Firefox(无任何指纹篡改配置)
context = await playwright.firefox.launch_persistent_context(
user_data_dir=profile_dir,
headless=False,
proxy={
'server': 'http://74.81.81.81:823',
'username': '0a06ab468ab80e3e6d6c__cr.gb',
'password': '5070cd44e888f480',
},
# 🔥 核心:用原生配置匹配指纹,而非手动修改
user_agent=REAL_FIREFOX_FP["ua"],
locale=REAL_FIREFOX_FP["locale"],
timezone_id=REAL_FIREFOX_FP["tz"],
viewport=REAL_FIREFOX_FP["screen"],
permissions=[],
# 原生启动参数(无任何指纹修改)
args=[
"--start-maximized",
"--no-remote",
"--disable-private-browsing"
],
# 🔥 原生Firefox偏好设置(模拟真实英国用户)
firefox_user_prefs={
# 系统级语言配置(无篡改痕迹)
"intl.locale.requested": "en-GB",
"intl.accept_languages": "en-GB,en",
"general.useragent.locale": "en-GB",
# 关闭自动化特征(无篡改痕迹)
"marionette.enabled": False,
"dom.webdriver.enabled": False,
# 原生硬件配置(匹配真实用户)
"browser.cache.disk.enable": True,
"browser.cache.memory.enable": True,
"network.cookie.cookieBehavior": 0,
"browser.send_pings": False
},
# 禁用所有Playwright的自动化注入
ignore_default_args=["--marionette", "--enable-automation"]
)
# 注入「无篡改痕迹」的反检测脚本
await context.add_init_script(STEALTH_NO_MASK)
page = await context.new_page()
# 🔥 模拟真人操作节奏(关键:无机器人特征)
await asyncio.sleep(random.uniform(1.5, 3.5)) # 随机延迟,更像真人
print("🌐 以原生英国Firefox环境打开Google...")
# 访问Google(无任何指纹修改,纯原生环境)
await page.goto(
"https://www.google.com",
wait_until="domcontentloaded",
timeout=60000
)
# 验证指纹(确认无篡改痕迹)
fp_check = await page.evaluate("""
({
webdriver: navigator.webdriver,
language: navigator.language,
platform: navigator.platform,
hardwareConcurrency: navigator.hardwareConcurrency
})
""")
print(f"✅ 指纹验证:{fp_check}")
print("✅ Google加载完成!无指纹伪装痕迹")
await asyncio.Event().wait()
await context.close()
if __name__ == "__main__":
asyncio.run(main())
123

1万+

被折叠的 条评论
为什么被折叠?



