lazysdk 0.1.89__tar.gz → 0.1.122__tar.gz
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.
- {lazysdk-0.1.89 → lazysdk-0.1.122}/PKG-INFO +12 -3
- lazysdk-0.1.122/lazysdk/lazy_header.py +34 -0
- lazysdk-0.1.122/lazysdk/lazy_input.py +35 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazydict.py +49 -1
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyexcel.py +35 -3
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyfile.py +6 -2
- lazysdk-0.1.122/lazysdk/lazyhash.py +60 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyhtml.py +24 -3
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyid.py +2 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyip.py +4 -1
- lazysdk-0.1.122/lazysdk/lazyjson.py +54 -0
- lazysdk-0.1.122/lazysdk/lazylist.py +43 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazypath.py +13 -3
- lazysdk-0.1.122/lazysdk/lazyre.py +40 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyrequests.py +12 -6
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazytext.py +3 -1
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazytime.py +129 -10
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazywebhook.py +83 -9
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk.egg-info/PKG-INFO +12 -3
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk.egg-info/SOURCES.txt +5 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk.egg-info/requires.txt +1 -1
- {lazysdk-0.1.89 → lazysdk-0.1.122}/setup.py +2 -2
- lazysdk-0.1.89/lazysdk/lazyjson.py +0 -33
- {lazysdk-0.1.89 → lazysdk-0.1.122}/LICENSE +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/README.md +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/__init__.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyCrypto.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazy_id_card.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazybase64.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazycache.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazychromedriver.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazydecode.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyenv.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyflask.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyinfo.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazym3u8.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazymd5.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyprocess.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyproxies.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyrandom.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyredis.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyua.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyurl.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazywifi.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/lazyxml.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk/showdata.py +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk.egg-info/dependency_links.txt +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/lazysdk.egg-info/top_level.txt +0 -0
- {lazysdk-0.1.89 → lazysdk-0.1.122}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: lazysdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.122
|
|
4
4
|
Summary: 基于Python的懒人包
|
|
5
5
|
Home-page: https://gitee.com/ZeroSeeker/lazysdk
|
|
6
6
|
Author: ZeroSeeker
|
|
@@ -23,7 +23,16 @@ Requires-Dist: filetype==1.2.0
|
|
|
23
23
|
Requires-Dist: netifaces==0.11.0
|
|
24
24
|
Requires-Dist: user_agents==2.2.0
|
|
25
25
|
Requires-Dist: rich>=13.5.2
|
|
26
|
-
Requires-Dist: urllib3==1.
|
|
26
|
+
Requires-Dist: urllib3==1.26.9
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: author-email
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: description-content-type
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: summary
|
|
27
36
|
|
|
28
37
|
# lazysdk
|
|
29
38
|

|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding = utf8
|
|
3
|
+
from lazysdk import showdata
|
|
4
|
+
|
|
5
|
+
def convert2dict(header_str: str):
|
|
6
|
+
header_temp = header_str.split('\n')
|
|
7
|
+
header_dict = dict()
|
|
8
|
+
for each in header_temp:
|
|
9
|
+
if len(each) == 0:
|
|
10
|
+
continue
|
|
11
|
+
else:
|
|
12
|
+
each_split = each.split(': ')
|
|
13
|
+
header_dict[each_split[0]] = each_split[1]
|
|
14
|
+
return header_dict
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_lines():
|
|
18
|
+
lines = []
|
|
19
|
+
print("请输入多行数据,以空行结束:")
|
|
20
|
+
while True:
|
|
21
|
+
line = input()
|
|
22
|
+
if line:
|
|
23
|
+
lines.append(line)
|
|
24
|
+
else:
|
|
25
|
+
break
|
|
26
|
+
|
|
27
|
+
print("您输入的多行数据是:")
|
|
28
|
+
return "\n".join(lines)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if __name__ == '__main__':
|
|
32
|
+
test_lines = get_lines()
|
|
33
|
+
showdata.show_dict(convert2dict(header_str=test_lines))
|
|
34
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding = utf8
|
|
3
|
+
from lazysdk import showdata
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def convert2dict(header_str: str):
|
|
7
|
+
header_temp = header_str.split('\n')
|
|
8
|
+
header_dict = dict()
|
|
9
|
+
for each in header_temp:
|
|
10
|
+
if len(each) == 0:
|
|
11
|
+
continue
|
|
12
|
+
else:
|
|
13
|
+
each_split = each.split(': ')
|
|
14
|
+
header_dict[each_split[0]] = each_split[1]
|
|
15
|
+
return header_dict
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_lines():
|
|
19
|
+
lines = []
|
|
20
|
+
print("请输入多行数据,以空行结束:")
|
|
21
|
+
while True:
|
|
22
|
+
line = input()
|
|
23
|
+
if line:
|
|
24
|
+
lines.append(line)
|
|
25
|
+
else:
|
|
26
|
+
break
|
|
27
|
+
|
|
28
|
+
print("您输入的多行数据是:")
|
|
29
|
+
return "\n".join(lines)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if __name__ == '__main__':
|
|
33
|
+
test_lines = get_lines()
|
|
34
|
+
showdata.show_dict(convert2dict(header_str=test_lines))
|
|
35
|
+
|
|
@@ -245,7 +245,7 @@ def list_dict_filter(
|
|
|
245
245
|
从[{},{}]中按照某个key-value条件筛选出符合条件的记录
|
|
246
246
|
"""
|
|
247
247
|
list_out = list(filter(lambda x: x[filter_key] == filter_value, list_in))
|
|
248
|
-
return list_out
|
|
248
|
+
return copy.deepcopy(list_out)
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
def key_max_value(
|
|
@@ -286,3 +286,51 @@ def key_min_value(
|
|
|
286
286
|
else:
|
|
287
287
|
continue
|
|
288
288
|
return min_value
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def get_value_list(
|
|
292
|
+
list_in: list,
|
|
293
|
+
key,
|
|
294
|
+
deepcopy: bool = True,
|
|
295
|
+
value_type: type = None
|
|
296
|
+
):
|
|
297
|
+
"""
|
|
298
|
+
提取list嵌套的字典中某个key的值列表
|
|
299
|
+
:param value_type: 将值格式化为指定的类型,例如str
|
|
300
|
+
"""
|
|
301
|
+
res = []
|
|
302
|
+
if list_in:
|
|
303
|
+
for each in list_in:
|
|
304
|
+
if isinstance(each, dict):
|
|
305
|
+
each_value = each.get(key)
|
|
306
|
+
if each_value and value_type is None:
|
|
307
|
+
res.append(each_value)
|
|
308
|
+
elif each_value and value_type is not None:
|
|
309
|
+
if isinstance(each_value, value_type):
|
|
310
|
+
res.append(each_value)
|
|
311
|
+
else:
|
|
312
|
+
res.append(value_type(each_value))
|
|
313
|
+
else:
|
|
314
|
+
continue
|
|
315
|
+
else:
|
|
316
|
+
continue
|
|
317
|
+
if deepcopy:
|
|
318
|
+
return copy.deepcopy(res)
|
|
319
|
+
else:
|
|
320
|
+
return res
|
|
321
|
+
else:
|
|
322
|
+
return []
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
if __name__ == '__main__':
|
|
326
|
+
res = get_value_list(
|
|
327
|
+
list_in = [
|
|
328
|
+
{"a": "1"},
|
|
329
|
+
{"a": "2"},
|
|
330
|
+
{"a": None},
|
|
331
|
+
],
|
|
332
|
+
key = "a",
|
|
333
|
+
value_type = int
|
|
334
|
+
|
|
335
|
+
)
|
|
336
|
+
print(res)
|
|
@@ -233,7 +233,10 @@ def save_xlsx(
|
|
|
233
233
|
datetime_cols: list = None,
|
|
234
234
|
num_cols: list = None,
|
|
235
235
|
col_name_dict: dict = None,
|
|
236
|
-
col_name_sort: list = None
|
|
236
|
+
col_name_sort: list = None,
|
|
237
|
+
cell_number_format: dict = None,
|
|
238
|
+
rank_col: str = None,
|
|
239
|
+
rank_asc: bool = True,
|
|
237
240
|
):
|
|
238
241
|
"""
|
|
239
242
|
如果输入的value是乱序,将重新排序
|
|
@@ -244,14 +247,23 @@ def save_xlsx(
|
|
|
244
247
|
:param num_cols: 数字列列表
|
|
245
248
|
:param col_name_dict: 自定义列名的对照关系,规则为:{'旧名称1':'新名称1', '旧名称2':'新名称2'}
|
|
246
249
|
:param col_name_sort: 自定义列名排序,将按照列表顺序排,如果不在列表中,将随机
|
|
250
|
+
:param cell_number_format: 自定义列数据格式,例如{"a": "0.00", "b": "0.00%"}
|
|
251
|
+
:param rank_col: 排序列名
|
|
252
|
+
:param rank_asc: 排序列是否正序排序,True为按正序排序,False为按倒序排序
|
|
247
253
|
将输出保存后的文件绝对路径
|
|
248
254
|
"""
|
|
255
|
+
# 自动检查添加后缀
|
|
256
|
+
if file.endswith(".xlsx"):
|
|
257
|
+
pass
|
|
258
|
+
else:
|
|
259
|
+
file += ".xlsx"
|
|
260
|
+
|
|
249
261
|
if os.path.isabs(file): # 判断是否为绝对路径
|
|
250
262
|
pass
|
|
251
263
|
else:
|
|
252
264
|
file = os.getcwd() + path_separator + file
|
|
253
265
|
if value is None:
|
|
254
|
-
return
|
|
266
|
+
return file
|
|
255
267
|
else:
|
|
256
268
|
wb = openpyxl.Workbook()
|
|
257
269
|
sheet_index = 0 # sheet序号
|
|
@@ -280,6 +292,19 @@ def save_xlsx(
|
|
|
280
292
|
keys_sort=col_name_sort
|
|
281
293
|
) # 先对要存储的数据做排序对齐
|
|
282
294
|
|
|
295
|
+
# 对值排序
|
|
296
|
+
if rank_col:
|
|
297
|
+
if rank_asc:
|
|
298
|
+
sheet_data_f = lazydict.dict_list_ranker(
|
|
299
|
+
dict_list=sheet_data_f,
|
|
300
|
+
rank_by_list=[[rank_col, 'asc']]
|
|
301
|
+
) # 升序排序
|
|
302
|
+
else:
|
|
303
|
+
sheet_data_f = lazydict.dict_list_ranker(
|
|
304
|
+
dict_list=sheet_data_f,
|
|
305
|
+
rank_by_list=[[rank_col,'desc']]
|
|
306
|
+
) # 降序排序
|
|
307
|
+
|
|
283
308
|
if date_cols is not None:
|
|
284
309
|
for each_sheet_data_f in sheet_data_f:
|
|
285
310
|
# 日期格式化
|
|
@@ -339,11 +364,18 @@ def save_xlsx(
|
|
|
339
364
|
value = each.get(key)
|
|
340
365
|
if isinstance(value, dict) or isinstance(value, list):
|
|
341
366
|
value = json.dumps(value, ensure_ascii=False)
|
|
342
|
-
sheet.cell(
|
|
367
|
+
cell = sheet.cell(
|
|
343
368
|
row=row_num,
|
|
344
369
|
column=col_num,
|
|
345
370
|
value=value
|
|
346
371
|
)
|
|
372
|
+
|
|
373
|
+
# 对单元数据格式化
|
|
374
|
+
if cell_number_format:
|
|
375
|
+
value_cell_number_format = cell_number_format.get(key)
|
|
376
|
+
if value_cell_number_format:
|
|
377
|
+
cell.number_format = value_cell_number_format # 设置单元格数据格式
|
|
378
|
+
|
|
347
379
|
col_num += 1
|
|
348
380
|
row_num += 1
|
|
349
381
|
else:
|
|
@@ -145,7 +145,7 @@ def download(
|
|
|
145
145
|
proxies=proxies,
|
|
146
146
|
verify=verify
|
|
147
147
|
)
|
|
148
|
-
total_length = response.headers.get('content-length') # 文件大小
|
|
148
|
+
total_length = response.headers.get('content-length', '0') # 文件大小
|
|
149
149
|
content_type = response.headers.get('content-type') # 文件类型
|
|
150
150
|
content_disposition = response.headers.get('content-disposition') # 文件名及类型
|
|
151
151
|
filename_default = 'unknown_' + str(time.time())
|
|
@@ -169,7 +169,11 @@ def download(
|
|
|
169
169
|
if filename is None:
|
|
170
170
|
download_file_name = str(filename_default) + "." + str(suffix_name)
|
|
171
171
|
else:
|
|
172
|
-
|
|
172
|
+
if filename.endswith(suffix_name):
|
|
173
|
+
# 如果文件名中已存在后缀名,则不重复添加
|
|
174
|
+
download_file_name = filename
|
|
175
|
+
else:
|
|
176
|
+
download_file_name = str(filename) + "." + str(suffix_name)
|
|
173
177
|
|
|
174
178
|
if path is None:
|
|
175
179
|
path_local = download_file_name
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# coding = utf8
|
|
3
|
+
"""
|
|
4
|
+
@ Author : ZeroSeeker
|
|
5
|
+
@ e-mail : zeroseeker@foxmail.com
|
|
6
|
+
@ GitHub : https://github.com/ZeroSeeker
|
|
7
|
+
@ Gitee : https://gitee.com/ZeroSeeker
|
|
8
|
+
"""
|
|
9
|
+
import requests
|
|
10
|
+
import hashlib
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def md5_file(
|
|
14
|
+
file_path: str = None,
|
|
15
|
+
file_url: str = None
|
|
16
|
+
):
|
|
17
|
+
"""
|
|
18
|
+
计算文件的md5
|
|
19
|
+
:param file_path: 本地文件路径
|
|
20
|
+
:param file_url: 网络文件地址
|
|
21
|
+
"""
|
|
22
|
+
# 文件名不影响md5
|
|
23
|
+
d5 = hashlib.md5()
|
|
24
|
+
if file_path:
|
|
25
|
+
with open(r'%s' % file_path, 'rb') as f:
|
|
26
|
+
while True:
|
|
27
|
+
data = f.read(2048)
|
|
28
|
+
if not data:
|
|
29
|
+
break
|
|
30
|
+
d5.update(data) # update添加时会进行计算
|
|
31
|
+
return d5.hexdigest()
|
|
32
|
+
elif file_url:
|
|
33
|
+
resp = requests.get(file_url)
|
|
34
|
+
d5.update(resp.content) # update添加时会进行计算
|
|
35
|
+
return d5.hexdigest()
|
|
36
|
+
else:
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def md5_str(
|
|
41
|
+
content,
|
|
42
|
+
encoding='UTF-8'
|
|
43
|
+
):
|
|
44
|
+
d5 = hashlib.md5()
|
|
45
|
+
d5.update(content.encode(encoding=encoding)) # update添加时会进行计算
|
|
46
|
+
return d5.hexdigest()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def calculate_sha256(
|
|
50
|
+
content,
|
|
51
|
+
encoding: str='UTF-8'
|
|
52
|
+
):
|
|
53
|
+
"""
|
|
54
|
+
计算文档的SHA-256哈希值
|
|
55
|
+
:param content:
|
|
56
|
+
:param encoding:
|
|
57
|
+
:return: SHA-256哈希字符串
|
|
58
|
+
"""
|
|
59
|
+
# 使用BSON的JSON工具确保一致的序列化
|
|
60
|
+
return hashlib.sha256(content.encode(encoding)).hexdigest()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
1
2
|
|
|
2
3
|
|
|
3
4
|
def make_thead(head_list: list):
|
|
@@ -25,7 +26,9 @@ def make_tbody(body_list: list):
|
|
|
25
26
|
def make_tb(
|
|
26
27
|
data: list,
|
|
27
28
|
border: int = 0,
|
|
28
|
-
beautiful: bool = False
|
|
29
|
+
beautiful: bool = False,
|
|
30
|
+
charset: str = "UTF-8",
|
|
31
|
+
col_name_dict: OrderedDict = None
|
|
29
32
|
) -> str:
|
|
30
33
|
"""
|
|
31
34
|
输入数据为list(dict()),输出生成的html表格代码
|
|
@@ -35,7 +38,17 @@ def make_tb(
|
|
|
35
38
|
for each_data in data:
|
|
36
39
|
key_list.extend(list(each_data.keys()))
|
|
37
40
|
key_list = list(set(key_list))
|
|
38
|
-
|
|
41
|
+
if col_name_dict:
|
|
42
|
+
key_list_new = list()
|
|
43
|
+
for each_key in key_list:
|
|
44
|
+
each_value = col_name_dict.get(each_key)
|
|
45
|
+
if each_value:
|
|
46
|
+
key_list_new.append(each_value)
|
|
47
|
+
else:
|
|
48
|
+
key_list_new.append(each_key)
|
|
49
|
+
thead_list = make_thead(head_list=key_list_new)
|
|
50
|
+
else:
|
|
51
|
+
thead_list = make_thead(head_list=key_list)
|
|
39
52
|
html_head = f"<tr>{''.join(thead_list)}</tr>"
|
|
40
53
|
|
|
41
54
|
html_body = ''
|
|
@@ -50,7 +63,7 @@ def make_tb(
|
|
|
50
63
|
if border:
|
|
51
64
|
table_others += f' border={border}'
|
|
52
65
|
|
|
53
|
-
html_table = f"<table{table_others}>\n{html_head}\n{html_body}</table>"
|
|
66
|
+
html_table = f"""<meta http-equiv="Content-Type" content="text/html;charset={charset}"/>\n<table{table_others}>\n{html_head}\n{html_body}</table>"""
|
|
54
67
|
|
|
55
68
|
if beautiful:
|
|
56
69
|
# 美化输出
|
|
@@ -66,3 +79,11 @@ def make_tb(
|
|
|
66
79
|
html_table = html.tostring(root, pretty_print=True)
|
|
67
80
|
|
|
68
81
|
return html_table
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_text(content: str):
|
|
85
|
+
"""
|
|
86
|
+
从html中提取文本
|
|
87
|
+
"""
|
|
88
|
+
import html2text
|
|
89
|
+
return html2text.html2text(content)
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
@ GitHub : https://github.com/ZeroSeeker
|
|
7
7
|
@ Gitee : https://gitee.com/ZeroSeeker
|
|
8
8
|
"""
|
|
9
|
+
import json
|
|
10
|
+
|
|
9
11
|
import requests
|
|
10
12
|
|
|
11
13
|
|
|
@@ -55,5 +57,6 @@ def get_ip_addr(ip: str):
|
|
|
55
57
|
"""
|
|
56
58
|
api_url = f'http://whois.pconline.com.cn/ipJson.jsp?ip={ip}&json=true'
|
|
57
59
|
response = requests.get(api_url)
|
|
58
|
-
|
|
60
|
+
response_text = response.text.replace("\\", "-")
|
|
61
|
+
addr = json.loads(response_text)['addr']
|
|
59
62
|
return addr
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import decimal
|
|
3
|
+
import datetime
|
|
4
|
+
import base64
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LazyEncoder(json.JSONEncoder):
|
|
8
|
+
def default(self, obj):
|
|
9
|
+
if isinstance(obj, decimal.Decimal):
|
|
10
|
+
return float(obj)
|
|
11
|
+
elif isinstance(obj, datetime.datetime):
|
|
12
|
+
# # 将datetime对象转换为ISO格式字符串
|
|
13
|
+
return obj.isoformat()
|
|
14
|
+
elif isinstance(obj, datetime.date):
|
|
15
|
+
return obj.isoformat()
|
|
16
|
+
elif isinstance(obj, bytes):
|
|
17
|
+
# 将bytes转换为base64编码的字符串
|
|
18
|
+
try:
|
|
19
|
+
# 尝试将bytes解码为UTF-8字符串
|
|
20
|
+
return obj.decode('utf-8')
|
|
21
|
+
except UnicodeDecodeError:
|
|
22
|
+
# 如果UTF-8解码失败,回退到Base64编码
|
|
23
|
+
return base64.b64encode(obj).decode('utf-8')
|
|
24
|
+
# elif isinstance(obj, bson.timestamp.Timestamp):
|
|
25
|
+
# # # 将BSON时间戳转换为其时间表示的ISO格式字符串
|
|
26
|
+
# return obj.as_datetime().isoformat()
|
|
27
|
+
# elif isinstance(obj, bson.objectid.ObjectId):
|
|
28
|
+
# # # 将ObjectId转换为字符串
|
|
29
|
+
# return str(obj)
|
|
30
|
+
return super(LazyEncoder, self).default(obj)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def json2str(
|
|
34
|
+
data: json,
|
|
35
|
+
ensure_ascii: bool = False
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
在将json数据反序列化为str时,会遇到一些格式无法转换
|
|
39
|
+
这里使用识别类型转换转为str
|
|
40
|
+
目前支持类型:
|
|
41
|
+
|
|
42
|
+
对于mongodb返回数据的处理:
|
|
43
|
+
from bson import json_util
|
|
44
|
+
default=json_util.default
|
|
45
|
+
|
|
46
|
+
decimal --> str
|
|
47
|
+
datetime.datetime --> str(%Y-%m-%d %H:%M:%S)
|
|
48
|
+
datetime.date --> str(%Y-%m-%d)
|
|
49
|
+
"""
|
|
50
|
+
return json.dumps(
|
|
51
|
+
data,
|
|
52
|
+
cls=LazyEncoder,
|
|
53
|
+
ensure_ascii=ensure_ascii
|
|
54
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
def split(
|
|
4
|
+
list_in: list,
|
|
5
|
+
split_gap: int
|
|
6
|
+
):
|
|
7
|
+
"""
|
|
8
|
+
将输入的list按照split_gap进行分割
|
|
9
|
+
"""
|
|
10
|
+
list_out = list()
|
|
11
|
+
split_num = 0
|
|
12
|
+
for i in range(len(list_in)):
|
|
13
|
+
if i % split_gap == 0:
|
|
14
|
+
list_out.append(list())
|
|
15
|
+
split_num += 1
|
|
16
|
+
list_out[split_num-1].append(list_in[i])
|
|
17
|
+
return list_out
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def list_difference(
|
|
21
|
+
list_left: list,
|
|
22
|
+
list_right: list,
|
|
23
|
+
keep_sort: bool = False
|
|
24
|
+
):
|
|
25
|
+
"""
|
|
26
|
+
返回两个list的差集,效果等于list_left-list_right,返回无序;
|
|
27
|
+
|
|
28
|
+
在 Python 中,可以使用集合(`set`)的特性来取两个列表的差集。差集是指只在一个集合中出现而在另一个集合中没有的元素。
|
|
29
|
+
使用集合的 `difference()` 方法可以实现列表的差集操作。
|
|
30
|
+
需要注意的是,集合是无序的,因此在结果中元素的顺序可能与原始列表不同。如果需要保留原始列表的顺序,可以使用列表推导式来实现差集操作
|
|
31
|
+
"""
|
|
32
|
+
if keep_sort:
|
|
33
|
+
return [x for x in list_left if x not in list_right] # 返回有序
|
|
34
|
+
else:
|
|
35
|
+
return list(set(list_left).difference(list_right)) # 返回无序
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == '__main__':
|
|
39
|
+
print(list_difference(
|
|
40
|
+
list_left=[4,1,2],
|
|
41
|
+
list_right=[2,3],
|
|
42
|
+
keep_sort=True
|
|
43
|
+
))
|
|
@@ -185,10 +185,13 @@ def delete(path_or_file):
|
|
|
185
185
|
"""
|
|
186
186
|
删除目录/文件
|
|
187
187
|
"""
|
|
188
|
-
if os.path.
|
|
189
|
-
|
|
188
|
+
if os.path.exists(path_or_file):
|
|
189
|
+
if os.path.isdir(path_or_file):
|
|
190
|
+
shutil.rmtree(path_or_file)
|
|
191
|
+
else:
|
|
192
|
+
os.remove(path_or_file)
|
|
190
193
|
else:
|
|
191
|
-
|
|
194
|
+
return
|
|
192
195
|
|
|
193
196
|
|
|
194
197
|
def get_folder_name(dir_or_path: str):
|
|
@@ -219,3 +222,10 @@ def path_rename(
|
|
|
219
222
|
return new_path
|
|
220
223
|
else:
|
|
221
224
|
return
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def exe_path():
|
|
228
|
+
"""
|
|
229
|
+
获取当前脚本的绝对路径
|
|
230
|
+
"""
|
|
231
|
+
return os.path.dirname(os.path.realpath(sys.argv[0]))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def find_between(
|
|
5
|
+
text: str,
|
|
6
|
+
left: str,
|
|
7
|
+
right: str = None,
|
|
8
|
+
until_line_end: bool = False # 是否匹配到行尾
|
|
9
|
+
):
|
|
10
|
+
"""
|
|
11
|
+
找两个之间
|
|
12
|
+
"""
|
|
13
|
+
if until_line_end:
|
|
14
|
+
return re.findall(pattern=f'{left}(.*?){right}$', string=text, flags=re.S)
|
|
15
|
+
else:
|
|
16
|
+
return re.findall(pattern=f'{left}(.*?){right}', string=text, flags=re.S)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def find_all(
|
|
20
|
+
text: str,
|
|
21
|
+
left: str,
|
|
22
|
+
right: str = None,
|
|
23
|
+
until_line_end: bool = False # 是否匹配到行尾
|
|
24
|
+
):
|
|
25
|
+
"""
|
|
26
|
+
找一个之后所有
|
|
27
|
+
"""
|
|
28
|
+
if until_line_end:
|
|
29
|
+
return re.findall(pattern=f'{left}(.*){right}$', string=text, flags=re.S)
|
|
30
|
+
else:
|
|
31
|
+
return re.findall(pattern=f'{left}(.*){right}', string=text, flags=re.S)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def find_chs(
|
|
35
|
+
text: str
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
提取中文,目前不能去掉括号
|
|
39
|
+
"""
|
|
40
|
+
return re.sub(pattern="[A-Za-z0-9\!\%\[\]\,\。\ \']", repl="", string=text)
|
|
@@ -23,7 +23,8 @@ def lazy_requests(
|
|
|
23
23
|
ReadTimeout_retry: bool = True, # 超时重试
|
|
24
24
|
JSONDecodeError_retry: bool = True, # 返回非json类型重试
|
|
25
25
|
ConnectionError_retry: bool = True, # 连接错误重试
|
|
26
|
-
|
|
26
|
+
ChunkedEncodingError_retry: bool = True,
|
|
27
|
+
TooManyRedirects_retry: bool = True,
|
|
27
28
|
|
|
28
29
|
**kwargs
|
|
29
30
|
):
|
|
@@ -53,22 +54,27 @@ def lazy_requests(
|
|
|
53
54
|
except requests.exceptions.ReadTimeout:
|
|
54
55
|
if ReadTimeout_retry is True:
|
|
55
56
|
retry_count += 1
|
|
56
|
-
showlog.warning(f'
|
|
57
|
+
showlog.warning(f'ReadTimeout,将在{retry_delay}秒后重试第{retry_count}次...')
|
|
57
58
|
time.sleep(retry_delay)
|
|
58
59
|
except requests.exceptions.JSONDecodeError:
|
|
59
60
|
if JSONDecodeError_retry is True:
|
|
60
61
|
retry_count += 1
|
|
61
|
-
showlog.warning(f'
|
|
62
|
+
showlog.warning(f'JSONDecodeError,将在{retry_delay}秒后重试第{retry_count}次...')
|
|
62
63
|
time.sleep(retry_delay)
|
|
63
64
|
except requests.exceptions.ConnectionError: # 包含ProxyError
|
|
64
65
|
if ConnectionError_retry is True:
|
|
65
66
|
retry_count += 1
|
|
66
|
-
showlog.warning(f'
|
|
67
|
+
showlog.warning(f'ConnectionError,将在{retry_delay}秒后重试第{retry_count}次...')
|
|
67
68
|
time.sleep(retry_delay)
|
|
68
69
|
except requests.exceptions.ChunkedEncodingError:
|
|
69
|
-
if
|
|
70
|
+
if ChunkedEncodingError_retry is True:
|
|
70
71
|
retry_count += 1
|
|
71
|
-
showlog.warning(f'
|
|
72
|
+
showlog.warning(f'ChunkedEncodingError,将在{retry_delay}秒后重试第{retry_count}次...')
|
|
73
|
+
time.sleep(retry_delay)
|
|
74
|
+
except requests.exceptions.TooManyRedirects:
|
|
75
|
+
if TooManyRedirects_retry is True:
|
|
76
|
+
retry_count += 1
|
|
77
|
+
showlog.warning(f'TooManyRedirects,将在{retry_delay}秒后重试第{retry_count}次...')
|
|
72
78
|
time.sleep(retry_delay)
|
|
73
79
|
if retry_limit == 0:
|
|
74
80
|
break
|
|
@@ -58,7 +58,9 @@ def path_clean(content):
|
|
|
58
58
|
"""
|
|
59
59
|
清除路径前后可能出现的引号
|
|
60
60
|
"""
|
|
61
|
-
if
|
|
61
|
+
if not content:
|
|
62
|
+
return content
|
|
63
|
+
elif content[0] == '"' and content[-1] == '"':
|
|
62
64
|
content = content[1:-1]
|
|
63
65
|
elif content[0] == '“' and content[-1] == '”':
|
|
64
66
|
content = content[1:-1]
|
|
@@ -163,13 +163,17 @@ def get_time(
|
|
|
163
163
|
|
|
164
164
|
|
|
165
165
|
def get_datetime(
|
|
166
|
-
f: str = '%Y-%m-%d %H:%M:%S'
|
|
166
|
+
f: str = '%Y-%m-%d %H:%M:%S',
|
|
167
|
+
utc: bool = False
|
|
167
168
|
):
|
|
168
169
|
"""
|
|
169
170
|
获取当前系统的当前时间格式的时间,精确到秒
|
|
170
171
|
:return: 2018-08-01 14:18:31
|
|
171
172
|
"""
|
|
172
|
-
|
|
173
|
+
if utc:
|
|
174
|
+
inner_now = datetime.datetime.now(pytz.utc)
|
|
175
|
+
else:
|
|
176
|
+
inner_now = datetime.datetime.now()
|
|
173
177
|
data_time = inner_now.strftime(f)
|
|
174
178
|
return data_time
|
|
175
179
|
|
|
@@ -287,20 +291,26 @@ def get_timestamp():
|
|
|
287
291
|
def get_timestamp2datetime(
|
|
288
292
|
timestamp: int = None,
|
|
289
293
|
f: str = "%Y-%m-%d %H:%M:%S",
|
|
290
|
-
zero_to_none: bool = True
|
|
294
|
+
zero_to_none: bool = True,
|
|
295
|
+
utc: bool = False
|
|
291
296
|
):
|
|
292
297
|
"""
|
|
293
298
|
将时间戳转换为datetime时间
|
|
294
299
|
:param timestamp: 同时支持字符串和数字格式
|
|
295
300
|
:param f:
|
|
296
301
|
:param zero_to_none: 将0转换为空值
|
|
302
|
+
:param utc: 是否为utc时间
|
|
297
303
|
:return: 2018-08-01 14:19:53
|
|
298
304
|
"""
|
|
299
305
|
if timestamp is not None:
|
|
300
306
|
if timestamp == 0 and zero_to_none is True:
|
|
301
307
|
return
|
|
302
308
|
else:
|
|
303
|
-
|
|
309
|
+
if utc:
|
|
310
|
+
time_array = time.gmtime(timestamp)
|
|
311
|
+
else:
|
|
312
|
+
time_array = time.localtime(timestamp)
|
|
313
|
+
|
|
304
314
|
date_time = time.strftime(f, time_array)
|
|
305
315
|
return date_time
|
|
306
316
|
else:
|
|
@@ -310,7 +320,8 @@ def get_timestamp2datetime(
|
|
|
310
320
|
def get_timestamp2date(
|
|
311
321
|
timestamp: int = None,
|
|
312
322
|
f: str = "%Y-%m-%d",
|
|
313
|
-
zero_to_none: bool = True
|
|
323
|
+
zero_to_none: bool = True,
|
|
324
|
+
utc: bool = False
|
|
314
325
|
):
|
|
315
326
|
"""
|
|
316
327
|
将时间戳转换为datetime时间
|
|
@@ -318,13 +329,17 @@ def get_timestamp2date(
|
|
|
318
329
|
:param timestamp:
|
|
319
330
|
:param f:
|
|
320
331
|
:param zero_to_none: 将0转换为空值
|
|
332
|
+
:param utc: 是否为utc时间
|
|
321
333
|
:return: 2018-08-01 14:19:53
|
|
322
334
|
"""
|
|
323
335
|
if timestamp is not None:
|
|
324
336
|
if timestamp == 0 and zero_to_none is True:
|
|
325
337
|
return
|
|
326
338
|
else:
|
|
327
|
-
|
|
339
|
+
if utc:
|
|
340
|
+
time_array = time.gmtime(timestamp)
|
|
341
|
+
else:
|
|
342
|
+
time_array = time.localtime(timestamp)
|
|
328
343
|
date_time = time.strftime(f, time_array)
|
|
329
344
|
return date_time
|
|
330
345
|
else:
|
|
@@ -655,6 +670,20 @@ def date_str_list(
|
|
|
655
670
|
return date_list
|
|
656
671
|
|
|
657
672
|
|
|
673
|
+
def get_date_list(
|
|
674
|
+
start_date: str = None,
|
|
675
|
+
end_date: str = None,
|
|
676
|
+
start_days: int = None,
|
|
677
|
+
end_days: int = None
|
|
678
|
+
):
|
|
679
|
+
return date_str_list(
|
|
680
|
+
start_date=start_date,
|
|
681
|
+
end_date=end_date,
|
|
682
|
+
start_days=start_days,
|
|
683
|
+
end_days=end_days
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
|
|
658
687
|
def date_str_list_form_now(
|
|
659
688
|
day_num: int = 1
|
|
660
689
|
):
|
|
@@ -699,14 +728,20 @@ def get_data_date_string(
|
|
|
699
728
|
|
|
700
729
|
def get_date_string(
|
|
701
730
|
days: int = 0,
|
|
702
|
-
f: str = '%Y-%m-%d'
|
|
731
|
+
f: str = '%Y-%m-%d',
|
|
732
|
+
utc: bool = False
|
|
703
733
|
):
|
|
704
734
|
"""
|
|
705
735
|
获取多少天以后的时间字符串
|
|
706
736
|
:param days: 多少天以后,正数向未来计算,负数向历史计算,0是当天
|
|
737
|
+
:param f:
|
|
738
|
+
:param utc:
|
|
707
739
|
:return: 时间字符串(xxxx-xx-xx)
|
|
708
740
|
"""
|
|
709
|
-
|
|
741
|
+
if utc:
|
|
742
|
+
current_time = datetime.datetime.now(tz=pytz.utc)
|
|
743
|
+
else:
|
|
744
|
+
current_time = datetime.datetime.now()
|
|
710
745
|
target_time = current_time + datetime.timedelta(days=days)
|
|
711
746
|
date_str = target_time.strftime(f)
|
|
712
747
|
return date_str
|
|
@@ -890,7 +925,8 @@ def get_file_name(
|
|
|
890
925
|
|
|
891
926
|
|
|
892
927
|
def format_seconds(
|
|
893
|
-
input_seconds
|
|
928
|
+
input_seconds,
|
|
929
|
+
output_type: type = str
|
|
894
930
|
):
|
|
895
931
|
"""
|
|
896
932
|
输入秒数,以时间形式输出
|
|
@@ -902,7 +938,10 @@ def format_seconds(
|
|
|
902
938
|
seconds=seconds, # 秒
|
|
903
939
|
microseconds=microseconds # 微秒
|
|
904
940
|
)
|
|
905
|
-
|
|
941
|
+
if output_type:
|
|
942
|
+
return output_type(format_time)
|
|
943
|
+
else:
|
|
944
|
+
return format_time
|
|
906
945
|
|
|
907
946
|
|
|
908
947
|
def get_gap_days(
|
|
@@ -985,3 +1024,83 @@ def network_timestamp():
|
|
|
985
1024
|
res = requests.get(url=url)
|
|
986
1025
|
net_t = res.json()['data']['t'] # 精确到毫秒的时间戳
|
|
987
1026
|
return int(net_t)
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
def str2datetime(
|
|
1030
|
+
input_str,
|
|
1031
|
+
input_str_format: str = 'YYYYmmdd',
|
|
1032
|
+
output_str_format: str = '%Y-%m-%d %H:%M:%S.%f',
|
|
1033
|
+
):
|
|
1034
|
+
"""
|
|
1035
|
+
将输入的字符串按照既定格式格式化后输出
|
|
1036
|
+
:param input_str: 输入的字符串
|
|
1037
|
+
:param input_str_format: 输入的字符串格式,例如:YYmmdd
|
|
1038
|
+
:param output_str_format: 输出的字符串格式,例如:%Y-%m-%d %H:%M:%S.%f
|
|
1039
|
+
"""
|
|
1040
|
+
year_str = ""
|
|
1041
|
+
month_str = ""
|
|
1042
|
+
day_str = ""
|
|
1043
|
+
hour_str = ""
|
|
1044
|
+
minute_str = ""
|
|
1045
|
+
second_str = ""
|
|
1046
|
+
|
|
1047
|
+
for index in range(len(input_str_format)):
|
|
1048
|
+
index_str = input_str_format[index]
|
|
1049
|
+
if index_str == 'Y':
|
|
1050
|
+
year_str += input_str[index]
|
|
1051
|
+
elif index_str == 'm':
|
|
1052
|
+
month_str += input_str[index]
|
|
1053
|
+
elif index_str == 'd':
|
|
1054
|
+
day_str += input_str[index]
|
|
1055
|
+
elif index_str == 'H':
|
|
1056
|
+
hour_str += input_str[index]
|
|
1057
|
+
elif index_str == 'M':
|
|
1058
|
+
minute_str += input_str[index]
|
|
1059
|
+
elif index_str == 'S':
|
|
1060
|
+
second_str += input_str[index]
|
|
1061
|
+
else:
|
|
1062
|
+
continue
|
|
1063
|
+
|
|
1064
|
+
if year_str:
|
|
1065
|
+
year_int = int(year_str)
|
|
1066
|
+
else:
|
|
1067
|
+
year_int = None
|
|
1068
|
+
|
|
1069
|
+
if month_str:
|
|
1070
|
+
month_int = int(month_str)
|
|
1071
|
+
else:
|
|
1072
|
+
month_int = None
|
|
1073
|
+
|
|
1074
|
+
if day_str:
|
|
1075
|
+
day_int = int(day_str)
|
|
1076
|
+
else:
|
|
1077
|
+
day_int = None
|
|
1078
|
+
|
|
1079
|
+
if hour_str:
|
|
1080
|
+
hour_int = int(hour_str)
|
|
1081
|
+
else:
|
|
1082
|
+
hour_int = 0
|
|
1083
|
+
|
|
1084
|
+
if minute_str:
|
|
1085
|
+
minute_int = int(minute_str)
|
|
1086
|
+
else:
|
|
1087
|
+
minute_int = 0
|
|
1088
|
+
|
|
1089
|
+
if second_str:
|
|
1090
|
+
second_int = int(second_str)
|
|
1091
|
+
else:
|
|
1092
|
+
second_int = 0
|
|
1093
|
+
|
|
1094
|
+
return datetime.datetime(
|
|
1095
|
+
year=year_int,
|
|
1096
|
+
month=month_int,
|
|
1097
|
+
day=day_int,
|
|
1098
|
+
hour=hour_int,
|
|
1099
|
+
minute=minute_int,
|
|
1100
|
+
second=second_int
|
|
1101
|
+
).strftime(output_str_format)
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
if __name__ == '__main__':
|
|
1105
|
+
res = str2datetime(input_str="20250101123456", input_str_format="YYYYmmdd")
|
|
1106
|
+
print(res)
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
@ GitHub : https://github.com/ZeroSeeker
|
|
7
7
|
@ Gitee : https://gitee.com/ZeroSeeker
|
|
8
8
|
"""
|
|
9
|
+
import time
|
|
10
|
+
|
|
9
11
|
from lazysdk import lazyrequests
|
|
10
12
|
import showlog
|
|
11
13
|
import json
|
|
@@ -202,7 +204,9 @@ def send_text(
|
|
|
202
204
|
at_ids: list = None,
|
|
203
205
|
at_mobiles: list = None,
|
|
204
206
|
is_at: bool = None,
|
|
205
|
-
at_all: bool = None
|
|
207
|
+
at_all: bool = None,
|
|
208
|
+
ensure_success: bool = False,
|
|
209
|
+
ensure_success_limit: int = 60
|
|
206
210
|
):
|
|
207
211
|
"""
|
|
208
212
|
在内部实例化,
|
|
@@ -233,14 +237,84 @@ def send_text(
|
|
|
233
237
|
webhook_hostname = urlparse(webhook).hostname
|
|
234
238
|
if webhook_hostname == 'qyapi.weixin.qq.com':
|
|
235
239
|
webhook_basic = WeixinBasics(con_info=con_info)
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
retry_count = 0
|
|
241
|
+
while True:
|
|
242
|
+
response = webhook_basic.send_text(
|
|
243
|
+
msg=msg,
|
|
244
|
+
con_info=con_info,
|
|
245
|
+
at_ids=at_ids,
|
|
246
|
+
at_mobiles=at_mobiles,
|
|
247
|
+
is_at=is_at,
|
|
248
|
+
at_all=at_all
|
|
249
|
+
)
|
|
250
|
+
if not ensure_success:
|
|
251
|
+
return response
|
|
252
|
+
else:
|
|
253
|
+
if response.get('errcode') == 0:
|
|
254
|
+
return response
|
|
255
|
+
else:
|
|
256
|
+
showlog.warning(response)
|
|
257
|
+
retry_count += 1
|
|
258
|
+
if retry_count > ensure_success_limit:
|
|
259
|
+
return response
|
|
260
|
+
time.sleep(1)
|
|
261
|
+
elif webhook_hostname == 'open.feishu.cn':
|
|
262
|
+
return lazyrequests.lazy_requests(
|
|
263
|
+
url=webhook,
|
|
264
|
+
method="POST",
|
|
265
|
+
headers={"Content-Type": "application/json"},
|
|
266
|
+
json={"msg_type":"text","content":{"text": msg}}
|
|
267
|
+
)
|
|
268
|
+
elif webhook_hostname == 'api.day.app':
|
|
269
|
+
# 支持简单的Bark推送
|
|
270
|
+
return lazyrequests.lazy_requests(
|
|
271
|
+
url=webhook,
|
|
272
|
+
method="GET"
|
|
243
273
|
)
|
|
244
|
-
return response
|
|
245
274
|
else:
|
|
246
275
|
return {'errcode': -2, 'errmsg': '暂不支持此webhook'}
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def send(
|
|
279
|
+
msg: str = None,
|
|
280
|
+
|
|
281
|
+
env_file_name: str = None,
|
|
282
|
+
webhook: str = None,
|
|
283
|
+
webhooks: list = None,
|
|
284
|
+
at_ids: list = None,
|
|
285
|
+
at_mobiles: list = None,
|
|
286
|
+
is_at: bool = None,
|
|
287
|
+
at_all: bool = None,
|
|
288
|
+
ensure_success: bool = False,
|
|
289
|
+
ensure_success_limit: int = 60
|
|
290
|
+
):
|
|
291
|
+
webhooks_all = list()
|
|
292
|
+
send_res = list()
|
|
293
|
+
if webhook:
|
|
294
|
+
webhooks_all.append(webhook)
|
|
295
|
+
if webhooks:
|
|
296
|
+
webhooks_all.extend(webhooks)
|
|
297
|
+
|
|
298
|
+
if not webhooks_all:
|
|
299
|
+
showlog.warning("无有效的webhook地址")
|
|
300
|
+
else:
|
|
301
|
+
for each_index, each_webhook in enumerate(webhooks_all):
|
|
302
|
+
showlog.info(f"正在发送第 {each_index+1}/{len(webhooks_all)} 条推送: \n{msg}\n")
|
|
303
|
+
each_send_res = send_text(
|
|
304
|
+
msg=msg,
|
|
305
|
+
env_file_name=env_file_name,
|
|
306
|
+
webhook=each_webhook,
|
|
307
|
+
at_ids=at_ids,
|
|
308
|
+
at_mobiles=at_mobiles,
|
|
309
|
+
is_at=is_at,
|
|
310
|
+
at_all=at_all,
|
|
311
|
+
ensure_success=ensure_success,
|
|
312
|
+
ensure_success_limit=ensure_success_limit
|
|
313
|
+
)
|
|
314
|
+
send_res.append({
|
|
315
|
+
"webhook": each_webhook,
|
|
316
|
+
"msg": msg,
|
|
317
|
+
"send_res": each_send_res,
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
return send_res
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: lazysdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.122
|
|
4
4
|
Summary: 基于Python的懒人包
|
|
5
5
|
Home-page: https://gitee.com/ZeroSeeker/lazysdk
|
|
6
6
|
Author: ZeroSeeker
|
|
@@ -23,7 +23,16 @@ Requires-Dist: filetype==1.2.0
|
|
|
23
23
|
Requires-Dist: netifaces==0.11.0
|
|
24
24
|
Requires-Dist: user_agents==2.2.0
|
|
25
25
|
Requires-Dist: rich>=13.5.2
|
|
26
|
-
Requires-Dist: urllib3==1.
|
|
26
|
+
Requires-Dist: urllib3==1.26.9
|
|
27
|
+
Dynamic: author
|
|
28
|
+
Dynamic: author-email
|
|
29
|
+
Dynamic: classifier
|
|
30
|
+
Dynamic: description
|
|
31
|
+
Dynamic: description-content-type
|
|
32
|
+
Dynamic: home-page
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: summary
|
|
27
36
|
|
|
28
37
|
# lazysdk
|
|
29
38
|

|
|
@@ -3,7 +3,9 @@ README.md
|
|
|
3
3
|
setup.py
|
|
4
4
|
lazysdk/__init__.py
|
|
5
5
|
lazysdk/lazyCrypto.py
|
|
6
|
+
lazysdk/lazy_header.py
|
|
6
7
|
lazysdk/lazy_id_card.py
|
|
8
|
+
lazysdk/lazy_input.py
|
|
7
9
|
lazysdk/lazybase64.py
|
|
8
10
|
lazysdk/lazycache.py
|
|
9
11
|
lazysdk/lazychromedriver.py
|
|
@@ -13,17 +15,20 @@ lazysdk/lazyenv.py
|
|
|
13
15
|
lazysdk/lazyexcel.py
|
|
14
16
|
lazysdk/lazyfile.py
|
|
15
17
|
lazysdk/lazyflask.py
|
|
18
|
+
lazysdk/lazyhash.py
|
|
16
19
|
lazysdk/lazyhtml.py
|
|
17
20
|
lazysdk/lazyid.py
|
|
18
21
|
lazysdk/lazyinfo.py
|
|
19
22
|
lazysdk/lazyip.py
|
|
20
23
|
lazysdk/lazyjson.py
|
|
24
|
+
lazysdk/lazylist.py
|
|
21
25
|
lazysdk/lazym3u8.py
|
|
22
26
|
lazysdk/lazymd5.py
|
|
23
27
|
lazysdk/lazypath.py
|
|
24
28
|
lazysdk/lazyprocess.py
|
|
25
29
|
lazysdk/lazyproxies.py
|
|
26
30
|
lazysdk/lazyrandom.py
|
|
31
|
+
lazysdk/lazyre.py
|
|
27
32
|
lazysdk/lazyredis.py
|
|
28
33
|
lazysdk/lazyrequests.py
|
|
29
34
|
lazysdk/lazytext.py
|
|
@@ -13,7 +13,7 @@ with open("README.md", "r", encoding='utf-8') as fh:
|
|
|
13
13
|
|
|
14
14
|
setuptools.setup(
|
|
15
15
|
name="lazysdk",
|
|
16
|
-
version="0.1.
|
|
16
|
+
version="0.1.122",
|
|
17
17
|
description="基于Python的懒人包",
|
|
18
18
|
long_description=long_description,
|
|
19
19
|
long_description_content_type="text/markdown",
|
|
@@ -40,6 +40,6 @@ setuptools.setup(
|
|
|
40
40
|
'netifaces==0.11.0',
|
|
41
41
|
'user_agents==2.2.0',
|
|
42
42
|
'rich>=13.5.2',
|
|
43
|
-
'urllib3==1.23
|
|
43
|
+
'urllib3==1.26.9' # 之前为urllib3==1.23
|
|
44
44
|
]
|
|
45
45
|
)
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import decimal
|
|
3
|
-
import datetime
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class LazyEncoder(json.JSONEncoder):
|
|
7
|
-
def default(self, obj):
|
|
8
|
-
if isinstance(obj, decimal.Decimal):
|
|
9
|
-
return float(obj)
|
|
10
|
-
elif isinstance(obj, datetime.datetime):
|
|
11
|
-
return obj.strftime('%Y-%m-%d %H:%M:%S')
|
|
12
|
-
elif isinstance(obj, datetime.date):
|
|
13
|
-
return obj.strftime('%Y-%m-%d')
|
|
14
|
-
super(LazyEncoder, self).default(obj)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def json2str(
|
|
18
|
-
data: json,
|
|
19
|
-
ensure_ascii: bool = False
|
|
20
|
-
):
|
|
21
|
-
"""
|
|
22
|
-
在将json数据反序列化为str时,会遇到一些格式无法转换
|
|
23
|
-
这里使用识别类型转换转为str
|
|
24
|
-
目前支持类型:
|
|
25
|
-
decimal --> str
|
|
26
|
-
datetime.datetime --> str(%Y-%m-%d %H:%M:%S)
|
|
27
|
-
datetime.date --> str(%Y-%m-%d)
|
|
28
|
-
"""
|
|
29
|
-
return json.dumps(
|
|
30
|
-
data,
|
|
31
|
-
cls=LazyEncoder,
|
|
32
|
-
ensure_ascii=ensure_ascii
|
|
33
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|