qrpa 1.0.34__py3-none-any.whl → 1.1.50__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.
qrpa/temu_lib.py CHANGED
@@ -1,154 +1,156 @@
1
- from .fun_file import read_dict_from_file, write_dict_to_file, read_dict_from_file_ex, write_dict_to_file_ex
2
- from .fun_base import log, send_exception, md5_string, get_safe_value
3
- from .time_utils import TimeUtils
4
-
5
- import json, requests, time, math
6
-
7
- class TemuLib:
8
- def __init__(self, config, mobile, password, web_page):
9
- self.config = config
10
- self.web_page = web_page
11
- self.mobile = mobile
12
-
13
- self.dict_mall = {}
14
- self.cookie = self.doLoginToTemu(mobile, password)
15
-
16
- # 主账户登录 返回Cookie
17
- def doLoginToTemu(self, username, password):
18
- cache_cookie = f'{self.config.auto_dir}/temu/cookie/cookie_{username}.json'
19
- dict_cookie = read_dict_from_file(cache_cookie, 1)
20
- if len(dict_cookie) > 0:
21
- self.cookie = dict_cookie.get('cookie')
22
- return
23
-
24
- log(f'登录Temu账号: {username}')
25
-
26
- """使用 XPath 登录网站"""
27
- # 导航到登录页面
28
- self.web_page.goto("https://seller.kuajingmaihuo.com/login")
29
- # 输入用户名
30
- self.web_page.locator('//input[@id="usernameId"]').fill("")
31
- self.web_page.locator('//input[@id="usernameId"]').fill(username)
32
- # 输入密码
33
- self.web_page.locator('//input[@id="passwordId"]').fill("")
34
- self.web_page.locator('//input[@id="passwordId"]').fill(password)
35
- # 勾选隐私政策(checkbox)
36
- self.web_page.locator('//input[@type="checkbox"]/following-sibling::div').click() # 直接check不了 换成点击
37
- # 点击登录按钮
38
- self.web_page.locator('//button[span[text()="登录"]]').click()
39
- # 等待登录完成(根据页面加载情况调整等待策略)
40
- self.web_page.wait_for_load_state("load")
41
-
42
- while True:
43
- log('等待卖家中心出现')
44
- try:
45
- if self.web_page.locator('//div[text()="Temu商家中心"]').count() == 1:
46
- log('卖家中心已出现')
47
- break
48
- if self.web_page.locator('//div[text()="Seller Central"]').count() == 1:
49
- log('卖家中心已出现')
50
- break
51
- except Exception as e:
52
- log(f"❌{e}")
53
- time.sleep(1.5)
54
-
55
- log("✅ 登录成功")
56
-
57
- self.web_page.wait_for_load_state("load")
58
- self.web_page.wait_for_timeout(3000)
59
- cookies = self.web_page.context.cookies()
60
- cookies_list = [cookie for cookie in cookies if '.kuajingmaihuo.com' in cookie['domain']]
61
- self.cookie = '; '.join([f"{cookie['name']}={cookie['value']}" for cookie in cookies_list])
62
- log(f'已获取self.cookie:', self.cookie)
63
- write_dict_to_file(cache_cookie, {'cookie': self.cookie})
64
- return self.cookie
65
-
66
- def post_json(self, str_url, payload, mall_id=None):
67
- global response
68
- try:
69
- headers = {
70
- 'content-type': 'application/json',
71
- 'priority' : 'u=1, i',
72
- 'referer' : 'https://seller.kuajingmaihuo.com/settle/site-main',
73
- 'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
74
- 'Cookie' : self.cookie,
75
- }
76
- if mall_id:
77
- headers.update({'mallid': f"{mall_id}"})
78
- response = requests.post(str_url, headers=headers, data=json.dumps(payload))
79
- response.raise_for_status() # 如果响应不正常,会抛出异常
80
-
81
- response_text = response.json()
82
- error_code = response_text.get('error_code') or response_text.get('errorCode')
83
- if error_code != 1000000:
84
- raise send_exception(response_text)
85
- return response.json() # 直接返回 JSON 格式的数据
86
- except:
87
- raise send_exception()
88
-
89
- def get_shop_list(self):
90
- log(f'获取店铺列表')
91
- global DictMall
92
- url = "https://seller.kuajingmaihuo.com/bg/quiet/api/mms/userInfo"
93
- response_text = self.post_json(url, {})
94
-
95
- company_list = response_text['result']['companyList']
96
- mall_list = []
97
- for company in company_list:
98
- mallList = company['malInfoList']
99
- # shop_list = [['店铺ID', '店铺名称', '主账号', '店铺类型']]
100
- for mall in mallList:
101
- mall_id = str(mall['mallId'])
102
- mall_name = str(mall['mallName'])
103
- shop_info = [mall_id, mall_name, self.mobile, '半托管' if mall['isSemiManagedMall'] else '全托管']
104
- write_dict_to_file_ex(self.config.temu_store_info, {mall_id: shop_info}, [mall_id])
105
-
106
- self.dict_mall[str(mall['mallId'])] = mall['mallName']
107
-
108
- if not mall['isSemiManagedMall']:
109
- mall_list.append([str(mall['mallId']), mall['mallName'], '', self.mobile])
110
-
111
- return mall_list
112
-
113
- def get_funds_info(self, mall_id):
114
- log(f'获取 {self.dict_mall[mall_id]} 资金信息')
115
- url = "https://seller.kuajingmaihuo.com/api/merchant/payment/account/amount/info"
116
- response_text = self.post_json(url, {}, mall_id)
117
- total_amount = response_text.get('result').get('totalAmount')
118
- available_amount = response_text.get('result').get('availableBalance')
119
-
120
- NotifyItem = [self.dict_mall[mall_id], total_amount, available_amount, '', TimeUtils.current_datetime()]
121
-
122
- cache_file = f'{self.config.auto_dir}/temu/cache/funds_{TimeUtils.today_date()}.json'
123
- write_dict_to_file_ex(cache_file, {mall_id: NotifyItem}, [mall_id])
124
-
125
- return NotifyItem
126
-
127
- def list_warehouse(self, mall_id, mall_name):
128
- log(f'获取店铺 {mall_name} 销售商品列表 第1页')
129
- url = "https://seller.kuajingmaihuo.com/marvel-mms/cn/api/kiana/venom/sales/management/listWarehouse"
130
- payload = {
131
- "pageNo" : 1,
132
- "pageSize" : 40,
133
- "isLack" : 0,
134
- "selectStatusList" : [12], # 12 是已加入站点
135
- "priceAdjustRecentDays": 30 # 近30日价格调整
136
- }
137
- response_text = self.post_json(url, payload, mall_id)
138
-
139
- total = response_text['result']['total']
140
- subOrderListCount = len(response_text['result']['subOrderList'])
141
- totalPage = math.ceil(total / subOrderListCount) if subOrderListCount else 0
142
- subOrderList = response_text['result']['subOrderList']
143
-
144
- for page in range(2, totalPage + 1):
145
- log(f'获取店铺{mall_name}销售商品列表 第{page}/{totalPage}页')
146
- payload['pageNo'] = page
147
- response_text = self.post_json(url, payload, mall_id)
148
- subOrderList += response_text['result']['subOrderList']
149
- time.sleep(0.3)
150
-
151
- cache_file = f'{self.config.auto_dir}/temu/cache/warehouse_list_{TimeUtils.today_date()}.json'
152
- write_dict_to_file_ex(cache_file, {mall_id: subOrderList}, [mall_id])
153
-
154
- return subOrderList
1
+ from .fun_file import read_dict_from_file, write_dict_to_file, read_dict_from_file_ex, write_dict_to_file_ex
2
+ from .fun_base import log, send_exception, md5_string, get_safe_value
3
+ from .time_utils import TimeUtils
4
+
5
+ import json, requests, time, math
6
+
7
+ class TemuLib:
8
+ def __init__(self, config, mobile, password, web_page):
9
+ self.config = config
10
+ self.web_page = web_page
11
+ self.mobile = mobile
12
+
13
+ self.dict_mall = {}
14
+ self.cookie = self.doLoginToTemu(mobile, password)
15
+
16
+ # 主账户登录 返回Cookie
17
+ def doLoginToTemu(self, username, password):
18
+ cache_cookie = f'{self.config.auto_dir}/temu/cookie/cookie_{username}.json'
19
+ dict_cookie = read_dict_from_file(cache_cookie, 1)
20
+ if len(dict_cookie) > 0:
21
+ self.cookie = dict_cookie.get('cookie')
22
+ return
23
+
24
+ log(f'登录Temu账号: {username}')
25
+
26
+ """使用 XPath 登录网站"""
27
+ # 导航到登录页面
28
+ self.web_page.goto("https://seller.kuajingmaihuo.com/login")
29
+ # fixed
30
+ self.web_page.locator('//div[text()="账号登录"]').click()
31
+ # 输入用户名
32
+ self.web_page.locator('//input[@id="usernameId"]').fill("")
33
+ self.web_page.locator('//input[@id="usernameId"]').fill(username)
34
+ # 输入密码
35
+ self.web_page.locator('//input[@id="passwordId"]').fill("")
36
+ self.web_page.locator('//input[@id="passwordId"]').fill(password)
37
+ # 勾选隐私政策(checkbox)
38
+ self.web_page.locator('//input[@type="checkbox"]/following-sibling::div').click() # 直接check不了 换成点击
39
+ # 点击登录按钮
40
+ self.web_page.locator('//button[span[text()="登录"]]').click()
41
+ # 等待登录完成(根据页面加载情况调整等待策略)
42
+ self.web_page.wait_for_load_state("load")
43
+
44
+ while True:
45
+ log('等待卖家中心出现')
46
+ try:
47
+ if self.web_page.locator('//div[text()="Temu商家中心"]').count() == 1:
48
+ log('卖家中心已出现')
49
+ break
50
+ if self.web_page.locator('//div[text()="Seller Central"]').count() == 1:
51
+ log('卖家中心已出现')
52
+ break
53
+ except Exception as e:
54
+ log(f"❌{e}")
55
+ time.sleep(1.5)
56
+
57
+ log("✅ 登录成功")
58
+
59
+ self.web_page.wait_for_load_state("load")
60
+ self.web_page.wait_for_timeout(3000)
61
+ cookies = self.web_page.context.cookies()
62
+ cookies_list = [cookie for cookie in cookies if '.kuajingmaihuo.com' in cookie['domain']]
63
+ self.cookie = '; '.join([f"{cookie['name']}={cookie['value']}" for cookie in cookies_list])
64
+ log(f'已获取self.cookie:', self.cookie)
65
+ write_dict_to_file(cache_cookie, {'cookie': self.cookie})
66
+ return self.cookie
67
+
68
+ def post_json(self, str_url, payload, mall_id=None):
69
+ global response
70
+ try:
71
+ headers = {
72
+ 'content-type': 'application/json',
73
+ 'priority' : 'u=1, i',
74
+ 'referer' : 'https://seller.kuajingmaihuo.com/settle/site-main',
75
+ 'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
76
+ 'Cookie' : self.cookie,
77
+ }
78
+ if mall_id:
79
+ headers.update({'mallid': f"{mall_id}"})
80
+ response = requests.post(str_url, headers=headers, data=json.dumps(payload))
81
+ response.raise_for_status() # 如果响应不正常,会抛出异常
82
+
83
+ response_text = response.json()
84
+ error_code = response_text.get('error_code') or response_text.get('errorCode')
85
+ if error_code != 1000000:
86
+ raise send_exception(response_text)
87
+ return response.json() # 直接返回 JSON 格式的数据
88
+ except:
89
+ raise send_exception()
90
+
91
+ def get_shop_list(self):
92
+ log(f'获取店铺列表')
93
+ global DictMall
94
+ url = "https://seller.kuajingmaihuo.com/bg/quiet/api/mms/userInfo"
95
+ response_text = self.post_json(url, {})
96
+
97
+ company_list = response_text['result']['companyList']
98
+ mall_list = []
99
+ for company in company_list:
100
+ mallList = company['malInfoList']
101
+ # shop_list = [['店铺ID', '店铺名称', '主账号', '店铺类型']]
102
+ for mall in mallList:
103
+ mall_id = str(mall['mallId'])
104
+ mall_name = str(mall['mallName'])
105
+ shop_info = [mall_id, mall_name, self.mobile, '半托管' if mall['isSemiManagedMall'] else '全托管']
106
+ write_dict_to_file_ex(self.config.temu_store_info, {mall_id: shop_info}, [mall_id])
107
+
108
+ self.dict_mall[str(mall['mallId'])] = mall['mallName']
109
+
110
+ if not mall['isSemiManagedMall']:
111
+ mall_list.append([str(mall['mallId']), mall['mallName'], '', self.mobile])
112
+
113
+ return mall_list
114
+
115
+ def get_funds_info(self, mall_id):
116
+ log(f'获取 {self.dict_mall[mall_id]} 资金信息')
117
+ url = "https://seller.kuajingmaihuo.com/api/merchant/payment/account/amount/info"
118
+ response_text = self.post_json(url, {}, mall_id)
119
+ total_amount = response_text.get('result').get('totalAmount')
120
+ available_amount = response_text.get('result').get('availableBalance')
121
+
122
+ NotifyItem = [self.dict_mall[mall_id], total_amount, available_amount, '', TimeUtils.current_datetime()]
123
+
124
+ cache_file = f'{self.config.auto_dir}/temu/cache/funds_{TimeUtils.today_date()}.json'
125
+ write_dict_to_file_ex(cache_file, {mall_id: NotifyItem}, [mall_id])
126
+
127
+ return NotifyItem
128
+
129
+ def list_warehouse(self, mall_id, mall_name):
130
+ log(f'获取店铺 {mall_name} 销售商品列表 第1页')
131
+ url = "https://seller.kuajingmaihuo.com/marvel-mms/cn/api/kiana/venom/sales/management/listWarehouse"
132
+ payload = {
133
+ "pageNo" : 1,
134
+ "pageSize" : 40,
135
+ "isLack" : 0,
136
+ "selectStatusList" : [12], # 12 是已加入站点
137
+ "priceAdjustRecentDays": 30 # 近30日价格调整
138
+ }
139
+ response_text = self.post_json(url, payload, mall_id)
140
+
141
+ total = response_text['result']['total']
142
+ subOrderListCount = len(response_text['result']['subOrderList'])
143
+ totalPage = math.ceil(total / subOrderListCount) if subOrderListCount else 0
144
+ subOrderList = response_text['result']['subOrderList']
145
+
146
+ for page in range(2, totalPage + 1):
147
+ log(f'获取店铺{mall_name}销售商品列表 第{page}/{totalPage}页')
148
+ payload['pageNo'] = page
149
+ response_text = self.post_json(url, payload, mall_id)
150
+ subOrderList += response_text['result']['subOrderList']
151
+ time.sleep(0.3)
152
+
153
+ cache_file = f'{self.config.auto_dir}/temu/cache/warehouse_list_{TimeUtils.today_date()}.json'
154
+ write_dict_to_file_ex(cache_file, {mall_id: subOrderList}, [mall_id])
155
+
156
+ return subOrderList