re-common 10.0.23__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.
@@ -0,0 +1,195 @@
1
+ # 某些业务中的字符串处理 算是特定场景的工具 不算通用工具
2
+ import re
3
+
4
+ from re_common.v2.baselibrary.utils.string_bool import is_all_symbols
5
+
6
+
7
+ def clean_organ_postcode(organ):
8
+ """
9
+ 格式化组织名称字符串,移除括号内容并删除独立的6位数字(邮政编码),然后清理标点。
10
+
11
+ 备注: 该方法替换java 里面的 formatOrgan
12
+
13
+ 参数:
14
+ organ (str): 输入的组织名称字符串,可能包含括号、分号和邮政编码。
15
+
16
+ 返回:
17
+ str: 格式化并清理后的组织名称字符串(无独立6位数字)。
18
+ """
19
+ # 如果输入为空,设为空字符串以避免后续操作报错
20
+ if not organ:
21
+ organ = ""
22
+
23
+ # 删除方括号和圆括号中的内容(包括括号本身)
24
+ organ = re.sub(r"\[.*?\]", "", organ) # 非贪婪匹配方括号内容
25
+ organ = re.sub(r"\(.*?\)", "", organ) # 非贪婪匹配圆括号内容
26
+
27
+ # 定义正则表达式,匹配独立的6位数字
28
+ # \b 表示单词边界,确保6位数字是独立的(前后不是字母、数字或下划线)
29
+ organ = re.sub(r"\b[0-9]{6}\b", "", organ)
30
+
31
+ # 初始化结果列表,用于存储处理后的组织名称部分
32
+ format_organ = []
33
+ # 按分号分割字符串,生成组织名称的各个部分
34
+ organ_parts = organ.split(";")
35
+
36
+ # 遍历每个部分,追加到结果列表
37
+ for temp_organ in organ_parts:
38
+ # 去除首尾多余空格后追加(避免因移除邮编导致的空字符串)
39
+ cleaned_part = temp_organ.strip()
40
+ # 如果首尾是标点符号,则移除
41
+ # 定义标点符号的正则表达式(这里包括常见标点)
42
+ punctuation = r"^[!,.?;:#$%^&*+-]+|[!,.?;:#$%^&*+-]+$"
43
+ cleaned_part = re.sub(punctuation, "", cleaned_part)
44
+ if cleaned_part: # 只追加非空部分
45
+ format_organ.append(cleaned_part)
46
+
47
+ # 用分号连接结果,转换为大写并清理标点
48
+ format_organ = ";".join(format_organ)
49
+
50
+ # 返回最终结果并去除首尾空格
51
+ return format_organ.strip()
52
+
53
+
54
+ def get_first_organ(organ):
55
+ if not organ:
56
+ return ""
57
+ organ_list = organ.strip().split(";")
58
+ for organ_one in organ_list:
59
+ # 清理邮政编码
60
+ organ_one = clean_organ_postcode(organ_one)
61
+ if organ_one.strip():
62
+ return organ_one
63
+
64
+ return ""
65
+
66
+
67
+ def get_first_author(author: str) -> str:
68
+ if not author:
69
+ return ""
70
+ au_list = author.strip().split(";")
71
+ for au in au_list:
72
+ au = re.sub("\\[.*?]", "", au)
73
+ au = re.sub("\\(.*?\\)", "", au)
74
+ if au.strip():
75
+ return au
76
+ return ""
77
+
78
+ def get_author_list(author: str):
79
+ lists = []
80
+ if not author:
81
+ return []
82
+ au_list = author.strip().split(";")
83
+ for au in au_list:
84
+ au = re.sub("\\[.*?]", "", au)
85
+ au = re.sub("\\(.*?\\)", "", au)
86
+ if au.strip():
87
+ lists.append(au.strip())
88
+ return lists
89
+
90
+
91
+ def get_scopus_author_abbr(author_row: str):
92
+ if not author_row:
93
+ return ""
94
+ author_list = author_row.split("&&")
95
+ if len(author_list) != 3:
96
+ raise Exception("错误的数据个数 可能来自其他数据源")
97
+
98
+ abbr_list = author_list[0].strip().split(";")
99
+ abbr_list = [author.strip() for author in abbr_list if
100
+ author.strip() and author.strip().lower() not in ("*", "and")]
101
+ return ";".join(abbr_list)
102
+
103
+
104
+ def get_wos_author_abbr(author_row: str):
105
+ if not author_row:
106
+ return ""
107
+ author_list = author_row.split("&&")
108
+ if len(author_list) != 4:
109
+ raise Exception("错误的数据个数 可能来自其他数据源")
110
+ abbr_list = []
111
+ abbr_list_au = author_list[0].strip().split(";")
112
+ abbr_list_ba = author_list[2].strip().split(";")
113
+ abbr_list.extend(abbr_list_au)
114
+ abbr_list.extend(abbr_list_ba)
115
+ abbr_list = [author.strip() for author in abbr_list if
116
+ author.strip() and author.strip().lower() not in ("*", "and")]
117
+ return ";".join(abbr_list)
118
+
119
+
120
+ def deal_rel_vol(vol_str: str):
121
+ """
122
+ 处理 期刊融合时的卷处理逻辑
123
+ """
124
+
125
+ # 如果卷是全符号 清理掉
126
+ if is_all_symbols(vol_str):
127
+ vol_str = ""
128
+
129
+ if vol_str.replace(".", "").isdigit():
130
+ try:
131
+ float_num = float(vol_str)
132
+ if int(float_num) == float_num:
133
+ return str(int(float_num))
134
+ except:
135
+ pass
136
+
137
+ if vol_str.lower().startswith("v "):
138
+ vol_str = vol_str.lower().replace("v ", "").strip()
139
+ return vol_str
140
+ if vol_str.lower().startswith("volume "):
141
+ vol_str = vol_str.lower().replace("volume ", "").strip()
142
+ return vol_str
143
+ if vol_str.lower().startswith("vol. "):
144
+ vol_str = vol_str.lower().replace("vol. ", "").strip()
145
+ return vol_str
146
+ if vol_str.lower().startswith("vol "):
147
+ vol_str = vol_str.lower().replace("vol ", "").strip()
148
+ return vol_str
149
+ return vol_str
150
+
151
+
152
+ def deal_num_strs(input_str):
153
+ """
154
+ int后在str 防止有浮点型的表达方式
155
+ """
156
+ number_list = re.findall(r'\d+', input_str)
157
+ transformed_numbers = [str(int(num)) for num in number_list]
158
+
159
+ # 替换原字符串中的数字为转换后的数字
160
+ for num, transformed_num in zip(number_list, transformed_numbers):
161
+ input_str = input_str.replace(num, transformed_num)
162
+ return input_str
163
+
164
+
165
+ def deal_num(num_str):
166
+ """
167
+ 将 期格式化 方便 group尤其是有横杆的数据
168
+ 该方法 为融合二次分割时使用,如果场景合适也可以用于其他地方
169
+ :param strs:
170
+ :return:
171
+ """
172
+ # 如果期是全符号清理掉
173
+ if is_all_symbols(num_str):
174
+ num_str = ""
175
+
176
+ if num_str.lower().startswith("n "):
177
+ num_str = num_str.lower().replace("n ", "").strip()
178
+
179
+ num_str = num_str.lower().replace("special_issue_", '').replace("_special_issue", '').replace("issue", "")
180
+ num_str = num_str.replace("spec.", "").replace("iss.", "").replace("spl.", "").replace("special.", "").replace(
181
+ "specialissue.", "")
182
+ num_str = num_str.replace("spec", "").replace("iss", "").replace("spl", "").replace("special", "").replace(
183
+ "specialissue", '')
184
+
185
+ num_str = num_str.replace("-", "_").replace(".", "_").upper()
186
+ num_str = num_str.lstrip("_").rstrip("_")
187
+ if num_str.find("_") > -1:
188
+ start, end = num_str.split("_")
189
+ start = deal_num_strs(start)
190
+ end = deal_num_strs(end)
191
+ num_str = start + "_" + end
192
+ else:
193
+ num_str = deal_num_strs(num_str)
194
+
195
+ return num_str.lower().strip()
File without changes
@@ -0,0 +1,6 @@
1
+ def assign_group_id(rows: list, sub_db_order: list):
2
+ subdb_keyid_map = {row.sub_db_id: row.keyid for row in rows}
3
+ for sub_db_id in sub_db_order:
4
+ if keyid := subdb_keyid_map.get(sub_db_id):
5
+ return keyid, len(rows), rows
6
+ return rows[0].keyid, len(rows), rows
@@ -6,10 +6,13 @@ import json
6
6
  import traceback
7
7
 
8
8
 
9
+ # c1d3a814-1a02-4bbd-b5c2-f756fef92cb8: b层机器人消息群-非聊天 的 pythonspark
10
+ # 013547da-3d78-4a7f-b4a7-e668b192c293: b层机器人消息群-非聊天 的 数仓B层服务端部署通知
11
+
9
12
  # 发送消息到企业微信机器人
10
13
  # vx_key: string类型,自己的企业微信机器人的key
11
14
  # s:string类型,要发送的消息
12
- def send_vx(vx_key, s):
15
+ def send_vx(vx_key, s, i=0):
13
16
  vx_url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=' + vx_key
14
17
  headers = {"Content-Type": "text/plain"}
15
18
  data = {
@@ -18,10 +21,13 @@ def send_vx(vx_key, s):
18
21
  "content": s,
19
22
  }
20
23
  }
24
+ if i > 3:
25
+ raise Exception(str(traceback.format_exc()))
21
26
  try:
22
27
  requests.post(url=vx_url, headers=headers, json=data, timeout=30)
23
28
  except:
24
- send_vx(vx_key, str(traceback.format_exc()))
29
+ i = i + 1
30
+ send_vx(vx_key, str(traceback.format_exc()), i)
25
31
 
26
32
 
27
33
  # 发送文件到企业微信机器人
@@ -71,9 +77,19 @@ def file_to_vx(vx_key, data, file_name):
71
77
  else:
72
78
  if isinstance(data, dict):
73
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"
74
87
  else:
75
88
  data_str = str(data)
89
+ print(data_str[:100])
76
90
  with open(file_path, 'w', encoding='utf-8') as f:
77
91
  f.write(data_str)
92
+ post_file(vx_key, file_path)
78
93
  except:
79
94
  send_vx(vx_key, str(traceback.format_exc()))
95
+ os.system('rm -r' + temp_dir + '')
@@ -3,6 +3,12 @@ import re
3
3
  import unicodedata
4
4
 
5
5
 
6
+ def is_ascii_alnum(char: str) -> bool:
7
+ # 精准判断是否为英文或数字字符(ASCII 范围)
8
+ # char.isalnum() 字母或数字(Unicode)包含中文等非英文字符
9
+ return char.isascii() and char.isalnum()
10
+
11
+
6
12
  def is_all_english_chars(s):
7
13
  return bool(re.match(r'^[A-Za-z]+$', s))
8
14
 
@@ -104,46 +110,77 @@ def is_all_symbols(text):
104
110
 
105
111
  def is_whole_word_en(sub_str: str, long_str: str) -> bool:
106
112
  """
107
- 判断 sub_str long_str 中是否是一个完整的单词(而不是其他单词的一部分)。
113
+ 判断 sub_str 是否作为 long_str 中的一个完整英文单词(不被其他单词嵌套)。
108
114
 
109
- 参数:
110
- sub_str: 要搜索的单词
111
- long_str: 被搜索的文本
115
+ 参数:
116
+ sub_str: 要搜索的英文子串
117
+ long_str: 被搜索的字符串
112
118
 
113
- 返回:
114
- bool: 如果 sub_str long_str 中的一个完整单词则返回 True,否则返回 False
115
- """
116
- regex_pattern = re.compile(r"[^a-z0-9]")
119
+ 返回:
120
+ True 表示 sub_str 是一个完整单词;False 表示是部分单词或不匹配。
121
+ """
122
+ # 用于 忽略大小写 进行匹配
123
+ regex_pattern = re.compile(r"[^a-z0-9]", re.IGNORECASE) # 用于判断非字母数字字符
117
124
 
118
125
  if not sub_str or not long_str:
119
126
  return False
120
127
 
121
- # 使用 startsWith 和 endsWith 检查边界
122
- if long_str.startswith(sub_str) and long_str.endswith(sub_str):
128
+ # 检查整段是否完全等于 sub_str
129
+ if long_str == sub_str:
123
130
  return True
124
131
 
125
- # 检查是否在中间位置,且前后有非字母数字字符
126
- index = long_str.find(sub_str)
127
- if index >= 0:
132
+ # 遍历所有 sub_str 的出现位置
133
+ index = 0
134
+ while index < len(long_str):
135
+ # 从字符串 long_str 的第 index 个位置开始,查找子串 sub_str 第一次出现的位置,并把它赋值给 index。
136
+ index = long_str.find(sub_str, index)
137
+ if index == -1:
138
+ break
139
+
140
+ # 检查 sub_str 前一个字符(如果有)是否为非字母数字
128
141
  if index == 0:
129
142
  is_start = True
130
143
  else:
131
144
  is_start = bool(regex_pattern.match(long_str[index - 1]))
132
145
 
133
- if len(long_str) == len(sub_str) + index:
146
+ # 检查 sub_str 后一个字符(如果有)是否为非字母数字
147
+ end_index = index + len(sub_str)
148
+ if end_index == len(long_str):
134
149
  is_end = True
135
150
  else:
136
- is_end = bool(regex_pattern.match(long_str[index + len(sub_str)]))
151
+ is_end = bool(regex_pattern.match(long_str[end_index]))
137
152
 
138
- return is_start and is_end
139
- else:
140
- return False
153
+ if is_start and is_end:
154
+ return True
155
+
156
+ # 移动索引继续查找
157
+ index += 1
158
+
159
+ return False
141
160
 
142
161
 
143
162
  def is_whole_word(sub_str: str, long_str: str) -> bool:
163
+ """
164
+ 判断 sub_str 是否为 long_str 中的一个完整词(适配中英文)。
165
+ 中文采用“包含”判断,英文采用完整词匹配。
166
+
167
+ 参数:
168
+ sub_str: 要搜索的子串(中英文均可)
169
+ long_str: 被搜索的字符串
170
+
171
+ 返回:
172
+ True 表示 sub_str 是一个完整词;False 否则。
173
+ """
144
174
  if contains_chinese_chars(sub_str):
145
- return True
146
- elif is_whole_word_en(sub_str, long_str):
147
- return True
175
+ # 子字符串完全包含在长字符串
176
+ is_contain = sub_str in long_str
177
+ # 是否是字母数字
178
+ if is_ascii_alnum(sub_str[0]) or is_ascii_alnum(sub_str[-1]):
179
+ # 表示中英文混合 看是否是截断单词即可
180
+ return is_whole_word_en(sub_str, long_str)
181
+ else:
182
+ # 中文子串只要被包含即可视为“完整词”
183
+ return is_contain
148
184
  else:
149
- return False
185
+ # 英文使用完整单词判断逻辑
186
+ return is_whole_word_en(sub_str, long_str)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.1
2
2
  Name: re_common
3
- Version: 10.0.23
3
+ Version: 10.0.24
4
4
  Summary: a library about all python projects
5
5
  Home-page: https://gitee.com/xujiangios/re-common
6
6
  Author: vic
@@ -11,14 +11,6 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.6
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
- Dynamic: author
15
- Dynamic: author-email
16
- Dynamic: classifier
17
- Dynamic: description
18
- Dynamic: description-content-type
19
- Dynamic: home-page
20
- Dynamic: requires-python
21
- Dynamic: summary
22
14
 
23
15
 
24
16
  这是一个基础类,依赖很多的第三方包,是一个用得到的第三方库的封装,可以在此基础上迅速构建项目
@@ -163,12 +163,15 @@ re_common/studio/streamlitstudio/first_app.py,sha256=t7Fw8YDlub7G9q99GgVo_3sPZXU
163
163
  re_common/studio/streamlitstudio/uber_pickups.py,sha256=cvrV5e8vRBM2_CpVDBE-f3V4mGFK9SqpRPZK8TEqr6U,785
164
164
  re_common/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
165
165
  re_common/v2/baselibrary/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
+ re_common/v2/baselibrary/business_utils/BusinessStringUtil.py,sha256=M3Pb9TB9QRePa9phjqx6JZV_igM-xRRa554iZ-WgyOo,6786
167
+ re_common/v2/baselibrary/business_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
+ re_common/v2/baselibrary/business_utils/rel_tools.py,sha256=LfnGFCkUSxg1SHvOMOQdP1PiHxIKqk7Syuk5YYpjJag,295
166
169
  re_common/v2/baselibrary/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
170
  re_common/v2/baselibrary/decorators/utils.py,sha256=Q4D6KKCQxvNBXZkPQQn14keKKJpGtg8TUSakjJU40s0,2056
168
171
  re_common/v2/baselibrary/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
172
  re_common/v2/baselibrary/s3object/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
173
  re_common/v2/baselibrary/s3object/baseboto3.py,sha256=mXuIFx99pnrPGQ4LJCZwlN1HLbaU-OWLwck0cVzW6hc,11203
171
- re_common/v2/baselibrary/tools/WeChatRobot.py,sha256=EaQgNncROAhU5-psYRGWAshIV5aEw-p2u1kYLpvr7RA,2796
174
+ re_common/v2/baselibrary/tools/WeChatRobot.py,sha256=sKBt2gPsfj0gzV6KaLSAhIhL-j3qNfHfqE-lII1LVwM,3537
172
175
  re_common/v2/baselibrary/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
176
  re_common/v2/baselibrary/tools/ac_ahocorasick.py,sha256=c63y5RtKVLD37nyPCnBqfNygwRj4gTQqyIdDOrC65G0,2847
174
177
  re_common/v2/baselibrary/tools/dict_tools.py,sha256=BTh7oJuJ619IZgxiYlim0ltrXBclDtb7WzyFGr7wVf0,1246
@@ -190,7 +193,7 @@ re_common/v2/baselibrary/utils/db.py,sha256=lr6SI1Bk7tA0nw_4vHbmz-OaisPlb_p9ziC1
190
193
  re_common/v2/baselibrary/utils/json_cls.py,sha256=M93piYtmgm_wP8E57culTrd_AhHLoGg6PqeAJYdW2SM,438
191
194
  re_common/v2/baselibrary/utils/mq.py,sha256=UHpO8iNIHs91Tgp-BgnSUpZwjWquxrGLdpr3FMMv2zw,2858
192
195
  re_common/v2/baselibrary/utils/n_ary_expression_tree.py,sha256=-05kO6G2Rth7CEK-5lfFrthFZ1Q0-0a7cni7mWZ-2gg,9172
193
- re_common/v2/baselibrary/utils/string_bool.py,sha256=S5HMemxl2S248p4sEakD1NFJccH1NMQcbOFGmSFfcbg,4695
196
+ re_common/v2/baselibrary/utils/string_bool.py,sha256=vxnjSFOfuHWGxkqaIbUNn21opx5tfV1uCXSahFfp1mU,6197
194
197
  re_common/v2/baselibrary/utils/string_clear.py,sha256=_bK8oi7t34JfFh8IVbe0fFexBzafFWow0r3QJ45HsyE,7212
195
198
  re_common/v2/baselibrary/utils/string_smi.py,sha256=cU0WAWHRGnGoVQx3eCEKeM_q_olFNzRTJe7rSe586SY,741
196
199
  re_common/v2/baselibrary/utils/stringutils.py,sha256=WuxhXJVU6xuGfgHiSjxrn7Go1eobpa8DMR3Icoey4vo,6039
@@ -220,8 +223,8 @@ re_common/vip/title/transform/TransformRegulationTitleToZt.py,sha256=LKRdIsWKues
220
223
  re_common/vip/title/transform/TransformStandardTitleToZt.py,sha256=-fCKAbSBzXVyQDCE61CalvR9E_QzQMA08QOO_NePFNI,5563
221
224
  re_common/vip/title/transform/TransformThesisTitleToZt.py,sha256=QS-uV0cQrpUFAcKucuJQ9Ue2VRQH-inmfn_X3IplfRo,5488
222
225
  re_common/vip/title/transform/__init__.py,sha256=m83-CWyRq_VHPYHaALEQlmXrkTdrZ3e4B_kCfBYE-uc,239
223
- re_common-10.0.23.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
224
- re_common-10.0.23.dist-info/METADATA,sha256=N4eRHjYZVktVW-rEm3J4y8LJmJs_4U42a-MgJlzoWck,764
225
- re_common-10.0.23.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
226
- re_common-10.0.23.dist-info/top_level.txt,sha256=_H9H23zoLIalm1AIY_KYTVh_H0ZnmjxQIxsvXtLv45o,10
227
- re_common-10.0.23.dist-info/RECORD,,
226
+ re_common-10.0.24.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
227
+ re_common-10.0.24.dist-info/METADATA,sha256=R1kT5A-yNJHQ3lvpchpqc3dX8ONJK1kuTfoGUQ08018,582
228
+ re_common-10.0.24.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
229
+ re_common-10.0.24.dist-info/top_level.txt,sha256=_H9H23zoLIalm1AIY_KYTVh_H0ZnmjxQIxsvXtLv45o,10
230
+ re_common-10.0.24.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5