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 CHANGED
@@ -1 +1 @@
1
- VERSION = '4.0.85'
1
+ VERSION = '4.0.87'
mdbq/js/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+
2
+
3
+
4
+ #
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdbq
3
- Version: 4.0.85
3
+ Version: 4.0.87
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -1,5 +1,7 @@
1
1
  mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
2
- mdbq/__version__.py,sha256=fChZ6BK8bD1TI_mQOeH3ZHNk9gTc5c8fI7b7pT11Wxs,18
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.85.dist-info/METADATA,sha256=Loh74bBLIoi8zrbog9-aN_1xUkds8rXsLcZTP00Hnjw,364
32
- mdbq-4.0.85.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- mdbq-4.0.85.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
34
- mdbq-4.0.85.dist-info/RECORD,,
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