mdbq 4.0.85__py3-none-any.whl → 4.0.87__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mdbq/__version__.py +1 -1
- mdbq/js/__init__.py +4 -0
- mdbq/js/jc.py +376 -0
- {mdbq-4.0.85.dist-info → mdbq-4.0.87.dist-info}/METADATA +1 -1
- {mdbq-4.0.85.dist-info → mdbq-4.0.87.dist-info}/RECORD +7 -5
- {mdbq-4.0.85.dist-info → mdbq-4.0.87.dist-info}/WHEEL +0 -0
- {mdbq-4.0.85.dist-info → mdbq-4.0.87.dist-info}/top_level.txt +0 -0
mdbq/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = '4.0.
|
1
|
+
VERSION = '4.0.87'
|
mdbq/js/__init__.py
ADDED
mdbq/js/jc.py
ADDED
@@ -0,0 +1,376 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
JS和CSS混淆工具
|
6
|
+
自动清除注释,默认不添加反调试
|
7
|
+
|
8
|
+
### 1. 检查工具
|
9
|
+
```bash
|
10
|
+
python3 jc.py --check
|
11
|
+
```
|
12
|
+
|
13
|
+
### 2. 安装依赖(仅首次使用)
|
14
|
+
```bash
|
15
|
+
python3 jc.py --install
|
16
|
+
```
|
17
|
+
|
18
|
+
### 3. 开始混淆
|
19
|
+
```bash
|
20
|
+
# 混淆整个项目
|
21
|
+
python3 jc.py -i ./
|
22
|
+
|
23
|
+
# 混淆指定目录
|
24
|
+
```bash
|
25
|
+
cd /Users/xigua/data2/sycm
|
26
|
+
python3 jc.py -i ./js -o /Users/xigua/Downloads/加密版本/sycm/js
|
27
|
+
python3 jc.py -i ./css -o /Users/xigua/Downloads/加密版本/sycm/css
|
28
|
+
```
|
29
|
+
|
30
|
+
## 注意事项
|
31
|
+
- 自动跳过 `.min.js` 和 `.min.css` 文件
|
32
|
+
- 保护重要的全局变量如 `window`、`document`、`navigator`
|
33
|
+
|
34
|
+
"""
|
35
|
+
|
36
|
+
import os
|
37
|
+
import subprocess
|
38
|
+
import shutil
|
39
|
+
import json
|
40
|
+
import argparse
|
41
|
+
from pathlib import Path
|
42
|
+
|
43
|
+
class EasyObfuscator:
|
44
|
+
"""极简版混淆器 - 使用全局安装的现成库"""
|
45
|
+
|
46
|
+
def __init__(self, source_dir: str, output_dir: str = None):
|
47
|
+
self.source_dir = Path(source_dir)
|
48
|
+
self.output_dir = Path(output_dir) if output_dir else self.source_dir / "obfuscated"
|
49
|
+
self.stats = {
|
50
|
+
'js_files': 0,
|
51
|
+
'css_files': 0,
|
52
|
+
'other_files': 0,
|
53
|
+
'errors': 0
|
54
|
+
}
|
55
|
+
|
56
|
+
def ensure_output_dir(self):
|
57
|
+
"""确保输出目录存在"""
|
58
|
+
self.output_dir.mkdir(parents=True, exist_ok=True)
|
59
|
+
|
60
|
+
def obfuscate_js_simple(self, input_file: Path, output_file: Path):
|
61
|
+
"""使用简单方法混淆JS文件"""
|
62
|
+
try:
|
63
|
+
# 首先尝试使用 javascript-obfuscator
|
64
|
+
cmd = [
|
65
|
+
'javascript-obfuscator',
|
66
|
+
str(input_file),
|
67
|
+
'--output', str(output_file),
|
68
|
+
'--compact', 'true',
|
69
|
+
'--string-array', 'true',
|
70
|
+
'--string-array-encoding', 'base64',
|
71
|
+
'--string-array-threshold', '0.75',
|
72
|
+
'--transform-object-keys', 'true',
|
73
|
+
'--unicode-escape-sequence', 'false',
|
74
|
+
'--debug-protection', 'false',
|
75
|
+
'--self-defending', 'false',
|
76
|
+
'--control-flow-flattening', 'false'
|
77
|
+
]
|
78
|
+
|
79
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
80
|
+
print(f" ✅ JS混淆: {input_file.name}")
|
81
|
+
self.stats['js_files'] += 1
|
82
|
+
return True
|
83
|
+
|
84
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
85
|
+
# 备选方案:使用 terser
|
86
|
+
try:
|
87
|
+
cmd = [
|
88
|
+
'terser', str(input_file),
|
89
|
+
'--compress', 'drop_console=false,drop_debugger=true',
|
90
|
+
'--mangle', 'reserved=["window","document","navigator"]',
|
91
|
+
'--output', str(output_file),
|
92
|
+
'--comments', 'false'
|
93
|
+
]
|
94
|
+
|
95
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
96
|
+
print(f" ✅ JS压缩: {input_file.name}")
|
97
|
+
self.stats['js_files'] += 1
|
98
|
+
return True
|
99
|
+
|
100
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
101
|
+
# 最后备选:直接复制
|
102
|
+
shutil.copy2(input_file, output_file)
|
103
|
+
print(f" ⚠️ JS复制: {input_file.name} (混淆工具不可用)")
|
104
|
+
self.stats['other_files'] += 1
|
105
|
+
return False
|
106
|
+
|
107
|
+
def obfuscate_css_simple(self, input_file: Path, output_file: Path):
|
108
|
+
"""使用简单方法压缩CSS文件"""
|
109
|
+
try:
|
110
|
+
# 尝试使用 csso
|
111
|
+
cmd = [
|
112
|
+
'csso',
|
113
|
+
'--input', str(input_file),
|
114
|
+
'--output', str(output_file),
|
115
|
+
'--restructure-off'
|
116
|
+
]
|
117
|
+
|
118
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
119
|
+
print(f" ✅ CSS压缩: {input_file.name}")
|
120
|
+
self.stats['css_files'] += 1
|
121
|
+
return True
|
122
|
+
|
123
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
124
|
+
# 备选方案:使用 cleancss
|
125
|
+
try:
|
126
|
+
cmd = [
|
127
|
+
'cleancss',
|
128
|
+
'--output', str(output_file),
|
129
|
+
str(input_file)
|
130
|
+
]
|
131
|
+
|
132
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
133
|
+
print(f" ✅ CSS压缩: {input_file.name}")
|
134
|
+
self.stats['css_files'] += 1
|
135
|
+
return True
|
136
|
+
|
137
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
138
|
+
# 最后备选:手动简单压缩
|
139
|
+
self.manual_css_compress(input_file, output_file)
|
140
|
+
return False
|
141
|
+
|
142
|
+
def manual_css_compress(self, input_file: Path, output_file: Path):
|
143
|
+
"""手动进行简单的CSS压缩"""
|
144
|
+
try:
|
145
|
+
with open(input_file, 'r', encoding='utf-8') as f:
|
146
|
+
css_content = f.read()
|
147
|
+
|
148
|
+
# 简单的CSS压缩
|
149
|
+
import re
|
150
|
+
|
151
|
+
# 移除注释
|
152
|
+
css_content = re.sub(r'/\*.*?\*/', '', css_content, flags=re.DOTALL)
|
153
|
+
|
154
|
+
# 移除多余空白
|
155
|
+
css_content = re.sub(r'\s+', ' ', css_content)
|
156
|
+
css_content = re.sub(r';\s*}', ';}', css_content)
|
157
|
+
css_content = re.sub(r'{\s*', '{', css_content)
|
158
|
+
css_content = re.sub(r'}\s*', '}', css_content)
|
159
|
+
css_content = re.sub(r';\s*', ';', css_content)
|
160
|
+
|
161
|
+
css_content = css_content.strip()
|
162
|
+
|
163
|
+
with open(output_file, 'w', encoding='utf-8') as f:
|
164
|
+
f.write(css_content)
|
165
|
+
|
166
|
+
print(f" ✅ CSS手动压缩: {input_file.name}")
|
167
|
+
self.stats['css_files'] += 1
|
168
|
+
|
169
|
+
except Exception as e:
|
170
|
+
print(f" ❌ CSS处理失败 {input_file.name}: {e}")
|
171
|
+
shutil.copy2(input_file, output_file)
|
172
|
+
self.stats['errors'] += 1
|
173
|
+
|
174
|
+
def copy_other_files(self, input_file: Path, output_file: Path):
|
175
|
+
"""复制其他文件"""
|
176
|
+
try:
|
177
|
+
output_file.parent.mkdir(parents=True, exist_ok=True)
|
178
|
+
shutil.copy2(input_file, output_file)
|
179
|
+
self.stats['other_files'] += 1
|
180
|
+
except Exception as e:
|
181
|
+
print(f" ❌ 复制文件失败 {input_file.name}: {e}")
|
182
|
+
self.stats['errors'] += 1
|
183
|
+
|
184
|
+
def process_all_files(self):
|
185
|
+
"""处理所有文件"""
|
186
|
+
print(f"🚀 开始处理目录: {self.source_dir}")
|
187
|
+
print(f"📁 输出目录: {self.output_dir}")
|
188
|
+
|
189
|
+
# 确保输出目录存在
|
190
|
+
self.ensure_output_dir()
|
191
|
+
|
192
|
+
# 遍历所有文件
|
193
|
+
for file_path in self.source_dir.rglob('*'):
|
194
|
+
if file_path.is_file():
|
195
|
+
# 跳过一些不需要处理的文件
|
196
|
+
if (file_path.name.startswith('.') or
|
197
|
+
'node_modules' in str(file_path) or
|
198
|
+
'obfuscated' in str(file_path) or
|
199
|
+
'__pycache__' in str(file_path)):
|
200
|
+
continue
|
201
|
+
|
202
|
+
# 计算相对路径
|
203
|
+
relative_path = file_path.relative_to(self.source_dir)
|
204
|
+
output_path = self.output_dir / relative_path
|
205
|
+
|
206
|
+
# 确保输出目录存在
|
207
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
208
|
+
|
209
|
+
# 根据文件类型处理
|
210
|
+
if file_path.suffix.lower() == '.js':
|
211
|
+
# 跳过已经压缩的文件
|
212
|
+
if not file_path.name.endswith('.min.js'):
|
213
|
+
self.obfuscate_js_simple(file_path, output_path)
|
214
|
+
else:
|
215
|
+
self.copy_other_files(file_path, output_path)
|
216
|
+
|
217
|
+
elif file_path.suffix.lower() == '.css':
|
218
|
+
# 跳过已经压缩的文件
|
219
|
+
if not file_path.name.endswith('.min.css'):
|
220
|
+
self.obfuscate_css_simple(file_path, output_path)
|
221
|
+
else:
|
222
|
+
self.copy_other_files(file_path, output_path)
|
223
|
+
|
224
|
+
else:
|
225
|
+
# 其他文件直接复制
|
226
|
+
self.copy_other_files(file_path, output_path)
|
227
|
+
|
228
|
+
# 打印统计信息
|
229
|
+
self.print_stats()
|
230
|
+
|
231
|
+
def print_stats(self):
|
232
|
+
"""打印处理统计"""
|
233
|
+
print("\n" + "="*50)
|
234
|
+
print("📊 处理完成统计:")
|
235
|
+
print(f" JavaScript文件: {self.stats['js_files']}")
|
236
|
+
print(f" CSS文件: {self.stats['css_files']}")
|
237
|
+
print(f" 其他文件: {self.stats['other_files']}")
|
238
|
+
print(f" 错误: {self.stats['errors']}")
|
239
|
+
print(f" 总计: {sum(self.stats.values())}")
|
240
|
+
print(f"\n✅ 混淆文件已保存到: {self.output_dir}")
|
241
|
+
print("="*50)
|
242
|
+
|
243
|
+
def check_tools(self):
|
244
|
+
"""检查可用的工具"""
|
245
|
+
print("🔍 检查可用工具...")
|
246
|
+
|
247
|
+
tools = {
|
248
|
+
'javascript-obfuscator': 'JavaScript混淆器',
|
249
|
+
'terser': 'JavaScript压缩器',
|
250
|
+
'csso': 'CSS优化器',
|
251
|
+
'cleancss': 'CSS压缩器'
|
252
|
+
}
|
253
|
+
|
254
|
+
available_tools = []
|
255
|
+
for tool, description in tools.items():
|
256
|
+
try:
|
257
|
+
subprocess.run([tool, '--version'],
|
258
|
+
capture_output=True, check=True)
|
259
|
+
print(f" ✅ {tool}: {description}")
|
260
|
+
available_tools.append(tool)
|
261
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
262
|
+
print(f" ❌ {tool}: 未安装")
|
263
|
+
|
264
|
+
if not available_tools:
|
265
|
+
print("\n⚠️ 没有找到任何混淆工具!")
|
266
|
+
print("请先安装:npm install -g javascript-obfuscator terser csso-cli clean-css-cli")
|
267
|
+
return False
|
268
|
+
|
269
|
+
print(f"\n✅ 找到 {len(available_tools)} 个可用工具")
|
270
|
+
return True
|
271
|
+
|
272
|
+
def install_tools():
|
273
|
+
"""安装混淆工具"""
|
274
|
+
print("📦 安装混淆工具...")
|
275
|
+
|
276
|
+
try:
|
277
|
+
cmd = ['npm', 'install', '-g',
|
278
|
+
'javascript-obfuscator',
|
279
|
+
'terser',
|
280
|
+
'csso-cli',
|
281
|
+
'clean-css-cli']
|
282
|
+
|
283
|
+
result = subprocess.run(cmd, check=True)
|
284
|
+
print("✅ 工具安装完成!")
|
285
|
+
return True
|
286
|
+
|
287
|
+
except subprocess.CalledProcessError as e:
|
288
|
+
print(f"❌ 安装失败: {e}")
|
289
|
+
print("\n请手动执行:")
|
290
|
+
print("npm install -g javascript-obfuscator terser csso-cli clean-css-cli")
|
291
|
+
return False
|
292
|
+
|
293
|
+
def main():
|
294
|
+
"""主函数"""
|
295
|
+
parser = argparse.ArgumentParser(
|
296
|
+
description="极简版代码混淆工具 - 使用现成流行库",
|
297
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
298
|
+
epilog="""
|
299
|
+
使用示例:
|
300
|
+
python easy_obfuscator.py -i ./js
|
301
|
+
python easy_obfuscator.py -i ./ -o ./dist
|
302
|
+
python easy_obfuscator.py -i ./src --install
|
303
|
+
"""
|
304
|
+
)
|
305
|
+
|
306
|
+
parser.add_argument('-i', '--input',
|
307
|
+
help='输入目录路径')
|
308
|
+
|
309
|
+
parser.add_argument('-o', '--output',
|
310
|
+
help='输出目录路径 (默认: 输入目录/obfuscated)')
|
311
|
+
|
312
|
+
parser.add_argument('--install',
|
313
|
+
action='store_true',
|
314
|
+
help='自动安装所需的 npm 工具')
|
315
|
+
|
316
|
+
parser.add_argument('--check',
|
317
|
+
action='store_true',
|
318
|
+
help='检查可用工具')
|
319
|
+
|
320
|
+
parser.add_argument('--version',
|
321
|
+
action='version',
|
322
|
+
version='%(prog)s 3.0.0')
|
323
|
+
|
324
|
+
args = parser.parse_args()
|
325
|
+
|
326
|
+
# 只检查工具
|
327
|
+
if args.check:
|
328
|
+
obfuscator = EasyObfuscator(".", ".")
|
329
|
+
obfuscator.check_tools()
|
330
|
+
return
|
331
|
+
|
332
|
+
# 安装工具
|
333
|
+
if args.install:
|
334
|
+
if install_tools():
|
335
|
+
print("现在可以开始混淆了!")
|
336
|
+
return
|
337
|
+
|
338
|
+
# 如果没有指定输入目录且不是检查/安装模式,则报错
|
339
|
+
if not args.input:
|
340
|
+
print("❌ 请指定输入目录: -i <目录路径>")
|
341
|
+
print("或使用 --check 检查工具,--install 安装工具")
|
342
|
+
return
|
343
|
+
|
344
|
+
# 检查输入目录
|
345
|
+
input_path = Path(args.input)
|
346
|
+
if not input_path.exists():
|
347
|
+
print(f"❌ 输入目录不存在: {input_path}")
|
348
|
+
return
|
349
|
+
|
350
|
+
if not input_path.is_dir():
|
351
|
+
print(f"❌ 输入路径不是目录: {input_path}")
|
352
|
+
return
|
353
|
+
|
354
|
+
# 创建混淆器实例
|
355
|
+
obfuscator = EasyObfuscator(
|
356
|
+
source_dir=str(input_path),
|
357
|
+
output_dir=args.output
|
358
|
+
)
|
359
|
+
|
360
|
+
try:
|
361
|
+
# 检查工具可用性
|
362
|
+
if not obfuscator.check_tools():
|
363
|
+
print("\n💡 尝试运行: python easy_obfuscator.py --install")
|
364
|
+
return
|
365
|
+
|
366
|
+
# 开始处理
|
367
|
+
obfuscator.process_all_files()
|
368
|
+
print("\n🎉 混淆完成!文件已受到保护,可以安全部署。")
|
369
|
+
|
370
|
+
except KeyboardInterrupt:
|
371
|
+
print("\n⚠️ 用户中断操作")
|
372
|
+
except Exception as e:
|
373
|
+
print(f"\n❌ 处理失败: {e}")
|
374
|
+
|
375
|
+
if __name__ == "__main__":
|
376
|
+
main()
|
@@ -1,5 +1,7 @@
|
|
1
1
|
mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
|
2
|
-
mdbq/__version__.py,sha256=
|
2
|
+
mdbq/__version__.py,sha256=kgAHeV5rmBm2NSVTiA-VE9pJX4ZQJV-1Zlkl3EXsWBQ,18
|
3
|
+
mdbq/js/__init__.py,sha256=i-5dOsgWnoqs9DtclORulncneyyNFIBW9qlrgkyfeuc,6
|
4
|
+
mdbq/js/jc.py,sha256=FOc6HOOTJwnoZLZmgmaE1SQo9rUnVhXmefhKMD2MlDA,13229
|
3
5
|
mdbq/log/__init__.py,sha256=Mpbrav0s0ifLL7lVDAuePEi1hJKiSHhxcv1byBKDl5E,15
|
4
6
|
mdbq/log/mylogger.py,sha256=DyBftCMNLe1pTTXsa830pUtDISJxpJHFIradYtE3lFA,26418
|
5
7
|
mdbq/myconf/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
|
@@ -28,7 +30,7 @@ mdbq/route/routes.py,sha256=DHJg0eRNi7TKqhCHuu8ia3vdQ8cTKwrTm6mwDBtNboM,19111
|
|
28
30
|
mdbq/selenium/__init__.py,sha256=AKzeEceqZyvqn2dEDoJSzDQnbuENkJSHAlbHAD0u0ZI,10
|
29
31
|
mdbq/selenium/get_driver.py,sha256=1NTlVUE6QsyjTrVVVqTO2LOnYf578ccFWlWnvIXGtic,20903
|
30
32
|
mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
|
31
|
-
mdbq-4.0.
|
32
|
-
mdbq-4.0.
|
33
|
-
mdbq-4.0.
|
34
|
-
mdbq-4.0.
|
33
|
+
mdbq-4.0.87.dist-info/METADATA,sha256=DABl5p4FqCv3Ib6zAu2KjsT9N-GjFwD3Qtzw1yt0dIw,364
|
34
|
+
mdbq-4.0.87.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
35
|
+
mdbq-4.0.87.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
|
36
|
+
mdbq-4.0.87.dist-info/RECORD,,
|
File without changes
|
File without changes
|