qrpa 1.0.84__tar.gz → 1.0.86__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.

Potentially problematic release.


This version of qrpa might be problematic. Click here for more details.

Files changed (37) hide show
  1. {qrpa-1.0.84 → qrpa-1.0.86}/PKG-INFO +1 -1
  2. {qrpa-1.0.84 → qrpa-1.0.86}/pyproject.toml +1 -1
  3. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_lib.py +97 -202
  4. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa.egg-info/PKG-INFO +1 -1
  5. {qrpa-1.0.84 → qrpa-1.0.86}/README.md +0 -0
  6. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/RateLimitedSender.py +0 -0
  7. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/__init__.py +0 -0
  8. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/db_migrator.py +0 -0
  9. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/feishu_bot_app.py +0 -0
  10. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/feishu_client.py +0 -0
  11. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/feishu_logic.py +0 -0
  12. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/fun_base.py +0 -0
  13. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/fun_excel.py +0 -0
  14. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/fun_file.py +0 -0
  15. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/fun_web.py +0 -0
  16. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/fun_win.py +0 -0
  17. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/mysql_module/__init__.py +0 -0
  18. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/mysql_module/shein_product_model.py +0 -0
  19. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/mysql_module/shein_return_order_model.py +0 -0
  20. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_daily_report_model.py +0 -0
  21. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_excel.py +0 -0
  22. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_mysql.py +0 -0
  23. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_sqlite.py +0 -0
  24. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/shein_ziniao.py +0 -0
  25. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/temu_chrome.py +0 -0
  26. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/temu_excel.py +0 -0
  27. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/temu_lib.py +0 -0
  28. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/time_utils.py +0 -0
  29. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/time_utils_example.py +0 -0
  30. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa/wxwork.py +0 -0
  31. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa.egg-info/SOURCES.txt +0 -0
  32. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa.egg-info/dependency_links.txt +0 -0
  33. {qrpa-1.0.84 → qrpa-1.0.86}/qrpa.egg-info/top_level.txt +0 -0
  34. {qrpa-1.0.84 → qrpa-1.0.86}/setup.cfg +0 -0
  35. {qrpa-1.0.84 → qrpa-1.0.86}/setup.py +0 -0
  36. {qrpa-1.0.84 → qrpa-1.0.86}/tests/test_db_migrator.py +0 -0
  37. {qrpa-1.0.84 → qrpa-1.0.86}/tests/test_wxwork.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.0.84
3
+ Version: 1.0.86
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "qrpa"
7
- version = "1.0.84"
7
+ version = "1.0.86"
8
8
  description = "qsir's rpa library"
9
9
  authors = [{ name = "QSir", email = "1171725650@qq.com" }]
10
10
  readme = "README.md"
@@ -27,37 +27,39 @@ class SheinLib:
27
27
 
28
28
  self.deal_auth()
29
29
 
30
- # 处理鉴权 - 优化版本
30
+ # 处理鉴权
31
31
  def deal_auth(self):
32
32
  web_page = self.web_page
33
33
 
34
+ # 等待页面稳定
35
+ try:
36
+ web_page.wait_for_load_state("networkidle", timeout=10000)
37
+ except Exception as e:
38
+ log(f"等待页面稳定超时: {e}", self.store_username, self.store_name)
39
+
40
+ web_page.wait_for_timeout(2000)
41
+
34
42
  # 定义最大重试次数
35
- MAX_RETRIES = 3 # 减少重试次数,避免过度重试
43
+ MAX_RETRIES = 5
36
44
  retries = 0
37
45
  wait_count = 0
38
46
  is_send = False
39
47
 
48
+ # close_modal(web_page) # 不能开启 需要勾选协议弹窗
49
+
40
50
  while retries < MAX_RETRIES:
41
51
  try:
42
- # 检查页面是否已崩溃,如果是则重新创建页面
43
- if self.is_page_crashed():
44
- self.recreate_page()
45
- web_page = self.web_page
46
52
 
47
- # 等待页面稳定加载
48
- self.wait_for_page_stable()
53
+ retries += 1
49
54
 
50
55
  while not web_page.locator('//div[contains(text(),"商家后台")]').nth(1).is_visible():
51
56
 
52
- # 处理鉴权确定按钮
53
57
  if web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).is_visible():
54
58
  if 'https://sso.geiwohuo.com/#/home' not in web_page.url:
55
59
  log("鉴权确定按钮可见 点击'确定'按钮", web_page.title(), web_page.url, self.store_username, self.store_name)
56
60
  web_page.locator('xpath=//div[@id="container" and @alita-name="gmpsso"]//button[@type="button" and @id]').nth(0).click()
57
- # 等待导航完成
58
- self.wait_for_navigation()
61
+ web_page.wait_for_timeout(5000)
59
62
 
60
- # 处理验证码
61
63
  while web_page.locator('//div[text()="验证码"]').is_visible():
62
64
  log(f'等待输入验证码: {wait_count}', self.store_username, self.store_name)
63
65
  if not is_send:
@@ -68,223 +70,116 @@ class SheinLib:
68
70
  time.sleep(5)
69
71
  wait_count += 1
70
72
 
71
- # 处理协议签署
72
- self.handle_agreement()
73
+ if web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
74
+ while web_page.locator('//div[contains(text(),"同意签署协议")]').count() == 0:
75
+ log('等待协议内容出现')
76
+ web_page.wait_for_timeout(1000)
77
+
78
+ if web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
79
+ log('检测到同意签署协议')
80
+ web_page.wait_for_timeout(1000)
81
+ log('点击同意复选框')
82
+ web_page.locator('//i[@class="so-checkinput-indicator so-checkinput-checkbox"]').click()
83
+ web_page.wait_for_timeout(1000)
84
+ log('点击同意按钮')
85
+ web_page.locator('//button[span[text()="同意"]]').click()
73
86
 
74
- # 处理登录按钮
75
87
  if web_page.locator('//input[@name="username"]').is_visible():
76
88
  log("用户名输入框可见 等待5秒点击'登录'按钮", self.store_username, self.store_name)
77
89
  web_page.wait_for_timeout(5000)
78
90
  log('点击"登录"', self.store_username, self.store_name)
79
91
  web_page.locator('//button[contains(@class,"login_btn")]').click()
80
- # 等待登录完成
81
- self.wait_for_navigation()
82
92
 
83
- # 检查是否已成功进入商品管理
93
+ log('再延时5秒', self.store_username, self.store_name)
94
+ web_page.wait_for_timeout(5000)
95
+
84
96
  if web_page.locator('//span[contains(text(),"商品管理")]').nth(1).is_visible():
85
97
  log('商品管理菜单可见 退出鉴权处理', self.store_username, self.store_name)
86
98
  return
87
99
 
88
- # 处理各种页面状态
89
- self.handle_page_states()
100
+ log('商家后台不可见', web_page.title(), web_page.url, self.store_username, self.store_name)
101
+ if 'https://sso.geiwohuo.com/#/home' in web_page.url:
102
+ web_page.wait_for_timeout(5000)
103
+ web_page.reload()
104
+
105
+ # while r'=/CN' in web_page.url:
106
+ # safe_goto(web_page, 'https://sso.geiwohuo.com/#/home?q=0')
107
+ #
108
+ # web_page.wait_for_timeout(5000)
109
+ # if web_page.locator('//input[@name="username"]').is_visible():
110
+ # log("用户名输入框可见 等待5秒点击'登录'按钮", self.store_username, self.store_name)
111
+ # web_page.wait_for_timeout(5000)
112
+ # log('点击"登录"', self.store_username, self.store_name)
113
+ # web_page.locator('//button[contains(@class,"login_btn")]').click()
114
+ #
115
+ # log('再延时5秒', self.store_username, self.store_name)
116
+ # web_page.wait_for_timeout(5000)
90
117
 
91
118
  web_page.wait_for_timeout(3000)
92
119
 
93
- # 检查成功条件
94
- if self.is_auth_successful():
95
- break
120
+ if 'https://sso.geiwohuo.com/#/home' in web_page.url:
121
+
122
+ if 'SHEIN全球商家中心' in web_page.title() or '后台首页' in web_page.title() or '商家后台' in web_page.title():
123
+ log(web_page.title(), '中断循环', self.store_username, self.store_name)
124
+ web_page.wait_for_timeout(5000)
125
+ break
126
+
127
+ if 'mrs.biz.sheincorp.cn' in web_page.url and '商家后台' in web_page.title():
128
+ try:
129
+ web_page.goto('https://sso.geiwohuo.com/#/home?q=1', wait_until='domcontentloaded', timeout=10000)
130
+ web_page.wait_for_timeout(3000)
131
+ except Exception as nav_error:
132
+ log(f"导航失败,尝试重新加载: {nav_error}", self.store_username, self.store_name)
133
+ web_page.reload(wait_until='domcontentloaded', timeout=10000)
134
+ web_page.wait_for_timeout(5000)
135
+
136
+ if web_page.locator('//h1[contains(text(),"鉴权")]').is_visible():
137
+ log('检测到鉴权 刷新页面', self.store_username, self.store_name)
138
+ web_page.reload()
139
+ web_page.wait_for_timeout(5000)
140
+ web_page.reload()
141
+ web_page.wait_for_timeout(5000)
96
142
 
97
- break
143
+ if web_page.title() == 'SHEIN':
144
+ try:
145
+ web_page.goto('https://sso.geiwohuo.com/#/home?q=2', wait_until='domcontentloaded', timeout=10000)
146
+ web_page.wait_for_timeout(3000)
147
+ except Exception as nav_error:
148
+ log(f"导航失败,尝试重新加载: {nav_error}", self.store_username, self.store_name)
149
+ web_page.reload(wait_until='domcontentloaded', timeout=10000)
150
+ web_page.wait_for_timeout(5000)
98
151
 
152
+ break
99
153
  except Exception as e:
100
154
  log(f"错误发生: {e}, 重试中...({self.store_username}, {self.store_name})")
101
155
  log(traceback.format_exc())
102
-
103
- # 特殊处理页面崩溃错误
104
156
  if 'crashed' in str(e):
105
- log("检测到页面崩溃,尝试恢复...")
106
- self.handle_page_crash()
107
-
157
+ try:
158
+ log("检测到页面崩溃,尝试重建页面", self.store_username, self.store_name)
159
+ context = web_page.context
160
+ web_page.close()
161
+ web_page = context.new_page()
162
+ self.web_page = web_page
163
+ web_page.goto('https://sso.geiwohuo.com/#/home', wait_until='domcontentloaded', timeout=15000)
164
+ web_page.wait_for_timeout(3000)
165
+ log("页面重建成功", self.store_username, self.store_name)
166
+ except Exception as recovery_error:
167
+ log(f"页面重建失败: {recovery_error}", self.store_username, self.store_name)
168
+ try:
169
+ web_page.reload(wait_until='domcontentloaded', timeout=10000)
170
+ web_page.wait_for_timeout(3000)
171
+ except:
172
+ web_page.wait_for_timeout(5000)
108
173
  retries += 1
109
174
  if retries >= MAX_RETRIES:
110
175
  log(f"达到最大重试次数,停止尝试({self.store_username}, {self.store_name})")
111
- raise e # 重新抛出异常以便上层处理
112
-
113
- # 指数退避等待
114
- time.sleep(2 ** retries)
115
-
116
- # 辅助方法
117
- def is_page_crashed(self):
118
- """检查页面是否已崩溃"""
119
- try:
120
- # 尝试访问页面基本属性
121
- self.web_page.url
122
- self.web_page.title()
123
- return False
124
- except Exception as e:
125
- if 'crashed' in str(e):
126
- return True
127
- return False
128
-
129
- def recreate_page(self):
130
- """重新创建页面实例"""
131
- try:
132
- # 关闭当前页面
133
- if hasattr(self, 'web_page') and self.web_page:
134
- try:
135
- self.web_page.close()
136
- except:
137
- pass
138
-
139
- # 重新创建页面
140
- self.web_page = self.browser.new_page()
141
-
142
- # 设置页面选项
143
- self.web_page.set_default_timeout(30000) # 30秒超时
144
- self.web_page.set_default_navigation_timeout(30000)
145
-
146
- # 导航到目标页面
147
- self.safe_goto('https://sso.geiwohuo.com/#/home')
148
-
149
- except Exception as e:
150
- log(f"重新创建页面失败: {e}")
151
- raise
176
+ break
177
+ time.sleep(2) # 错误时等待2秒后重试
152
178
 
153
- def wait_for_page_stable(self, timeout=10000):
154
- """等待页面稳定加载"""
155
- try:
156
- # 等待网络空闲
157
- self.web_page.wait_for_load_state('networkidle', timeout=timeout)
158
- # 额外等待一下确保JavaScript执行完成
159
- self.web_page.wait_for_timeout(2000)
160
- except Exception as e:
161
- log(f"等待页面稳定超时: {e}")
162
-
163
- def wait_for_navigation(self, timeout=30000):
164
- """等待导航完成"""
165
- try:
166
- self.web_page.wait_for_load_state('networkidle', timeout=timeout)
167
- self.web_page.wait_for_timeout(2000)
168
- except Exception as e:
169
- log(f"等待导航完成超时: {e}")
170
-
171
- def safe_goto(self, url, retries=3):
172
- """安全的页面导航"""
173
- for i in range(retries):
174
- try:
175
- # 设置较长的超时时间处理302重定向
176
- response = self.web_page.goto(url, wait_until='networkidle', timeout=60000)
177
-
178
- # 检查响应状态
179
- if response and response.status >= 400:
180
- log(f"页面返回错误状态: {response.status}")
181
- if i < retries - 1:
182
- time.sleep(2)
183
- continue
184
-
185
- # 等待页面稳定
186
- self.wait_for_page_stable()
187
- return
188
-
189
- except Exception as e:
190
- log(f"导航到 {url} 失败 (尝试 {i + 1}/{retries}): {e}")
191
- if 'crashed' in str(e):
192
- # 页面崩溃,需要重新创建
193
- if i < retries - 1:
194
- self.recreate_page()
195
- continue
196
- else:
197
- raise
198
-
199
- if i < retries - 1:
200
- time.sleep(2 ** i) # 指数退避
201
- continue
202
- raise
203
-
204
- def handle_agreement(self):
205
- """处理协议签署"""
206
- if self.web_page.locator('//div[contains(text(),"同意签署协议")]').count() > 0:
207
- # 等待协议内容完全加载
208
- self.web_page.wait_for_selector('//div[contains(text(),"同意签署协议")]', timeout=10000)
209
- log('检测到同意签署协议')
210
- self.web_page.wait_for_timeout(1000)
211
- log('点击同意复选框')
212
- self.web_page.locator('//i[@class="so-checkinput-indicator so-checkinput-checkbox"]').click()
213
- self.web_page.wait_for_timeout(1000)
214
- log('点击同意按钮')
215
- self.web_page.locator('//button[span[text()="同意"]]').click()
216
- # 等待处理完成
217
- self.wait_for_navigation()
218
-
219
- def handle_page_states(self):
220
- """处理各种页面状态"""
221
- current_url = self.web_page.url
222
- current_title = self.web_page.title()
223
-
224
- log(f'当前页面状态 - URL: {current_url}, Title: {current_title}', self.store_username, self.store_name)
225
-
226
- if 'https://sso.geiwohuo.com/#/home' in current_url:
227
- if current_title == 'SHEIN' or '后台首页' in current_title or '商家后台' in current_title:
228
- log(f'{current_title} 页面加载完成', self.store_username, self.store_name)
229
- self.web_page.wait_for_timeout(5000)
230
- else:
231
- # 页面可能还在加载,刷新一下
232
- self.web_page.reload()
233
- self.wait_for_page_stable()
234
-
235
- elif 'mrs.biz.sheincorp.cn' in current_url and '商家后台' in current_title:
236
- self.safe_goto('https://sso.geiwohuo.com/#/home?q=1')
237
-
238
- elif self.web_page.locator('//h1[contains(text(),"鉴权")]').is_visible():
239
- log('检测到鉴权页面,刷新页面', self.store_username, self.store_name)
240
- self.web_page.reload()
241
- self.wait_for_page_stable()
242
-
243
- elif current_title == 'SHEIN' and 'sso.geiwohuo.com' not in current_url:
244
- self.safe_goto('https://sso.geiwohuo.com/#/home?q=2')
245
-
246
- def is_auth_successful(self):
247
- """检查鉴权是否成功"""
248
- try:
249
- current_url = self.web_page.url
250
- current_title = self.web_page.title()
251
-
252
- success_conditions = [
253
- 'SHEIN全球商家中心' in current_title,
254
- '后台首页' in current_title,
255
- '商家后台' in current_title,
256
- self.web_page.locator('//span[contains(text(),"商品管理")]').nth(1).is_visible()
257
- ]
258
-
259
- return any(success_conditions)
260
- except:
261
- return False
262
-
263
- def handle_page_crash(self):
264
- """处理页面崩溃"""
265
- try:
266
- log("处理页面崩溃...")
267
-
268
- # 如果是特定URL的崩溃,直接导航到安全页面
269
- if hasattr(self, 'web_page'):
270
- try:
271
- current_url = self.web_page.url
272
- if 'https://sso.geiwohuo.com//#/auth/SSLS' in current_url:
273
- self.safe_goto('https://sso.geiwohuo.com/#/home?q=3')
274
- return
275
- except:
276
- pass
277
-
278
- # 重新创建页面
279
- self.recreate_page()
280
-
281
- except Exception as e:
282
- log(f"处理页面崩溃失败: {e}")
283
- raise
284
179
  log('鉴权处理结束')
285
180
  # web_page.wait_for_load_state("load")
286
181
  # web_page.wait_for_load_state("networkidle")
287
- self.web_page.wait_for_timeout(3000)
182
+ web_page.wait_for_timeout(3000)
288
183
 
289
184
  # 获取质检报告pdf地址
290
185
  def get_qc_report_url(self, deliverCode, purchaseCode):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qrpa
3
- Version: 1.0.84
3
+ Version: 1.0.86
4
4
  Summary: qsir's rpa library
5
5
  Author: QSir
6
6
  Author-email: QSir <1171725650@qq.com>
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
File without changes
File without changes