xtn-tools-pro 1.0.0.0.4__py3-none-any.whl → 1.0.0.0.6__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.
- xtn_tools_pro/db/MongoDB.py +2 -2
- xtn_tools_pro/db/MysqlDB.py +397 -0
- xtn_tools_pro/proxy/XiaoXiangProxy.py +1 -1
- xtn_tools_pro/tools.py +4 -114
- xtn_tools_pro/tools_flie.py +1 -1
- xtn_tools_pro/utils/__init__.py +10 -0
- xtn_tools_pro/utils/crypto.py +87 -0
- xtn_tools_pro/utils/file_utils.py +42 -0
- xtn_tools_pro/utils/helpers.py +123 -0
- xtn_tools_pro/utils/log.py +192 -0
- xtn_tools_pro/utils/retry.py +57 -0
- xtn_tools_pro/utils/sql.py +159 -0
- xtn_tools_pro/utils/time_utils.py +143 -0
- {xtn_tools_pro-1.0.0.0.4.dist-info → xtn_tools_pro-1.0.0.0.6.dist-info}/METADATA +4 -1
- xtn_tools_pro-1.0.0.0.6.dist-info/RECORD +23 -0
- xtn_tools_pro-1.0.0.0.4.dist-info/RECORD +0 -14
- {xtn_tools_pro-1.0.0.0.4.dist-info → xtn_tools_pro-1.0.0.0.6.dist-info}/LICENSE +0 -0
- {xtn_tools_pro-1.0.0.0.4.dist-info → xtn_tools_pro-1.0.0.0.6.dist-info}/WHEEL +0 -0
- {xtn_tools_pro-1.0.0.0.4.dist-info → xtn_tools_pro-1.0.0.0.6.dist-info}/top_level.txt +0 -0
xtn_tools_pro/db/MongoDB.py
CHANGED
@@ -8,11 +8,11 @@
|
|
8
8
|
# --------------------------------------------------------------------------------------------------
|
9
9
|
# 2024/4/17 xiatn V00.01.000 新建
|
10
10
|
# --------------------------------------------------------------------------------------------------
|
11
|
-
from xtn_tools_pro.tools_time import *
|
12
11
|
from urllib import parse
|
12
|
+
from typing import List, Dict, Optional
|
13
|
+
from xtn_tools_pro.utils.time_utils import *
|
13
14
|
from pymongo import MongoClient as _MongoClient
|
14
15
|
from pymongo.database import Database as _Database
|
15
|
-
from typing import List, Dict, Optional
|
16
16
|
from pymongo.collection import Collection as _Collection
|
17
17
|
from pymongo.errors import DuplicateKeyError, BulkWriteError
|
18
18
|
|
@@ -0,0 +1,397 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# 说明:
|
5
|
+
# 程序说明xxxxxxxxxxxxxxxxxxx
|
6
|
+
# History:
|
7
|
+
# Date Author Version Modification
|
8
|
+
# --------------------------------------------------------------------------------------------------
|
9
|
+
# 2024/5/11 xiatn V00.01.000 新建
|
10
|
+
# --------------------------------------------------------------------------------------------------
|
11
|
+
import json
|
12
|
+
import pymysql
|
13
|
+
import datetime
|
14
|
+
from pymysql import err
|
15
|
+
from urllib import parse
|
16
|
+
from pymysql import cursors
|
17
|
+
from typing import List, Dict
|
18
|
+
from dbutils.pooled_db import PooledDB
|
19
|
+
from xtn_tools_pro.utils.log import Log
|
20
|
+
from xtn_tools_pro.utils.sql import get_insert_sql, get_insert_batch_sql, get_update_sql
|
21
|
+
|
22
|
+
log = Log(name="MysqlDB", color=True)
|
23
|
+
|
24
|
+
|
25
|
+
def auto_retry(func):
|
26
|
+
def wapper(*args, **kwargs):
|
27
|
+
for i in range(3):
|
28
|
+
try:
|
29
|
+
return func(*args, **kwargs)
|
30
|
+
except (err.InterfaceError, err.OperationalError) as e:
|
31
|
+
log.error(
|
32
|
+
"""
|
33
|
+
error:%s
|
34
|
+
sql: %s
|
35
|
+
"""
|
36
|
+
% (e, kwargs.get("sql") or args[1])
|
37
|
+
)
|
38
|
+
|
39
|
+
return wapper
|
40
|
+
|
41
|
+
|
42
|
+
class MysqlDBPro:
|
43
|
+
def __init__(self, ip, port, db, user_name, user_pass, **kwargs):
|
44
|
+
try:
|
45
|
+
self.connect_pool = PooledDB(
|
46
|
+
creator=pymysql, # 指定数据库连接的创建方法,这里使用的是pymysql作为创建方法
|
47
|
+
mincached=1, # 连接池中空闲连接的初始数量
|
48
|
+
maxcached=100, # 连接池中空闲连接的最大数量
|
49
|
+
maxconnections=100, # 连接池允许的最大连接数
|
50
|
+
blocking=True, # 当连接池达到最大连接数时,是否阻塞等待连接释放
|
51
|
+
ping=7, # 连接池中的连接在重新使用之前,是否需要进行ping操作来验证连接的有效性,这里的7是一个时间间隔,表示每隔7秒会对连接进行一次ping操作
|
52
|
+
host=ip, # 数据库主机的IP地址
|
53
|
+
port=port, # 数据库的端口号
|
54
|
+
user=user_name, # 连接数据库的用户名
|
55
|
+
passwd=user_pass, # 连接数据库的密码
|
56
|
+
db=db, # 连接的数据库名
|
57
|
+
charset="utf8mb4", # 连接数据库时使用的字符编码
|
58
|
+
cursorclass=cursors.SSCursor, # 指定使用的游标类,这里使用的是cursors.SSCursor,该游标类在多线程下大批量插入数据时可以减少内存的使用
|
59
|
+
) # cursorclass 使用服务的游标,默认的在多线程下大批量插入数据会使内存递增
|
60
|
+
|
61
|
+
except Exception as e:
|
62
|
+
log.error(
|
63
|
+
"""
|
64
|
+
连接失败:
|
65
|
+
ip: {}
|
66
|
+
port: {}
|
67
|
+
db: {}
|
68
|
+
user_name: {}
|
69
|
+
user_pass: {}
|
70
|
+
exception: {}
|
71
|
+
""".format(
|
72
|
+
ip, port, db, user_name, user_pass, e
|
73
|
+
)
|
74
|
+
)
|
75
|
+
else:
|
76
|
+
log.debug("连接到mysql数据库 %s : %s" % (ip, db))
|
77
|
+
|
78
|
+
@classmethod
|
79
|
+
def from_url(cls, url, **kwargs):
|
80
|
+
"""
|
81
|
+
|
82
|
+
Args:
|
83
|
+
url: mysql://username:password@ip:port/db?charset=utf8mb4
|
84
|
+
url: mysql://username:password@127.0.0.1:port/db?charset=utf8mb4
|
85
|
+
**kwargs:
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
|
89
|
+
"""
|
90
|
+
url_parsed = parse.urlparse(url)
|
91
|
+
|
92
|
+
db_type = url_parsed.scheme.strip()
|
93
|
+
if db_type != "mysql":
|
94
|
+
raise Exception(
|
95
|
+
"url error, expect mysql://username:ip:port/db?charset=utf8mb4, but get {}".format(
|
96
|
+
url
|
97
|
+
)
|
98
|
+
)
|
99
|
+
|
100
|
+
connect_params = {
|
101
|
+
"ip": url_parsed.hostname.strip(),
|
102
|
+
"port": url_parsed.port,
|
103
|
+
"user_name": url_parsed.username.strip(),
|
104
|
+
"user_pass": url_parsed.password.strip(),
|
105
|
+
"db": url_parsed.path.strip("/").strip(),
|
106
|
+
}
|
107
|
+
|
108
|
+
connect_params.update(kwargs)
|
109
|
+
|
110
|
+
return cls(**connect_params)
|
111
|
+
|
112
|
+
@staticmethod
|
113
|
+
def unescape_string(value):
|
114
|
+
if not isinstance(value, str):
|
115
|
+
return value
|
116
|
+
value = value.replace("\\0", "\0")
|
117
|
+
value = value.replace("\\\\", "\\")
|
118
|
+
value = value.replace("\\n", "\n")
|
119
|
+
value = value.replace("\\r", "\r")
|
120
|
+
value = value.replace("\\Z", "\032")
|
121
|
+
value = value.replace('\\"', '"')
|
122
|
+
value = value.replace("\\'", "'")
|
123
|
+
return value
|
124
|
+
|
125
|
+
def get_connection(self):
|
126
|
+
conn = self.connect_pool.connection(shareable=False)
|
127
|
+
# cursor = conn.cursor(cursors.SSCursor)
|
128
|
+
cursor = conn.cursor()
|
129
|
+
|
130
|
+
return conn, cursor
|
131
|
+
|
132
|
+
def close_connection(self, conn, cursor):
|
133
|
+
"""
|
134
|
+
关闭数据库连接和游标对象
|
135
|
+
:param conn:
|
136
|
+
:param cursor:
|
137
|
+
:return:
|
138
|
+
"""
|
139
|
+
if conn:
|
140
|
+
conn.close()
|
141
|
+
if cursor:
|
142
|
+
cursor.close()
|
143
|
+
|
144
|
+
def execute(self, sql):
|
145
|
+
"""
|
146
|
+
执行sql
|
147
|
+
:param sql:
|
148
|
+
:return:
|
149
|
+
"""
|
150
|
+
conn, cursor = None, None
|
151
|
+
try:
|
152
|
+
conn, cursor = self.get_connection()
|
153
|
+
cursor.execute(sql)
|
154
|
+
conn.commit()
|
155
|
+
except Exception as e:
|
156
|
+
log.error(
|
157
|
+
"""
|
158
|
+
error:%s
|
159
|
+
sql: %s
|
160
|
+
"""
|
161
|
+
% (e, sql)
|
162
|
+
)
|
163
|
+
return False
|
164
|
+
else:
|
165
|
+
return True
|
166
|
+
finally:
|
167
|
+
self.close_connection(conn, cursor)
|
168
|
+
|
169
|
+
def add(self, sql, exception_callfunc=None):
|
170
|
+
"""
|
171
|
+
单条 传入sql执行插入语句
|
172
|
+
:param sql: sql
|
173
|
+
:param exception_callfunc: 异常回调函数
|
174
|
+
:return: 添加行数
|
175
|
+
"""
|
176
|
+
affect_count = None
|
177
|
+
conn, cursor = None, None
|
178
|
+
|
179
|
+
try:
|
180
|
+
conn, cursor = self.get_connection()
|
181
|
+
affect_count = cursor.execute(sql)
|
182
|
+
conn.commit()
|
183
|
+
|
184
|
+
except Exception as e:
|
185
|
+
log.error(
|
186
|
+
"""
|
187
|
+
error:%s
|
188
|
+
sql: %s
|
189
|
+
"""
|
190
|
+
% (e, sql)
|
191
|
+
)
|
192
|
+
if exception_callfunc:
|
193
|
+
exception_callfunc(e)
|
194
|
+
finally:
|
195
|
+
self.close_connection(conn, cursor)
|
196
|
+
|
197
|
+
return affect_count
|
198
|
+
|
199
|
+
def add_smart(self, table, data: Dict, **kwargs):
|
200
|
+
"""
|
201
|
+
单条 添加数据, 直接传递json格式的数据,不用拼sql
|
202
|
+
:param table: 表
|
203
|
+
:param data: 字典 {"xxx":"xxx"}
|
204
|
+
:param kwargs:
|
205
|
+
:return: 添加行数
|
206
|
+
"""
|
207
|
+
sql = get_insert_sql(table, data, **kwargs)
|
208
|
+
return self.add(sql)
|
209
|
+
|
210
|
+
def add_batch(self, sql, datas: List[Dict]):
|
211
|
+
"""
|
212
|
+
批量 添加数据
|
213
|
+
建议配合 get_insert_batch_sql() 生成sql
|
214
|
+
get_insert_batch_sql("user_copy1", [{"auth": 2, "id": "9", "email": "999"}]
|
215
|
+
:param sql:
|
216
|
+
insert ignore into `表` (字段1,字段2) values (%s, %s)
|
217
|
+
insert into `表` (`字段1`,`字段2`,`字段3`) values (%s, %s, %s)
|
218
|
+
这里有多少个字段,values后面就要有多少个%s
|
219
|
+
:param datas: 列表 [{}, {}, {}]
|
220
|
+
:return:
|
221
|
+
"""
|
222
|
+
affect_count = None
|
223
|
+
conn, cursor = None, None
|
224
|
+
try:
|
225
|
+
conn, cursor = self.get_connection()
|
226
|
+
affect_count = cursor.executemany(sql, datas)
|
227
|
+
conn.commit()
|
228
|
+
|
229
|
+
except Exception as e:
|
230
|
+
log.error(
|
231
|
+
"""
|
232
|
+
error:%s
|
233
|
+
sql: %s
|
234
|
+
"""
|
235
|
+
% (e, sql)
|
236
|
+
)
|
237
|
+
finally:
|
238
|
+
self.close_connection(conn, cursor)
|
239
|
+
|
240
|
+
return affect_count
|
241
|
+
|
242
|
+
def add_batch_smart(self, table, datas: List[Dict], **kwargs):
|
243
|
+
"""
|
244
|
+
批量 直接传递list格式的数据,不用拼sql
|
245
|
+
:param table: 表名
|
246
|
+
:param datas: 列表 [{}, {}, {}]
|
247
|
+
:param kwargs:
|
248
|
+
:return: 添加行数
|
249
|
+
"""
|
250
|
+
sql, datas = get_insert_batch_sql(table, datas, **kwargs)
|
251
|
+
return self.add_batch(sql, datas)
|
252
|
+
|
253
|
+
def update(self, sql):
|
254
|
+
"""
|
255
|
+
更新
|
256
|
+
:param sql:
|
257
|
+
:return:
|
258
|
+
"""
|
259
|
+
conn, cursor = None, None
|
260
|
+
|
261
|
+
try:
|
262
|
+
conn, cursor = self.get_connection()
|
263
|
+
cursor.execute(sql)
|
264
|
+
conn.commit()
|
265
|
+
except Exception as e:
|
266
|
+
log.error(
|
267
|
+
"""
|
268
|
+
error:%s
|
269
|
+
sql: %s
|
270
|
+
"""
|
271
|
+
% (e, sql)
|
272
|
+
)
|
273
|
+
return False
|
274
|
+
else:
|
275
|
+
return True
|
276
|
+
finally:
|
277
|
+
self.close_connection(conn, cursor)
|
278
|
+
|
279
|
+
def update_smart(self, table, data: Dict, condition):
|
280
|
+
"""
|
281
|
+
更新 无需拼sql
|
282
|
+
:param table: 表名
|
283
|
+
:param data: 数据 {"xxx":"xxx"}
|
284
|
+
:param condition: 更新条件 where后面的条件,如 condition='status=1'
|
285
|
+
:return:
|
286
|
+
"""
|
287
|
+
sql = get_update_sql(table, data, condition)
|
288
|
+
return self.update(sql)
|
289
|
+
|
290
|
+
def delete(self, sql):
|
291
|
+
"""
|
292
|
+
删除
|
293
|
+
:param sql:
|
294
|
+
:return:
|
295
|
+
"""
|
296
|
+
conn, cursor = None, None
|
297
|
+
try:
|
298
|
+
conn, cursor = self.get_connection()
|
299
|
+
cursor.execute(sql)
|
300
|
+
conn.commit()
|
301
|
+
except Exception as e:
|
302
|
+
log.error(
|
303
|
+
"""
|
304
|
+
error:%s
|
305
|
+
sql: %s
|
306
|
+
"""
|
307
|
+
% (e, sql)
|
308
|
+
)
|
309
|
+
return False
|
310
|
+
else:
|
311
|
+
return True
|
312
|
+
finally:
|
313
|
+
self.close_connection(conn, cursor)
|
314
|
+
|
315
|
+
@auto_retry
|
316
|
+
def find(self, sql, limit=0, to_json=False, conver_col=True):
|
317
|
+
"""
|
318
|
+
查询
|
319
|
+
无数据: 返回None或[] 取决于limit
|
320
|
+
有数据: 如果limit=1 则返回 一条数据(字段1, 字段2) 其余返回[(字段1, 字段2),(字段1, 字段2)]
|
321
|
+
:param sql:
|
322
|
+
:param limit:
|
323
|
+
:param to_json: 是否将查询结果转为json
|
324
|
+
:param conver_col: 是否处理查询结果,如date类型转字符串,json字符串转成json。仅当to_json=True时生效
|
325
|
+
:return:
|
326
|
+
"""
|
327
|
+
conn, cursor = self.get_connection()
|
328
|
+
|
329
|
+
cursor.execute(sql)
|
330
|
+
|
331
|
+
if limit == 1:
|
332
|
+
result = cursor.fetchone() # 全部查出来,截取 不推荐使用
|
333
|
+
elif limit > 1:
|
334
|
+
result = cursor.fetchmany(limit) # 全部查出来,截取 不推荐使用
|
335
|
+
else:
|
336
|
+
result = cursor.fetchall()
|
337
|
+
|
338
|
+
if result is None:
|
339
|
+
return result
|
340
|
+
|
341
|
+
if to_json:
|
342
|
+
columns = [i[0] for i in cursor.description]
|
343
|
+
|
344
|
+
# 处理数据
|
345
|
+
def convert(col):
|
346
|
+
if isinstance(col, (datetime.date, datetime.time)):
|
347
|
+
return str(col)
|
348
|
+
elif isinstance(col, str) and (
|
349
|
+
col.startswith("{") or col.startswith("[")
|
350
|
+
):
|
351
|
+
try:
|
352
|
+
# col = self.unescape_string(col)
|
353
|
+
return json.loads(col)
|
354
|
+
except:
|
355
|
+
return col
|
356
|
+
else:
|
357
|
+
# col = self.unescape_string(col)
|
358
|
+
return col
|
359
|
+
|
360
|
+
if limit == 1:
|
361
|
+
if conver_col:
|
362
|
+
result = [convert(col) for col in result]
|
363
|
+
result = dict(zip(columns, result))
|
364
|
+
else:
|
365
|
+
if conver_col:
|
366
|
+
result = [[convert(col) for col in row] for row in result]
|
367
|
+
result = [dict(zip(columns, r)) for r in result]
|
368
|
+
|
369
|
+
self.close_connection(conn, cursor)
|
370
|
+
|
371
|
+
return result
|
372
|
+
|
373
|
+
|
374
|
+
if __name__ == '__main__':
|
375
|
+
pass
|
376
|
+
# mysql_db = MysqlDBPro(ip="127.0.0.1", port=3306, db="xtn_home", user_name="root", user_pass="xtn-kk")
|
377
|
+
# sql = """insert into `user_copy1` (`id`, `email`, `auth`) values (8, '888', 2)"""
|
378
|
+
# print(mysql_db.add(sql))
|
379
|
+
# print(mysql_db.add_smart("user_copy1", {"id": "9", "email": "999"}))
|
380
|
+
# sql = "insert ignore into `user_copy1` (`id`,`email`) values (%s, %s)"
|
381
|
+
# sql, datas = get_insert_batch_sql("user_copy1", [{"auth": 2, "id": "9", "email": "999"}])
|
382
|
+
# print(mysql_db.add_batch(sql, datas))
|
383
|
+
|
384
|
+
# print(mysql_db.add_batch_smart("user_copy1", [{"auth": 2, "id": "9", "email": "999"},
|
385
|
+
# {"auth": 2, "id": "10", "email": "10"},
|
386
|
+
# {"id": "11", "auth": 1, "email": "11"},
|
387
|
+
# {"auth": 2, "id": "12", "email": "12"}]))
|
388
|
+
|
389
|
+
# 更新案例
|
390
|
+
# sql = "UPDATE user_copy1 SET status = '2', auth = 1 WHERE id = 2;"
|
391
|
+
# print(mysql_db.update(sql))
|
392
|
+
|
393
|
+
# 更新 无需拼接sql案例
|
394
|
+
# print(mysql_db.update_smart("user_copy1", {"email": "123", "status": 4}, "id=22"))
|
395
|
+
|
396
|
+
# 查询案例
|
397
|
+
# print(mysql_db.find("select * from user_copy1 where id=11",1,True))
|
@@ -10,7 +10,7 @@
|
|
10
10
|
# --------------------------------------------------------------------------------------------------
|
11
11
|
import requests, time, random
|
12
12
|
from xtn_tools_pro.db.RedisDB import RedisDBPro
|
13
|
-
from xtn_tools_pro.
|
13
|
+
from xtn_tools_pro.utils.time_utils import get_time_now_timestamp, get_time_now_day59_timestamp
|
14
14
|
|
15
15
|
import warnings
|
16
16
|
from urllib3.exceptions import InsecureRequestWarning
|
xtn_tools_pro/tools.py
CHANGED
@@ -8,125 +8,15 @@
|
|
8
8
|
# --------------------------------------------------------------------------------------------------
|
9
9
|
# 2024/4/17 xiatn V00.01.000 新建
|
10
10
|
# --------------------------------------------------------------------------------------------------
|
11
|
-
import hashlib, json, math
|
12
|
-
from urllib.parse import urlencode
|
13
11
|
|
14
12
|
|
15
|
-
def
|
13
|
+
def split_image(img):
|
16
14
|
"""
|
17
|
-
|
18
|
-
:param
|
19
|
-
:param is_upper: 是否转大写 默认False
|
15
|
+
切割图片
|
16
|
+
:param img:
|
20
17
|
:return:
|
21
18
|
"""
|
22
|
-
|
23
|
-
m = hashlib.md5(s.encode()) # 长度是32
|
24
|
-
if is_upper:
|
25
|
-
return m.hexdigest().upper()
|
26
|
-
return m.hexdigest()
|
27
|
-
|
28
|
-
|
29
|
-
def get_md5_16(s, is_upper=False):
|
30
|
-
"""
|
31
|
-
获取文本的md5值 16位
|
32
|
-
:param s: 文本
|
33
|
-
:param is_upper: 是否转大写 默认False
|
34
|
-
:return:
|
35
|
-
"""
|
36
|
-
result = get_md5_32(s, is_upper)
|
37
|
-
return result[8:24]
|
38
|
-
|
39
|
-
|
40
|
-
def get_binary_content_md5_32(content, is_upper=False):
|
41
|
-
"""
|
42
|
-
二进制内容md5 例如图片
|
43
|
-
:param content: 二进制内容
|
44
|
-
:param is_upper: 是否转大写 默认False
|
45
|
-
:return:
|
46
|
-
"""
|
47
|
-
md5_hash = hashlib.md5(content)
|
48
|
-
md5_hexdigest = md5_hash.hexdigest()
|
49
|
-
if is_upper:
|
50
|
-
return md5_hexdigest.upper()
|
51
|
-
return md5_hexdigest
|
52
|
-
|
53
|
-
|
54
|
-
def get_binary_content_md5_16(content, is_upper=False):
|
55
|
-
"""
|
56
|
-
二进制内容md5 例如图片
|
57
|
-
:param content: 二进制内容
|
58
|
-
:param is_upper: 是否转大写 默认False
|
59
|
-
:return:
|
60
|
-
"""
|
61
|
-
result = get_binary_content_md5_32(content, is_upper)
|
62
|
-
return result[8:24]
|
63
|
-
|
64
|
-
|
65
|
-
def get_file_md5_32(file_path, is_upper=False):
|
66
|
-
"""
|
67
|
-
获取文件md5值
|
68
|
-
:param file_path: 文件路径
|
69
|
-
:param is_upper: 是否转大写 默认False
|
70
|
-
:return:
|
71
|
-
"""
|
72
|
-
with open(file_path, 'rb') as file:
|
73
|
-
data = file.read()
|
74
|
-
md5_hash = hashlib.md5(data).hexdigest()
|
75
|
-
if is_upper:
|
76
|
-
return md5_hash.upper()
|
77
|
-
return md5_hash
|
78
|
-
|
79
|
-
|
80
|
-
def get_file_md5_16(file_path, is_upper=False):
|
81
|
-
"""
|
82
|
-
获取文件md5值
|
83
|
-
:param file_path: 文件路径
|
84
|
-
:param is_upper: 是否转大写 默认False
|
85
|
-
:return:
|
86
|
-
"""
|
87
|
-
result = get_file_md5_32(file_path, is_upper)
|
88
|
-
return result[8:24]
|
89
|
-
|
90
|
-
|
91
|
-
def get_str_to_json(str_json):
|
92
|
-
"""
|
93
|
-
字符串类型的json格式 转 json
|
94
|
-
:param str_json: 字符串json
|
95
|
-
:return:
|
96
|
-
"""
|
97
|
-
try:
|
98
|
-
new_str_json = str_json.replace("'", '"'). \
|
99
|
-
replace("None", "null").replace("True", "true"). \
|
100
|
-
replace("False", "false")
|
101
|
-
return json.loads(new_str_json)
|
102
|
-
except Exception as e:
|
103
|
-
return {}
|
104
|
-
|
105
|
-
|
106
|
-
def get_build_url_with_params(url, params):
|
107
|
-
"""
|
108
|
-
传入url和params拼接完整的url ->效果 https://wwww.xxxx.com/?xxx1=1&xxx2=2
|
109
|
-
:param url:
|
110
|
-
:param params:
|
111
|
-
:return:
|
112
|
-
"""
|
113
|
-
encoded_params = urlencode(params)
|
114
|
-
full_url = url + "?" + encoded_params
|
115
|
-
return full_url
|
116
|
-
|
117
|
-
|
118
|
-
def get_calculate_total_page(total, limit):
|
119
|
-
"""
|
120
|
-
根据total和limit计算出一共有多少页
|
121
|
-
:param total:
|
122
|
-
:param limit:
|
123
|
-
:return:
|
124
|
-
"""
|
125
|
-
if limit <= 0:
|
126
|
-
return 0
|
127
|
-
# 根据总条数和limit计算总页数
|
128
|
-
total_pages = math.ceil(total / limit)
|
129
|
-
return total_pages
|
19
|
+
pass
|
130
20
|
|
131
21
|
|
132
22
|
if __name__ == '__main__':
|
xtn_tools_pro/tools_flie.py
CHANGED
@@ -38,4 +38,4 @@ def get_file_check_filename(file_name):
|
|
38
38
|
if __name__ == '__main__':
|
39
39
|
pass
|
40
40
|
print(get_file_extension('file/2024-04-19/BOSCH GEX 125-1A/125-1AE砂磨机操作说明书:[1]_jingyan.txt'))
|
41
|
-
print(
|
41
|
+
print(get_file_check_filename('file/2024-04-19/BOSCH GEX 125-1A/125-1AE砂磨机操作说明书:[1]_jingyan.txt'))
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# 说明:
|
5
|
+
# 程序说明xxxxxxxxxxxxxxxxxxx
|
6
|
+
# History:
|
7
|
+
# Date Author Version Modification
|
8
|
+
# --------------------------------------------------------------------------------------------------
|
9
|
+
# 2024/5/12 xiatn V00.01.000 新建
|
10
|
+
# --------------------------------------------------------------------------------------------------
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# 说明:
|
5
|
+
# 加解密、编解码
|
6
|
+
# History:
|
7
|
+
# Date Author Version Modification
|
8
|
+
# --------------------------------------------------------------------------------------------------
|
9
|
+
# 2024/5/13 xiatn V00.01.000 新建
|
10
|
+
# --------------------------------------------------------------------------------------------------
|
11
|
+
import hashlib
|
12
|
+
|
13
|
+
|
14
|
+
def get_md5_32(s, is_upper=False):
|
15
|
+
"""
|
16
|
+
获取文本的md5值 32位
|
17
|
+
:param s: 文本
|
18
|
+
:param is_upper: 是否转大写 默认False
|
19
|
+
:return:
|
20
|
+
"""
|
21
|
+
# s.encode()#变成bytes类型才能加密
|
22
|
+
m = hashlib.md5(s.encode()) # 长度是32
|
23
|
+
if is_upper:
|
24
|
+
return m.hexdigest().upper()
|
25
|
+
return m.hexdigest()
|
26
|
+
|
27
|
+
|
28
|
+
def get_md5_16(s, is_upper=False):
|
29
|
+
"""
|
30
|
+
获取文本的md5值 16位
|
31
|
+
:param s: 文本
|
32
|
+
:param is_upper: 是否转大写 默认False
|
33
|
+
:return:
|
34
|
+
"""
|
35
|
+
result = get_md5_32(s, is_upper)
|
36
|
+
return result[8:24]
|
37
|
+
|
38
|
+
|
39
|
+
def get_binary_content_md5_32(content, is_upper=False):
|
40
|
+
"""
|
41
|
+
二进制内容md5 例如图片
|
42
|
+
:param content: 二进制内容
|
43
|
+
:param is_upper: 是否转大写 默认False
|
44
|
+
:return:
|
45
|
+
"""
|
46
|
+
md5_hash = hashlib.md5(content)
|
47
|
+
md5_hexdigest = md5_hash.hexdigest()
|
48
|
+
if is_upper:
|
49
|
+
return md5_hexdigest.upper()
|
50
|
+
return md5_hexdigest
|
51
|
+
|
52
|
+
|
53
|
+
def get_binary_content_md5_16(content, is_upper=False):
|
54
|
+
"""
|
55
|
+
二进制内容md5 例如图片
|
56
|
+
:param content: 二进制内容
|
57
|
+
:param is_upper: 是否转大写 默认False
|
58
|
+
:return:
|
59
|
+
"""
|
60
|
+
result = get_binary_content_md5_32(content, is_upper)
|
61
|
+
return result[8:24]
|
62
|
+
|
63
|
+
|
64
|
+
def get_file_md5_32(file_path, is_upper=False):
|
65
|
+
"""
|
66
|
+
获取文件md5值
|
67
|
+
:param file_path: 文件路径
|
68
|
+
:param is_upper: 是否转大写 默认False
|
69
|
+
:return:
|
70
|
+
"""
|
71
|
+
with open(file_path, 'rb') as file:
|
72
|
+
data = file.read()
|
73
|
+
md5_hash = hashlib.md5(data).hexdigest()
|
74
|
+
if is_upper:
|
75
|
+
return md5_hash.upper()
|
76
|
+
return md5_hash
|
77
|
+
|
78
|
+
|
79
|
+
def get_file_md5_16(file_path, is_upper=False):
|
80
|
+
"""
|
81
|
+
获取文件md5值
|
82
|
+
:param file_path: 文件路径
|
83
|
+
:param is_upper: 是否转大写 默认False
|
84
|
+
:return:
|
85
|
+
"""
|
86
|
+
result = get_file_md5_32(file_path, is_upper)
|
87
|
+
return result[8:24]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# 说明:
|
5
|
+
# 文件
|
6
|
+
# History:
|
7
|
+
# Date Author Version Modification
|
8
|
+
# --------------------------------------------------------------------------------------------------
|
9
|
+
# 2024/5/13 xiatn V00.01.000 新建
|
10
|
+
# --------------------------------------------------------------------------------------------------
|
11
|
+
import os
|
12
|
+
import re
|
13
|
+
|
14
|
+
|
15
|
+
def get_file_extension(file_name):
|
16
|
+
"""
|
17
|
+
根据文件名获取文件扩展名/后缀名
|
18
|
+
:param file_name: 文件名称
|
19
|
+
:return:
|
20
|
+
"""
|
21
|
+
_, file_extension = os.path.splitext(file_name)
|
22
|
+
return file_extension
|
23
|
+
|
24
|
+
|
25
|
+
def get_file_check_filename(file_name):
|
26
|
+
"""
|
27
|
+
传入文件名返回一个合法的文件名 会替换掉一些特殊符号 常用于爬虫写文件时文件名中带有特殊符号的情况...
|
28
|
+
:param filename: 文件名
|
29
|
+
:return:
|
30
|
+
"""
|
31
|
+
file_extension = get_file_extension(file_name)
|
32
|
+
# 删除非法字符
|
33
|
+
sanitized_filename = re.sub(r'[\/:*?"<>|]', '', file_name)
|
34
|
+
max_length = 255 # 操作系统限制文件名的最大长度为255个
|
35
|
+
sanitized_filename = sanitized_filename[:max_length]
|
36
|
+
return sanitized_filename
|
37
|
+
|
38
|
+
|
39
|
+
if __name__ == '__main__':
|
40
|
+
pass
|
41
|
+
print(get_file_extension('file/2024-04-19/BOSCH GEX 125-1A/125-1AE砂磨机操作说明书:[1]_jingyan.txt'))
|
42
|
+
print(get_file_check_filename('file/2024-04-19/BOSCH GEX 125-1A/125-1AE砂磨机操作说明书:[1]_jingyan.txt'))
|