re-common 10.0.22__py3-none-any.whl → 10.0.24__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.
Files changed (202) hide show
  1. re_common/baselibrary/__init__.py +4 -4
  2. re_common/baselibrary/baseabs/__init__.py +6 -6
  3. re_common/baselibrary/baseabs/baseabs.py +26 -26
  4. re_common/baselibrary/database/mbuilder.py +132 -132
  5. re_common/baselibrary/database/moudle.py +93 -93
  6. re_common/baselibrary/database/msqlite3.py +194 -194
  7. re_common/baselibrary/database/mysql.py +169 -169
  8. re_common/baselibrary/database/sql_factory.py +26 -26
  9. re_common/baselibrary/mthread/MThreadingRun.py +486 -486
  10. re_common/baselibrary/mthread/MThreadingRunEvent.py +349 -349
  11. re_common/baselibrary/mthread/__init__.py +2 -2
  12. re_common/baselibrary/mthread/mythreading.py +695 -695
  13. re_common/baselibrary/pakge_other/socks.py +404 -404
  14. re_common/baselibrary/readconfig/config_factory.py +18 -18
  15. re_common/baselibrary/readconfig/ini_config.py +317 -317
  16. re_common/baselibrary/readconfig/toml_config.py +49 -49
  17. re_common/baselibrary/temporary/envdata.py +36 -36
  18. re_common/baselibrary/tools/all_requests/aiohttp_request.py +118 -118
  19. re_common/baselibrary/tools/all_requests/httpx_requet.py +102 -102
  20. re_common/baselibrary/tools/all_requests/mrequest.py +412 -412
  21. re_common/baselibrary/tools/all_requests/requests_request.py +81 -81
  22. re_common/baselibrary/tools/batch_compre/bijiao_batch.py +31 -31
  23. re_common/baselibrary/tools/contrast_db3.py +123 -123
  24. re_common/baselibrary/tools/copy_file.py +39 -39
  25. re_common/baselibrary/tools/db3_2_sizedb3.py +102 -102
  26. re_common/baselibrary/tools/foreachgz.py +39 -39
  27. re_common/baselibrary/tools/get_attr.py +10 -10
  28. re_common/baselibrary/tools/image_to_pdf.py +61 -61
  29. re_common/baselibrary/tools/java_code_deal.py +139 -139
  30. re_common/baselibrary/tools/javacode.py +79 -79
  31. re_common/baselibrary/tools/mdb_db3.py +48 -48
  32. re_common/baselibrary/tools/merge_file.py +171 -171
  33. re_common/baselibrary/tools/merge_gz_file.py +165 -165
  34. re_common/baselibrary/tools/mhdfstools/down_hdfs_files.py +42 -42
  35. re_common/baselibrary/tools/mhdfstools/hdfst.py +42 -42
  36. re_common/baselibrary/tools/mhdfstools/up_hdfs_files.py +38 -38
  37. re_common/baselibrary/tools/mongo_tools.py +50 -50
  38. re_common/baselibrary/tools/move_file.py +170 -170
  39. re_common/baselibrary/tools/move_mongo/mongo_table_to_file.py +63 -63
  40. re_common/baselibrary/tools/move_mongo/move_mongo_table.py +354 -354
  41. re_common/baselibrary/tools/move_mongo/use_mttf.py +18 -18
  42. re_common/baselibrary/tools/move_mongo/use_mv.py +93 -93
  43. re_common/baselibrary/tools/mpandas/mpandasreadexcel.py +125 -125
  44. re_common/baselibrary/tools/mpandas/pandas_visualization.py +7 -7
  45. re_common/baselibrary/tools/myparsel.py +104 -104
  46. re_common/baselibrary/tools/rename_dir_file.py +37 -37
  47. re_common/baselibrary/tools/sequoiadb_utils.py +398 -398
  48. re_common/baselibrary/tools/split_line_to_many.py +25 -25
  49. re_common/baselibrary/tools/stringtodicts.py +33 -33
  50. re_common/baselibrary/tools/workwechant_bot.py +84 -84
  51. re_common/baselibrary/utils/baseaiohttp.py +296 -296
  52. re_common/baselibrary/utils/baseaiomysql.py +87 -87
  53. re_common/baselibrary/utils/baseallstep.py +191 -191
  54. re_common/baselibrary/utils/baseavro.py +19 -19
  55. re_common/baselibrary/utils/baseboto3.py +291 -291
  56. re_common/baselibrary/utils/basecsv.py +32 -32
  57. re_common/baselibrary/utils/basedict.py +133 -133
  58. re_common/baselibrary/utils/basedir.py +241 -241
  59. re_common/baselibrary/utils/baseencode.py +351 -351
  60. re_common/baselibrary/utils/baseencoding.py +28 -28
  61. re_common/baselibrary/utils/baseesdsl.py +86 -86
  62. re_common/baselibrary/utils/baseexcel.py +264 -264
  63. re_common/baselibrary/utils/baseexcept.py +109 -109
  64. re_common/baselibrary/utils/basefile.py +654 -654
  65. re_common/baselibrary/utils/baseftp.py +214 -214
  66. re_common/baselibrary/utils/basegzip.py +60 -60
  67. re_common/baselibrary/utils/basehdfs.py +135 -135
  68. re_common/baselibrary/utils/basehttpx.py +268 -268
  69. re_common/baselibrary/utils/baseip.py +87 -87
  70. re_common/baselibrary/utils/basejson.py +2 -2
  71. re_common/baselibrary/utils/baselist.py +32 -32
  72. re_common/baselibrary/utils/basemotor.py +190 -190
  73. re_common/baselibrary/utils/basemssql.py +98 -98
  74. re_common/baselibrary/utils/baseodbc.py +113 -113
  75. re_common/baselibrary/utils/basepandas.py +302 -302
  76. re_common/baselibrary/utils/basepeewee.py +11 -11
  77. re_common/baselibrary/utils/basepika.py +180 -180
  78. re_common/baselibrary/utils/basepydash.py +143 -143
  79. re_common/baselibrary/utils/basepymongo.py +230 -230
  80. re_common/baselibrary/utils/basequeue.py +22 -22
  81. re_common/baselibrary/utils/baserar.py +57 -57
  82. re_common/baselibrary/utils/baserequest.py +279 -279
  83. re_common/baselibrary/utils/baseset.py +8 -8
  84. re_common/baselibrary/utils/basesmb.py +403 -403
  85. re_common/baselibrary/utils/basestring.py +382 -382
  86. re_common/baselibrary/utils/basetime.py +320 -320
  87. re_common/baselibrary/utils/baseurl.py +121 -121
  88. re_common/baselibrary/utils/basezip.py +57 -57
  89. re_common/baselibrary/utils/core/__init__.py +7 -7
  90. re_common/baselibrary/utils/core/bottomutils.py +18 -18
  91. re_common/baselibrary/utils/core/mdeprecated.py +327 -327
  92. re_common/baselibrary/utils/core/mlamada.py +16 -16
  93. re_common/baselibrary/utils/core/msginfo.py +25 -25
  94. re_common/baselibrary/utils/core/requests_core.py +103 -103
  95. re_common/baselibrary/utils/fateadm.py +429 -429
  96. re_common/baselibrary/utils/importfun.py +123 -123
  97. re_common/baselibrary/utils/mfaker.py +57 -57
  98. re_common/baselibrary/utils/my_abc/__init__.py +3 -3
  99. re_common/baselibrary/utils/my_abc/better_abc.py +32 -32
  100. re_common/baselibrary/utils/mylogger.py +414 -414
  101. re_common/baselibrary/utils/myredisclient.py +861 -861
  102. re_common/baselibrary/utils/pipupgrade.py +21 -21
  103. re_common/baselibrary/utils/ringlist.py +85 -85
  104. re_common/baselibrary/utils/version_compare.py +36 -36
  105. re_common/baselibrary/utils/ydmhttp.py +126 -126
  106. re_common/facade/lazy_import.py +11 -11
  107. re_common/facade/loggerfacade.py +25 -25
  108. re_common/facade/mysqlfacade.py +467 -467
  109. re_common/facade/now.py +31 -31
  110. re_common/facade/sqlite3facade.py +257 -257
  111. re_common/facade/use/mq_use_facade.py +83 -83
  112. re_common/facade/use/proxy_use_facade.py +19 -19
  113. re_common/libtest/base_dict_test.py +19 -19
  114. re_common/libtest/baseavro_test.py +13 -13
  115. re_common/libtest/basefile_test.py +14 -14
  116. re_common/libtest/basemssql_test.py +77 -77
  117. re_common/libtest/baseodbc_test.py +7 -7
  118. re_common/libtest/basepandas_test.py +38 -38
  119. re_common/libtest/get_attr_test/get_attr_test_settings.py +14 -14
  120. re_common/libtest/get_attr_test/settings.py +54 -54
  121. re_common/libtest/idencode_test.py +53 -53
  122. re_common/libtest/iniconfig_test.py +35 -35
  123. re_common/libtest/ip_test.py +34 -34
  124. re_common/libtest/merge_file_test.py +20 -20
  125. re_common/libtest/mfaker_test.py +8 -8
  126. re_common/libtest/mm3_test.py +31 -31
  127. re_common/libtest/mylogger_test.py +88 -88
  128. re_common/libtest/myparsel_test.py +27 -27
  129. re_common/libtest/mysql_test.py +151 -151
  130. re_common/libtest/pymongo_test.py +21 -21
  131. re_common/libtest/split_test.py +11 -11
  132. re_common/libtest/sqlite3_merge_test.py +5 -5
  133. re_common/libtest/sqlite3_test.py +34 -34
  134. re_common/libtest/tomlconfig_test.py +30 -30
  135. re_common/libtest/use_tools_test/__init__.py +2 -2
  136. re_common/libtest/user/__init__.py +4 -4
  137. re_common/studio/__init__.py +4 -4
  138. re_common/studio/assignment_expressions.py +36 -36
  139. re_common/studio/mydash/test1.py +18 -18
  140. re_common/studio/pydashstudio/first.py +9 -9
  141. re_common/studio/streamlitstudio/first_app.py +65 -65
  142. re_common/studio/streamlitstudio/uber_pickups.py +23 -23
  143. re_common/studio/test.py +18 -18
  144. re_common/v2/baselibrary/business_utils/BusinessStringUtil.py +195 -0
  145. re_common/v2/baselibrary/business_utils/__init__.py +0 -0
  146. re_common/v2/baselibrary/business_utils/rel_tools.py +6 -0
  147. re_common/v2/baselibrary/decorators/utils.py +59 -59
  148. re_common/v2/baselibrary/s3object/baseboto3.py +230 -230
  149. re_common/v2/baselibrary/tools/WeChatRobot.py +95 -79
  150. re_common/v2/baselibrary/tools/ac_ahocorasick.py +75 -75
  151. re_common/v2/baselibrary/tools/dict_tools.py +37 -37
  152. re_common/v2/baselibrary/tools/dolphinscheduler.py +187 -187
  153. re_common/v2/baselibrary/tools/hdfs_data_processer.py +338 -338
  154. re_common/v2/baselibrary/tools/list_tools.py +65 -65
  155. re_common/v2/baselibrary/tools/search_hash_tools.py +54 -54
  156. re_common/v2/baselibrary/tools/text_matcher.py +326 -326
  157. re_common/v2/baselibrary/tools/unionfind_tools.py +60 -60
  158. re_common/v2/baselibrary/utils/BusinessStringUtil.py +196 -196
  159. re_common/v2/baselibrary/utils/author_smi.py +360 -360
  160. re_common/v2/baselibrary/utils/base_string_similarity.py +158 -158
  161. re_common/v2/baselibrary/utils/basedict.py +37 -37
  162. re_common/v2/baselibrary/utils/basehdfs.py +161 -161
  163. re_common/v2/baselibrary/utils/basepika.py +180 -180
  164. re_common/v2/baselibrary/utils/basetime.py +77 -77
  165. re_common/v2/baselibrary/utils/db.py +38 -38
  166. re_common/v2/baselibrary/utils/json_cls.py +16 -16
  167. re_common/v2/baselibrary/utils/mq.py +83 -83
  168. re_common/v2/baselibrary/utils/n_ary_expression_tree.py +243 -243
  169. re_common/v2/baselibrary/utils/string_bool.py +186 -149
  170. re_common/v2/baselibrary/utils/string_clear.py +227 -204
  171. re_common/v2/baselibrary/utils/string_smi.py +18 -18
  172. re_common/v2/baselibrary/utils/stringutils.py +213 -213
  173. re_common/vip/base_step_process.py +11 -11
  174. re_common/vip/baseencodeid.py +90 -90
  175. re_common/vip/changetaskname.py +28 -28
  176. re_common/vip/core_var.py +24 -24
  177. re_common/vip/mmh3Hash.py +89 -89
  178. re_common/vip/proxy/allproxys.py +127 -127
  179. re_common/vip/proxy/allproxys_thread.py +159 -159
  180. re_common/vip/proxy/cnki_proxy.py +153 -153
  181. re_common/vip/proxy/kuaidaili.py +87 -87
  182. re_common/vip/proxy/proxy_all.py +113 -113
  183. re_common/vip/proxy/update_kuaidaili_0.py +42 -42
  184. re_common/vip/proxy/wanfang_proxy.py +152 -152
  185. re_common/vip/proxy/wp_proxy_all.py +181 -181
  186. re_common/vip/read_rawid_to_txt.py +91 -91
  187. re_common/vip/title/__init__.py +5 -5
  188. re_common/vip/title/transform/TransformBookTitleToZt.py +125 -125
  189. re_common/vip/title/transform/TransformConferenceTitleToZt.py +139 -139
  190. re_common/vip/title/transform/TransformCstadTitleToZt.py +195 -195
  191. re_common/vip/title/transform/TransformJournalTitleToZt.py +203 -203
  192. re_common/vip/title/transform/TransformPatentTitleToZt.py +132 -132
  193. re_common/vip/title/transform/TransformRegulationTitleToZt.py +114 -114
  194. re_common/vip/title/transform/TransformStandardTitleToZt.py +135 -135
  195. re_common/vip/title/transform/TransformThesisTitleToZt.py +135 -135
  196. re_common/vip/title/transform/__init__.py +10 -10
  197. {re_common-10.0.22.dist-info → re_common-10.0.24.dist-info}/LICENSE +201 -201
  198. {re_common-10.0.22.dist-info → re_common-10.0.24.dist-info}/METADATA +16 -16
  199. re_common-10.0.24.dist-info/RECORD +230 -0
  200. {re_common-10.0.22.dist-info → re_common-10.0.24.dist-info}/WHEEL +1 -1
  201. re_common-10.0.22.dist-info/RECORD +0 -227
  202. {re_common-10.0.22.dist-info → re_common-10.0.24.dist-info}/top_level.txt +0 -0
@@ -1,230 +1,230 @@
1
- from boto3.session import Session
2
-
3
-
4
- class BaseBoto3(object):
5
-
6
- def __init__(self, aws_access_key_id="", aws_secret_access_key="", endpoint_url=""):
7
- self.aws_access_key_id = aws_access_key_id
8
- self.aws_secret_access_key = aws_secret_access_key
9
- self.endpoint_url = endpoint_url
10
- self.session = None
11
- self.client = None
12
- if self.aws_access_key_id and self.aws_secret_access_key and self.endpoint_url:
13
- self.conn_session()
14
- self.get_client()
15
-
16
- def set_key(self, aws_access_key_id, aws_secret_access_key, endpoint_url):
17
- self.aws_access_key_id = aws_access_key_id
18
- self.aws_secret_access_key = aws_secret_access_key
19
- self.endpoint_url = endpoint_url
20
- return self
21
-
22
- def conn_session(self):
23
- assert self.aws_access_key_id not in (None, '')
24
- assert self.aws_secret_access_key not in (None, '')
25
- self.session = Session(aws_access_key_id=self.aws_access_key_id,
26
- aws_secret_access_key=self.aws_secret_access_key)
27
- return self.session
28
-
29
- def get_client(self):
30
- assert self.session is not None
31
- self.client = self.session.client('s3', endpoint_url=self.endpoint_url)
32
- return self
33
-
34
- def get_all_buckets(self):
35
- """
36
- 获取所有的桶信息
37
- :return:
38
- """
39
- return self.client.list_buckets()
40
-
41
- def create_buckets(self, buckets_name):
42
- """
43
- 如果get_client 使用 client 返回
44
- {'ResponseMetadata': {'RequestId': '16BC90EED4A433C4', 'HostId': '', 'HTTPStatusCode': 200, 'HTTPHeaders': {'accept-ranges': 'bytes', 'content-length': '0', 'content-security-policy': 'block-all-mixed-content', 'location': '/create1', 'server': 'MinIO', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '16BC90EED4A433C4', 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Wed, 01 Dec 2021 07:28:39 GMT'}, 'RetryAttempts': 0}, 'Location': '/create1'}
45
- """
46
- assert buckets_name.find("_") == -1, "新建一个bucket桶(bucket name 中不能有_下划线)"
47
- # 新建一个bucket桶(bucket name 中不能有_下划线)
48
- return self.client.create_bucket(Bucket=buckets_name)
49
-
50
- def delete_buckets(self, bucket_name):
51
- """
52
- 删除桶 删除bucket(只能删除空的bucket)
53
- :return:
54
- """
55
- response = self.client.delete_bucket(Bucket=bucket_name)
56
- return response
57
-
58
- def get_bucket(self, bucket_name):
59
- raise Exception("无实现方法")
60
-
61
- def get_all_objs(self, bucket_name, prefix=None, continuation_token=None):
62
- """
63
-
64
- continuation_token: 如果超过1000 需要传第一次获取结果中的 continuation_token
65
-
66
- response 的结构
67
- {'ResponseMetadata': {'RequestId': '1818F447C1E7BA3B', 'HostId': '', 'HTTPStatusCode': 200,
68
- 'HTTPHeaders': {'accept-ranges': 'bytes', 'content-length': '3182', 'content-security-policy': 'block-all-mixed-content', 'content-type': 'application/xml',
69
- 'server': 'MinIO', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '1818F447C1E7BA3B',
70
- 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Thu, 09 Jan 2025 07:04:05 GMT'}, 'RetryAttempts': 0},
71
- 'IsTruncated': False, 'Contents':
72
- [
73
- {'Key': 'zt_file/zt类型样例数据/11_part-00000.gz', 'LastModified': datetime.datetime(2024, 4, 28, 2, 56, 59, 716000, tzinfo=tzutc()), 'ETag': '"e0d635f171bce6a67ad72265e5f9137d-2"',
74
- 'Size': 18164139, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': 'minio', 'ID': '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4'}},
75
- {'Key': 'zt_file/zt类型样例数据/12_part-00000.gz', 'LastModified': datetime.datetime(2024, 4, 28, 2, 56, 57, 70000, tzinfo=tzutc()), 'ETag': '"f238fe9973a2bc0d3e1562c2938ce897-9"',
76
- 'Size': 93710911, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': 'minio', 'ID': '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4'}},
77
- ],
78
- 'Name': 'crawl.dc.cqvip.com', 'Prefix': 'zt_file/zt类型样例数据', 'Delimiter': '',
79
- 'MaxKeys': 1000, 'EncodingType': 'url', 'KeyCount': 7}
80
-
81
- """
82
- if continuation_token:
83
- # 获取桶中以特定前缀开头的所有对象
84
- response = self.client.list_objects_v2(Bucket=bucket_name,
85
- Prefix=prefix,
86
- ContinuationToken=continuation_token)
87
- else:
88
- # 获取桶中以特定前缀开头的所有对象
89
- response = self.client.list_objects_v2(Bucket=bucket_name,
90
- Prefix=prefix)
91
- object_list = []
92
- # 检查是否有对象存在
93
- if 'Contents' in response:
94
- object_list = [obj['Key'] for obj in response['Contents']]
95
-
96
- continuation_token = None
97
- # 检查是否有更多对象
98
- if response.get('IsTruncated'): # 如果返回结果被截断,说明有更多对象
99
- continuation_token = response.get('NextContinuationToken')
100
-
101
- return object_list, continuation_token
102
-
103
- def list_prefixes(self, bucket_name, prefix=None, Delimiter="/", continuation_token=None):
104
- """
105
- 获取目录下一层的目录
106
- prefix: 注意 这个要以 Delimiter 结尾 比如 Delimiter="/" 那么 prefix="a/"
107
- continuation_token: 如果超过1000 需要传第一次获取结果中的 continuation_token
108
- return: ['a/b/', 'a/c/'] 注意 反回的 结果带有prefix 只能返回目录 不能返回文件
109
- """
110
- if continuation_token:
111
- # 获取桶中以特定前缀开头的所有对象
112
- response = self.client.list_objects_v2(Bucket=bucket_name,
113
- Prefix=prefix,
114
- Delimiter=Delimiter, # 使用斜杠分隔符模拟目录结构
115
- ContinuationToken=continuation_token)
116
- else:
117
- # 获取桶中以特定前缀开头的所有对象
118
- response = self.client.list_objects_v2(Bucket=bucket_name,
119
- Delimiter=Delimiter, # 使用斜杠分隔符模拟目录结构
120
- Prefix=prefix)
121
- object_list = []
122
- # 检查是否有对象存在
123
- if 'Contents' in response:
124
- object_list = [obj['Key'] for obj in response['Contents']]
125
-
126
- Prefix_list = []
127
- # 检查是否有目录存在
128
- if 'CommonPrefixes' in response:
129
- Prefix_list = [obj['Prefix'] for obj in response['CommonPrefixes']]
130
-
131
- continuation_token = None
132
- # 检查是否有更多对象
133
- if response.get('IsTruncated'): # 如果返回结果被截断,说明有更多对象
134
- continuation_token = response.get('NextContinuationToken')
135
-
136
- return object_list, Prefix_list, continuation_token
137
-
138
- def get_object_value(self, bucket_name, file_key, encoding='utf-8'):
139
- """
140
- 读取文本数据
141
- Returns:
142
- """
143
- obj = self.client.get_object(Bucket=bucket_name, Key=file_key)
144
- body = obj['Body'].read().decode(encoding)
145
- return body
146
-
147
- def put_object(self, bucket_name, key, body):
148
- """
149
- 直接写内容到文件
150
- Args:
151
- bucket_name:
152
- key:
153
- body: 需要 编码 .encode('utf-8')
154
-
155
- Returns:
156
- """
157
- self.client.put_object(Bucket=bucket_name,
158
- Key=key,
159
- Body=body)
160
-
161
- def download_file(self, bucket_name, key, local_file):
162
- """
163
- return: None
164
- """
165
- result = self.client.download_file(bucket_name, key, local_file)
166
- return result
167
-
168
- def upload_file(self, bucket_name, key, local_file):
169
- """
170
- # key 桶中的位置 test1/test.pdf
171
- :param local_file: 本地文件路径
172
- :param bucket_name: 桶名
173
- :param key: 远程文件路径
174
- :return:
175
- """
176
- self.client.upload_file(local_file, bucket_name, key)
177
-
178
- def download_fileobj(self, bucket_name, key, fileobj):
179
- """
180
- return: None
181
- """
182
- result = self.client.download_fileobj(bucket_name, key, fileobj)
183
- return result
184
-
185
- def upload_fileobj(self, bucket_name, key, fileobj):
186
- # fileobj 字节流
187
- self.client.upload_fileobj(fileobj, bucket_name, key)
188
-
189
- def check_exist_or_file_info(self, bucket_name, key):
190
- """
191
- 检查文件是否存在且能获取文件info
192
- {'ResponseMetadata': {'RequestId': '17E6A65A2B299D3B', 'HostId': '', 'HTTPStatusCode': 200, 'HTTPHeaders':
193
- {'accept-ranges': 'bytes', 'content-length': '117', 'content-security-policy': 'block-all-mixed-content', 'content-type': 'binary/octet-stream',
194
- 'etag': '"2237a934f176003e41abf3d733291079"', 'last-modified': 'Thu, 25 Jul 2024 05:49:43 GMT', 'server': 'MinIO',
195
- 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '17E6A65A2B299D3B',
196
- 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Mon, 29 Jul 2024 09:53:33 GMT'}, 'RetryAttempts': 0},
197
- 'AcceptRanges': 'bytes', 'LastModified': datetime.datetime(2024, 7, 25, 5, 49, 43, tzinfo=tzutc()), 'ContentLength': 117, 'ETag': '"2237a934f176003e41abf3d733291079"',
198
- 'ContentType': 'binary/octet-stream', 'Metadata': {}}
199
- """
200
- try:
201
- obj_info = self.client.head_object(
202
- Bucket=bucket_name,
203
- Key=key
204
- )
205
- return obj_info
206
- except:
207
- return None
208
-
209
- def get_prefix_count(self, bucket_name, obj_count, prefix, continuation_token=None):
210
- """
211
- 统计 某个目录的文件数据量,由于需要每个目录获取一次 性能很慢
212
- """
213
- for index in range(10000):
214
- obj_list, dir_list, token = self.list_prefixes(bucket_name=bucket_name,
215
- prefix=prefix,
216
- continuation_token=continuation_token)
217
-
218
- obj_count = obj_count + len(obj_list)
219
- for dir_sub in dir_list:
220
- obj_count = self.get_prefix_count(bucket_name, obj_count, dir_sub)
221
-
222
- if token:
223
- continuation_token = token
224
- else:
225
- break
226
-
227
- if index > 10000 - 5:
228
- raise Exception("循环耗尽,请检查逻辑正确性")
229
-
230
- return obj_count
1
+ from boto3.session import Session
2
+
3
+
4
+ class BaseBoto3(object):
5
+
6
+ def __init__(self, aws_access_key_id="", aws_secret_access_key="", endpoint_url=""):
7
+ self.aws_access_key_id = aws_access_key_id
8
+ self.aws_secret_access_key = aws_secret_access_key
9
+ self.endpoint_url = endpoint_url
10
+ self.session = None
11
+ self.client = None
12
+ if self.aws_access_key_id and self.aws_secret_access_key and self.endpoint_url:
13
+ self.conn_session()
14
+ self.get_client()
15
+
16
+ def set_key(self, aws_access_key_id, aws_secret_access_key, endpoint_url):
17
+ self.aws_access_key_id = aws_access_key_id
18
+ self.aws_secret_access_key = aws_secret_access_key
19
+ self.endpoint_url = endpoint_url
20
+ return self
21
+
22
+ def conn_session(self):
23
+ assert self.aws_access_key_id not in (None, '')
24
+ assert self.aws_secret_access_key not in (None, '')
25
+ self.session = Session(aws_access_key_id=self.aws_access_key_id,
26
+ aws_secret_access_key=self.aws_secret_access_key)
27
+ return self.session
28
+
29
+ def get_client(self):
30
+ assert self.session is not None
31
+ self.client = self.session.client('s3', endpoint_url=self.endpoint_url)
32
+ return self
33
+
34
+ def get_all_buckets(self):
35
+ """
36
+ 获取所有的桶信息
37
+ :return:
38
+ """
39
+ return self.client.list_buckets()
40
+
41
+ def create_buckets(self, buckets_name):
42
+ """
43
+ 如果get_client 使用 client 返回
44
+ {'ResponseMetadata': {'RequestId': '16BC90EED4A433C4', 'HostId': '', 'HTTPStatusCode': 200, 'HTTPHeaders': {'accept-ranges': 'bytes', 'content-length': '0', 'content-security-policy': 'block-all-mixed-content', 'location': '/create1', 'server': 'MinIO', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '16BC90EED4A433C4', 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Wed, 01 Dec 2021 07:28:39 GMT'}, 'RetryAttempts': 0}, 'Location': '/create1'}
45
+ """
46
+ assert buckets_name.find("_") == -1, "新建一个bucket桶(bucket name 中不能有_下划线)"
47
+ # 新建一个bucket桶(bucket name 中不能有_下划线)
48
+ return self.client.create_bucket(Bucket=buckets_name)
49
+
50
+ def delete_buckets(self, bucket_name):
51
+ """
52
+ 删除桶 删除bucket(只能删除空的bucket)
53
+ :return:
54
+ """
55
+ response = self.client.delete_bucket(Bucket=bucket_name)
56
+ return response
57
+
58
+ def get_bucket(self, bucket_name):
59
+ raise Exception("无实现方法")
60
+
61
+ def get_all_objs(self, bucket_name, prefix=None, continuation_token=None):
62
+ """
63
+
64
+ continuation_token: 如果超过1000 需要传第一次获取结果中的 continuation_token
65
+
66
+ response 的结构
67
+ {'ResponseMetadata': {'RequestId': '1818F447C1E7BA3B', 'HostId': '', 'HTTPStatusCode': 200,
68
+ 'HTTPHeaders': {'accept-ranges': 'bytes', 'content-length': '3182', 'content-security-policy': 'block-all-mixed-content', 'content-type': 'application/xml',
69
+ 'server': 'MinIO', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '1818F447C1E7BA3B',
70
+ 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Thu, 09 Jan 2025 07:04:05 GMT'}, 'RetryAttempts': 0},
71
+ 'IsTruncated': False, 'Contents':
72
+ [
73
+ {'Key': 'zt_file/zt类型样例数据/11_part-00000.gz', 'LastModified': datetime.datetime(2024, 4, 28, 2, 56, 59, 716000, tzinfo=tzutc()), 'ETag': '"e0d635f171bce6a67ad72265e5f9137d-2"',
74
+ 'Size': 18164139, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': 'minio', 'ID': '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4'}},
75
+ {'Key': 'zt_file/zt类型样例数据/12_part-00000.gz', 'LastModified': datetime.datetime(2024, 4, 28, 2, 56, 57, 70000, tzinfo=tzutc()), 'ETag': '"f238fe9973a2bc0d3e1562c2938ce897-9"',
76
+ 'Size': 93710911, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': 'minio', 'ID': '02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4'}},
77
+ ],
78
+ 'Name': 'crawl.dc.cqvip.com', 'Prefix': 'zt_file/zt类型样例数据', 'Delimiter': '',
79
+ 'MaxKeys': 1000, 'EncodingType': 'url', 'KeyCount': 7}
80
+
81
+ """
82
+ if continuation_token:
83
+ # 获取桶中以特定前缀开头的所有对象
84
+ response = self.client.list_objects_v2(Bucket=bucket_name,
85
+ Prefix=prefix,
86
+ ContinuationToken=continuation_token)
87
+ else:
88
+ # 获取桶中以特定前缀开头的所有对象
89
+ response = self.client.list_objects_v2(Bucket=bucket_name,
90
+ Prefix=prefix)
91
+ object_list = []
92
+ # 检查是否有对象存在
93
+ if 'Contents' in response:
94
+ object_list = [obj['Key'] for obj in response['Contents']]
95
+
96
+ continuation_token = None
97
+ # 检查是否有更多对象
98
+ if response.get('IsTruncated'): # 如果返回结果被截断,说明有更多对象
99
+ continuation_token = response.get('NextContinuationToken')
100
+
101
+ return object_list, continuation_token
102
+
103
+ def list_prefixes(self, bucket_name, prefix=None, Delimiter="/", continuation_token=None):
104
+ """
105
+ 获取目录下一层的目录
106
+ prefix: 注意 这个要以 Delimiter 结尾 比如 Delimiter="/" 那么 prefix="a/"
107
+ continuation_token: 如果超过1000 需要传第一次获取结果中的 continuation_token
108
+ return: ['a/b/', 'a/c/'] 注意 反回的 结果带有prefix 只能返回目录 不能返回文件
109
+ """
110
+ if continuation_token:
111
+ # 获取桶中以特定前缀开头的所有对象
112
+ response = self.client.list_objects_v2(Bucket=bucket_name,
113
+ Prefix=prefix,
114
+ Delimiter=Delimiter, # 使用斜杠分隔符模拟目录结构
115
+ ContinuationToken=continuation_token)
116
+ else:
117
+ # 获取桶中以特定前缀开头的所有对象
118
+ response = self.client.list_objects_v2(Bucket=bucket_name,
119
+ Delimiter=Delimiter, # 使用斜杠分隔符模拟目录结构
120
+ Prefix=prefix)
121
+ object_list = []
122
+ # 检查是否有对象存在
123
+ if 'Contents' in response:
124
+ object_list = [obj['Key'] for obj in response['Contents']]
125
+
126
+ Prefix_list = []
127
+ # 检查是否有目录存在
128
+ if 'CommonPrefixes' in response:
129
+ Prefix_list = [obj['Prefix'] for obj in response['CommonPrefixes']]
130
+
131
+ continuation_token = None
132
+ # 检查是否有更多对象
133
+ if response.get('IsTruncated'): # 如果返回结果被截断,说明有更多对象
134
+ continuation_token = response.get('NextContinuationToken')
135
+
136
+ return object_list, Prefix_list, continuation_token
137
+
138
+ def get_object_value(self, bucket_name, file_key, encoding='utf-8'):
139
+ """
140
+ 读取文本数据
141
+ Returns:
142
+ """
143
+ obj = self.client.get_object(Bucket=bucket_name, Key=file_key)
144
+ body = obj['Body'].read().decode(encoding)
145
+ return body
146
+
147
+ def put_object(self, bucket_name, key, body):
148
+ """
149
+ 直接写内容到文件
150
+ Args:
151
+ bucket_name:
152
+ key:
153
+ body: 需要 编码 .encode('utf-8')
154
+
155
+ Returns:
156
+ """
157
+ self.client.put_object(Bucket=bucket_name,
158
+ Key=key,
159
+ Body=body)
160
+
161
+ def download_file(self, bucket_name, key, local_file):
162
+ """
163
+ return: None
164
+ """
165
+ result = self.client.download_file(bucket_name, key, local_file)
166
+ return result
167
+
168
+ def upload_file(self, bucket_name, key, local_file):
169
+ """
170
+ # key 桶中的位置 test1/test.pdf
171
+ :param local_file: 本地文件路径
172
+ :param bucket_name: 桶名
173
+ :param key: 远程文件路径
174
+ :return:
175
+ """
176
+ self.client.upload_file(local_file, bucket_name, key)
177
+
178
+ def download_fileobj(self, bucket_name, key, fileobj):
179
+ """
180
+ return: None
181
+ """
182
+ result = self.client.download_fileobj(bucket_name, key, fileobj)
183
+ return result
184
+
185
+ def upload_fileobj(self, bucket_name, key, fileobj):
186
+ # fileobj 字节流
187
+ self.client.upload_fileobj(fileobj, bucket_name, key)
188
+
189
+ def check_exist_or_file_info(self, bucket_name, key):
190
+ """
191
+ 检查文件是否存在且能获取文件info
192
+ {'ResponseMetadata': {'RequestId': '17E6A65A2B299D3B', 'HostId': '', 'HTTPStatusCode': 200, 'HTTPHeaders':
193
+ {'accept-ranges': 'bytes', 'content-length': '117', 'content-security-policy': 'block-all-mixed-content', 'content-type': 'binary/octet-stream',
194
+ 'etag': '"2237a934f176003e41abf3d733291079"', 'last-modified': 'Thu, 25 Jul 2024 05:49:43 GMT', 'server': 'MinIO',
195
+ 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'vary': 'Origin, Accept-Encoding', 'x-amz-request-id': '17E6A65A2B299D3B',
196
+ 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'date': 'Mon, 29 Jul 2024 09:53:33 GMT'}, 'RetryAttempts': 0},
197
+ 'AcceptRanges': 'bytes', 'LastModified': datetime.datetime(2024, 7, 25, 5, 49, 43, tzinfo=tzutc()), 'ContentLength': 117, 'ETag': '"2237a934f176003e41abf3d733291079"',
198
+ 'ContentType': 'binary/octet-stream', 'Metadata': {}}
199
+ """
200
+ try:
201
+ obj_info = self.client.head_object(
202
+ Bucket=bucket_name,
203
+ Key=key
204
+ )
205
+ return obj_info
206
+ except:
207
+ return None
208
+
209
+ def get_prefix_count(self, bucket_name, obj_count, prefix, continuation_token=None):
210
+ """
211
+ 统计 某个目录的文件数据量,由于需要每个目录获取一次 性能很慢
212
+ """
213
+ for index in range(10000):
214
+ obj_list, dir_list, token = self.list_prefixes(bucket_name=bucket_name,
215
+ prefix=prefix,
216
+ continuation_token=continuation_token)
217
+
218
+ obj_count = obj_count + len(obj_list)
219
+ for dir_sub in dir_list:
220
+ obj_count = self.get_prefix_count(bucket_name, obj_count, dir_sub)
221
+
222
+ if token:
223
+ continuation_token = token
224
+ else:
225
+ break
226
+
227
+ if index > 10000 - 5:
228
+ raise Exception("循环耗尽,请检查逻辑正确性")
229
+
230
+ return obj_count
@@ -1,79 +1,95 @@
1
- import sqlite3
2
- import requests
3
- import pandas as pd
4
- import os
5
- import json
6
- import traceback
7
-
8
-
9
- # 发送消息到企业微信机器人
10
- # vx_key: string类型,自己的企业微信机器人的key
11
- # s:string类型,要发送的消息
12
- def send_vx(vx_key, s):
13
- vx_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' + vx_key
14
- headers = {"Content-Type": "text/plain"}
15
- data = {
16
- "msgtype": "text",
17
- "text": {
18
- "content": s,
19
- }
20
- }
21
- try:
22
- requests.post(url=vx_url, headers=headers, json=data, timeout=30)
23
- except:
24
- send_vx(vx_key, str(traceback.format_exc()))
25
-
26
-
27
- # 发送文件到企业微信机器人
28
- # vx_key: string类型,自己的企业微信机器人的key
29
- # file_path: string类型,文件地址
30
- def post_file(vx_key, file_path):
31
- id_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=' + vx_key + '&type=file'
32
- wx_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' + vx_key
33
- data = {'file': open(file_path, 'rb')}
34
- response = requests.post(url=id_url, files=data)
35
- json_res = response.json()
36
- media_id = json_res['media_id']
37
- data = {"msgtype": "file",
38
- "file": {"media_id": media_id}
39
- }
40
- try:
41
- requests.post(url=wx_url, json=data)
42
- except:
43
- send_vx(send_vx, str(traceback.format_exc()))
44
-
45
-
46
- # data: dataframe|string|dict|list|tuple|array
47
- # file_name: 带后缀的完整文件名
48
- # file_type: 文件类型,包括csv、excel、txt、json、sql
49
- def file_to_vx(vx_key, data, file_name):
50
- file_type = file_name.split('.')[-1]
51
- if file_type == "xls" or file_type == "xlsx":
52
- file_type = "excel"
53
- current_dir = os.getcwd()
54
- temp_dir = os.path.join(os.getcwd(), "tmp")
55
- if os.path.exists(temp_dir):
56
- pass
57
- else:
58
- os.makedirs(temp_dir)
59
- file_path = current_dir + "/" + file_name
60
- try:
61
- if isinstance(data, pd.DataFrame) and file_type != "txt":
62
- if file_type == "db3":
63
- conn = sqlite3.connect(file_path)
64
- data.to_sql('base_table', conn, if_exists='replace', index=False)
65
- post_file(vx_key, file_path)
66
- else:
67
- code_str = "data.to_" + file_type + "(file_path,index=False)"
68
- eval(code_str)
69
- post_file(vx_key, file_path)
70
- os.system('rm ' + file_path + '')
71
- else:
72
- if isinstance(data, dict):
73
- data_str = json.dumps(data, ensure_ascii=False)
74
- else:
75
- data_str = str(data)
76
- with open(file_path, 'w', encoding='utf-8') as f:
77
- f.write(data_str)
78
- except:
79
- send_vx(vx_key, str(traceback.format_exc()))
1
+ import sqlite3
2
+ import requests
3
+ import pandas as pd
4
+ import os
5
+ import json
6
+ import traceback
7
+
8
+
9
+ # c1d3a814-1a02-4bbd-b5c2-f756fef92cb8: b层机器人消息群-非聊天 的 pythonspark
10
+ # 013547da-3d78-4a7f-b4a7-e668b192c293: b层机器人消息群-非聊天 的 数仓B层服务端部署通知
11
+
12
+ # 发送消息到企业微信机器人
13
+ # vx_key: string类型,自己的企业微信机器人的key
14
+ # s:string类型,要发送的消息
15
+ def send_vx(vx_key, s, i=0):
16
+ vx_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' + vx_key
17
+ headers = {"Content-Type": "text/plain"}
18
+ data = {
19
+ "msgtype": "text",
20
+ "text": {
21
+ "content": s,
22
+ }
23
+ }
24
+ if i > 3:
25
+ raise Exception(str(traceback.format_exc()))
26
+ try:
27
+ requests.post(url=vx_url, headers=headers, json=data, timeout=30)
28
+ except:
29
+ i = i + 1
30
+ send_vx(vx_key, str(traceback.format_exc()), i)
31
+
32
+
33
+ # 发送文件到企业微信机器人
34
+ # vx_key: string类型,自己的企业微信机器人的key
35
+ # file_path: string类型,文件地址
36
+ def post_file(vx_key, file_path):
37
+ id_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=' + vx_key + '&type=file'
38
+ wx_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' + vx_key
39
+ data = {'file': open(file_path, 'rb')}
40
+ response = requests.post(url=id_url, files=data)
41
+ json_res = response.json()
42
+ media_id = json_res['media_id']
43
+ data = {"msgtype": "file",
44
+ "file": {"media_id": media_id}
45
+ }
46
+ try:
47
+ requests.post(url=wx_url, json=data)
48
+ except:
49
+ send_vx(send_vx, str(traceback.format_exc()))
50
+
51
+
52
+ # data: dataframe|string|dict|list|tuple|array
53
+ # file_name: 带后缀的完整文件名
54
+ # file_type: 文件类型,包括csv、excel、txt、json、sql
55
+ def file_to_vx(vx_key, data, file_name):
56
+ file_type = file_name.split('.')[-1]
57
+ if file_type == "xls" or file_type == "xlsx":
58
+ file_type = "excel"
59
+ current_dir = os.getcwd()
60
+ temp_dir = os.path.join(os.getcwd(), "tmp")
61
+ if os.path.exists(temp_dir):
62
+ pass
63
+ else:
64
+ os.makedirs(temp_dir)
65
+ file_path = current_dir + "/" + file_name
66
+ try:
67
+ if isinstance(data, pd.DataFrame) and file_type != "txt":
68
+ if file_type == "db3":
69
+ conn = sqlite3.connect(file_path)
70
+ data.to_sql('base_table', conn, if_exists='replace', index=False)
71
+ post_file(vx_key, file_path)
72
+ else:
73
+ code_str = "data.to_" + file_type + "(file_path,index=False)"
74
+ eval(code_str)
75
+ post_file(vx_key, file_path)
76
+ os.system('rm ' + file_path + '')
77
+ else:
78
+ if isinstance(data, dict):
79
+ data_str = json.dumps(data, ensure_ascii=False)
80
+ elif isinstance(data, list):
81
+ data_str = ""
82
+ for i in data:
83
+ if isinstance(i, dict):
84
+ data_str = data_str + json.dumps(i, ensure_ascii=False) + "\n"
85
+ else:
86
+ data_str = data_str + str(i) + "\n"
87
+ else:
88
+ data_str = str(data)
89
+ print(data_str[:100])
90
+ with open(file_path, 'w', encoding='utf-8') as f:
91
+ f.write(data_str)
92
+ post_file(vx_key, file_path)
93
+ except:
94
+ send_vx(vx_key, str(traceback.format_exc()))
95
+ os.system('rm -r' + temp_dir + '')