douyin_user_operate.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. import time
  2. from func.action_func import del_key_vague
  3. from task.task_job import callback_task
  4. from tools import loggerKit, redis_client
  5. from scene.oprator.atom_data import start_app, stop_app, single_click_by_control, \
  6. send_text_by_control, single_click_by_text, get_text_by_control, click_pic
  7. from tools.pic_base64_util import pic_to_base64
  8. import requests
  9. import json
  10. import threading
  11. import yaml
  12. import httpx
  13. with open('config.yaml', 'r') as file:
  14. config = yaml.load(file, Loader=yaml.FullLoader)
  15. extern_domain = config['bmp-cp']['extern_domain']
  16. # 调用AIGC接口
  17. post_ai_gc_url = config['bmp-cp']['post_ai_gc_url']
  18. # 任务执行回调url
  19. task_callback_url = extern_domain + config['bmp-cp']['task_callback_url']
  20. # 抖音极速版用户操作(对指定用户作品进行点赞 评论和收藏)
  21. # version 28.8.0
  22. def douyin_spider(task_id, keyword, data):
  23. loggerKit.info('请求信息:{0}'.format(data))
  24. device_id = data.get("deviceID")
  25. perform_action_id = data.get("performActionId")
  26. result = data.get("result")
  27. if result is not None:
  28. """
  29. 非首个指令
  30. """
  31. perform_action_result = result.get("performActionResult")
  32. if perform_action_result is None:
  33. return_dict = {
  34. "data": "",
  35. "code": -2,
  36. "message": "fail, performActionResult is null"
  37. }
  38. # 回调任务中心
  39. del_key_vague(device_id)
  40. callback_task(500, '指令执行失败', task_id, device_id, 0, None)
  41. return return_dict
  42. if perform_action_result != "success":
  43. # 回调任务中心
  44. return_dict = {
  45. "data": "",
  46. "code": -2,
  47. "message": "fail, performActionResult is null"
  48. }
  49. del_key_vague(device_id)
  50. callback_task(500, '任务执行失败,可能当日已签到过', task_id, device_id, 0, None)
  51. return return_dict
  52. # 每次操作完成后会将对应的操作唯一id存储到redis,并且返回给手机端 手机端下次带着上个操作id来执行下一个操作
  53. last_action_id = redis_client.get(device_id + "operate")
  54. step0 = redis_client.get(f"{device_id}_step0")
  55. if step0 is not None and int(step0) == 1 and last_action_id is not None and int(perform_action_id) == int(
  56. last_action_id) and perform_action_result == "success":
  57. action1_id = int(round(time.time() * 1000))
  58. """
  59. 发送第1条指令
  60. 点击急速版抖音搜索按钮
  61. """
  62. action1_dict = single_click_by_control(action1_id, target_app="douyin", target_version="28.8.0",
  63. package_name="com.ss.android.ugc.aweme.lite",
  64. control_id="com.ss.android.ugc.aweme.lite:id/hvy",
  65. control_ids="com.ss.android.ugc.aweme.lite:id/hvy,"
  66. "com.ss.android.ugc.aweme.lite:id/lf3")
  67. redis_client.set(device_id + "operate", action1_id)
  68. redis_client.set(f"{device_id}_step1", "1")
  69. redis_client.delete(f"{device_id}_step0")
  70. loggerKit.info("设备:{0}, action1_id:{1}", device_id, action1_id)
  71. return action1_dict
  72. step1 = redis_client.get(f"{device_id}_step1")
  73. if step1 is not None and int(step1) == 1 and last_action_id is not None and int(perform_action_id) == int(
  74. last_action_id) and perform_action_result == "success":
  75. loggerKit.info("设备:{0}, action2_id_mem:{1}", device_id, int(last_action_id))
  76. action2_id = int(round(time.time() * 1000))
  77. """
  78. 发送第2条指令
  79. 对搜索框进行赋值
  80. """
  81. action2_dict = send_text_by_control(action2_id, target_app="douyin", target_version="28.8.0",
  82. package_name="com.ss.android.ugc.aweme.lite",
  83. control_id="com.ss.android.ugc.aweme.lite:id/et_search_kw",
  84. content=keyword, timeout=5)
  85. redis_client.set(device_id + "operate", action2_id)
  86. redis_client.set(f"{device_id}_step2", "1")
  87. redis_client.delete(f"{device_id}_step1")
  88. loggerKit.info("设备:{0}, action2_id:{1}", device_id, action2_id)
  89. return action2_dict
  90. step2 = redis_client.get(f"{device_id}_step2")
  91. if step2 is not None and int(step2) == 1 and last_action_id is not None and int(perform_action_id) == int(
  92. last_action_id) and perform_action_result == "success":
  93. loggerKit.info("设备:{0}, action3_id_mem:{1}", device_id, int(last_action_id))
  94. action3_id = int(round(time.time() * 1000))
  95. """
  96. 发送第3条指令
  97. 点击搜索按钮 根据图片识别
  98. """
  99. action3_dict = single_click_by_control(action3_id, target_app="douyin", target_version="28.8.0",
  100. package_name="com.ss.android.ugc.aweme.lite",
  101. control_id="com.ss.android.ugc.aweme.lite:id/nup")
  102. redis_client.set(device_id + "operate", action3_id)
  103. redis_client.set(f"{device_id}_step3", "1")
  104. redis_client.delete(f"{device_id}_step2")
  105. loggerKit.info("设备:{0}, action3_id:{1}", device_id, action3_id)
  106. return action3_dict
  107. step3 = redis_client.get(f"{device_id}_step3")
  108. if step3 is not None and int(step3) == 1 and last_action_id is not None and int(perform_action_id) == int(
  109. last_action_id) \
  110. and perform_action_result == "success":
  111. loggerKit.info("设备:{0}, action4_id_mem:{1}", device_id, int(last_action_id))
  112. action4_id = int(round(time.time() * 1000))
  113. """
  114. 发送第4条指令
  115. 点击用户按钮
  116. """
  117. action4_dict = single_click_by_text(action4_id, target_app="douyin", target_version="28.8.0",
  118. package_name="com.ss.android.ugc.aweme.lite",
  119. text="用户", timeout=5)
  120. redis_client.set(device_id + "operate", action4_id)
  121. redis_client.set(f"{device_id}_step4", "1")
  122. redis_client.delete(f"{device_id}_step3")
  123. loggerKit.info("设备:{0}, action4_id:{1}", device_id, action4_id)
  124. return action4_dict
  125. step4 = redis_client.get(f"{device_id}_step4")
  126. if step4 is not None and int(step4) == 1 and last_action_id is not None and int(perform_action_id) == int(
  127. last_action_id) \
  128. and perform_action_result == "success":
  129. loggerKit.info("设备:{0}, action5_id_mem:{1}", device_id, int(last_action_id))
  130. action5_id = int(round(time.time() * 1000))
  131. """
  132. 发送第5条指令
  133. 点击用户tab下的第一个用户
  134. """
  135. action5_dict = single_click_by_control(action5_id, target_app="douyin", target_version="28.8.0",
  136. package_name="com.ss.android.ugc.aweme.lite",
  137. item_index=0,
  138. control_id="com.ss.android.ugc.aweme.lite:id/gzs", timeout=5)
  139. redis_client.set(device_id + "operate", action5_id)
  140. redis_client.set(f"{device_id}_step5", "1")
  141. redis_client.delete(f"{device_id}_step4")
  142. loggerKit.info("设备:{0}, action5_id:{1}", device_id, action5_id)
  143. return action5_dict
  144. step5 = redis_client.get(f"{device_id}_step5")
  145. if step5 is not None and int(step5) == 1 and last_action_id is not None and int(perform_action_id) == int(
  146. last_action_id) \
  147. and perform_action_result == "success":
  148. loggerKit.info("设备:{0}, action6_id_mem:{1}", device_id, int(last_action_id))
  149. action6_id = int(round(time.time() * 1000))
  150. """
  151. 发送第6条指令
  152. 进入用户对应的视频
  153. """
  154. action6_dict = single_click_by_control(action6_id, target_app="douyin", target_version="28.8.0",
  155. package_name="com.ss.android.ugc.aweme.lite",
  156. control_id="com.ss.android.ugc.aweme.lite:id/hld", timeout=5)
  157. redis_client.set(device_id + "operate", action6_id)
  158. redis_client.set(f"{device_id}_step6", "1")
  159. redis_client.delete(f"{device_id}_step5")
  160. loggerKit.info("设备:{0}, action6_id:{1}", device_id, action6_id)
  161. return action6_dict
  162. step6 = redis_client.get(f"{device_id}_step6")
  163. if step6 is not None and int(step6) == 1 and last_action_id is not None and int(perform_action_id) == int(
  164. last_action_id) \
  165. and perform_action_result == "success":
  166. loggerKit.info("设备:{0}, action7_id_mem:{1}", device_id, int(last_action_id))
  167. action7_id = int(round(time.time() * 1000))
  168. """
  169. 发送第7条指令
  170. 进行点赞
  171. """
  172. action7_dict = single_click_by_control(action7_id, target_app="douyin", target_version="28.8.0",
  173. package_name="com.ss.android.ugc.aweme.lite",
  174. control_id="com.ss.android.ugc.aweme.lite:id/cug", timeout=5)
  175. redis_client.set(device_id + "operate", action7_id)
  176. redis_client.set(f"{device_id}_step7", "1")
  177. redis_client.delete(f"{device_id}_step6")
  178. loggerKit.info("设备:{0}, action7_id:{1}", device_id, action7_id)
  179. return action7_dict
  180. step7 = redis_client.get(f"{device_id}_step7")
  181. if step7 is not None and int(step7) == 1 and last_action_id is not None and int(perform_action_id) == int(
  182. last_action_id) \
  183. and perform_action_result == "success":
  184. loggerKit.info("设备:{0}, action8_id_mem:{1}", device_id, int(last_action_id))
  185. action8_id = int(round(time.time() * 1000))
  186. """
  187. 发送第8条指令
  188. 收藏
  189. """
  190. action8_dict = single_click_by_control(action8_id, target_app="douyin", target_version="28.8.0",
  191. package_name="com.ss.android.ugc.aweme.lite",
  192. control_id="com.ss.android.ugc.aweme.lite:id/bn=", timeout=5)
  193. redis_client.set(device_id + "operate", action8_id)
  194. redis_client.set(f"{device_id}_step8", "1")
  195. redis_client.delete(f"{device_id}_step7")
  196. loggerKit.info("设备:{0}, action8_id:{1}", device_id, action8_dict)
  197. return action8_dict
  198. step8 = redis_client.get(f"{device_id}_step8")
  199. if step8 is not None and int(step8) == 1 and last_action_id is not None and int(perform_action_id) == int(
  200. last_action_id) \
  201. and perform_action_result == "success":
  202. loggerKit.info("设备:{0}, action9_id_mem:{1}", device_id, int(last_action_id))
  203. action9_id = int(round(time.time() * 1000))
  204. """
  205. 发送第9条指令
  206. 获取到用户的帖子内容
  207. """
  208. action9_dict = get_text_by_control(action9_id, target_app="douyin", target_version="28.8.0",
  209. package_name="com.ss.android.ugc.aweme.lite",
  210. max_page='1',
  211. control_id="com.ss.android.ugc.aweme.lite:id/desc", timeout=5)
  212. redis_client.set(device_id + "operate", action9_id)
  213. redis_client.set(f"{device_id}_step9", "1")
  214. redis_client.delete(f"{device_id}_step8")
  215. loggerKit.info("设备:{0}, action9_id:{1}", device_id, action9_id)
  216. return action9_dict
  217. step9 = redis_client.get(f"{device_id}_step9")
  218. if step9 is not None and int(step9) == 1 and last_action_id is not None and int(perform_action_id) == int(
  219. last_action_id) \
  220. and perform_action_result == "success":
  221. loggerKit.info("设备:{0}, action4_id_mem:{1}", device_id, int(last_action_id))
  222. action10_id = int(round(time.time() * 1000))
  223. """
  224. 发送第10条指令
  225. 根据视频内容 生成评论文案将文案缓存 并且点击评论
  226. """
  227. result_text = result.get("performActionText")
  228. if result_text is None:
  229. return_dict = {
  230. "data": "",
  231. "code": -2,
  232. "message": "fail, result_text is null"
  233. }
  234. # 回调任务中心
  235. del_key_vague(device_id)
  236. callback_task(500, '获取到的内容标题为null,无法评论', task_id, device_id, 0, None)
  237. return return_dict
  238. request_data = {
  239. "templateId": "dcd_comment",
  240. "content": result_text,
  241. "existingComment": None
  242. }
  243. loggerKit.info("任务id:{0}对应标题:{1},请求AIGC信息:{2}", task_id, keyword, request_data)
  244. response = httpx.post(post_ai_gc_url, json=request_data, timeout=120)
  245. # 点击评论框
  246. action10_dict = single_click_by_control(action10_id, target_app="douyin", target_version="28.8.0",
  247. package_name="com.ss.android.ugc.aweme.lite",
  248. control_id="com.ss.android.ugc.aweme.lite:id/comment_container",
  249. timeout=5)
  250. if not response.is_success:
  251. # 调用AIGC获取评论失败
  252. loggerKit.info("任务id:{0}对应标题:{1},请求AIGC失败信息:{2},返回信息:{3}", task_id, keyword, request_data, response)
  253. redis_client.set(device_id + "douyin" + "comments", '不错👍')
  254. redis_client.set(device_id + "operate", action10_id)
  255. redis_client.set(f"{device_id}_step10", "1")
  256. redis_client.delete(f"{device_id}_step9")
  257. loggerKit.info("设备:{0}, action10_id:{1}", device_id, action10_id)
  258. return action10_dict
  259. response_body = json.loads(response.text)
  260. data = response_body.get('data')
  261. reply_text = data.get('answer')
  262. reply_text_json = json.loads(reply_text)
  263. reply = reply_text_json.get('comment')
  264. if '内容太少' in reply or '对不起' in reply or reply is None or reply == '' or '提供' in reply:
  265. # 获取到的评论内容不符合
  266. loggerKit.info("任务id:{0}对应标题:{1},请求AIGC失败信息:{2},返回信息:{3}", task_id, keyword, request_data, response)
  267. redis_client.set(device_id + "douyin" + "comments", '不错👍')
  268. redis_client.set(device_id + "operate", action10_id)
  269. redis_client.set(f"{device_id}_step10", "1")
  270. redis_client.delete(f"{device_id}_step9")
  271. loggerKit.info("设备:{0}, action10_id:{1}", device_id, action10_id)
  272. return action10_dict
  273. # 将需要评论的内容存入缓存
  274. redis_client.set(device_id + "douyin" + "comments", reply)
  275. redis_client.set(device_id + "operate", action10_id)
  276. redis_client.set(f"{device_id}_step10", "1")
  277. redis_client.delete(f"{device_id}_step9")
  278. loggerKit.info("设备:{0}, action10_id:{1}", device_id, action10_id)
  279. return action10_dict
  280. step10 = redis_client.get(f"{device_id}_step10")
  281. if step10 is not None and int(step10) == 1 and last_action_id is not None and int(perform_action_id) == int(
  282. last_action_id) \
  283. and perform_action_result == "success":
  284. loggerKit.info("设备:{0}, action11_id_mem:{1}", device_id, int(last_action_id))
  285. action11_id = int(round(time.time() * 1000))
  286. """
  287. 发送第11条指令
  288. 点击评论框
  289. """
  290. reply = redis_client.get(device_id + "douyin" + "comments")
  291. if reply is None:
  292. # 调用AIGC获取评论失败
  293. del_key_vague(device_id)
  294. return_dict = {
  295. "data": "",
  296. "code": -2,
  297. "message": "fail, result_text is null"
  298. }
  299. callback_task(500, '获取到的内容标题为null,无法评论', task_id, device_id, 0, None)
  300. return return_dict
  301. action11_dict = single_click_by_control(action11_id, target_app="douyin", target_version="28.8.0",
  302. package_name="com.ss.android.ugc.aweme.lite",
  303. control_id="com.ss.android.ugc.aweme.lite:id/brv", timeout=5)
  304. redis_client.set(device_id + "operate", action11_id)
  305. redis_client.set(f"{device_id}_step11", "1")
  306. redis_client.delete(f"{device_id}_step10")
  307. loggerKit.info("设备:{0}, action11_id:{1}", device_id, action11_id)
  308. return action11_dict
  309. step11 = redis_client.get(f"{device_id}_step11")
  310. if step11 is not None and int(step11) == 1 and last_action_id is not None and int(perform_action_id) == int(
  311. last_action_id) \
  312. and perform_action_result == "success":
  313. loggerKit.info("设备:{0}, action12_id_mem:{1}", device_id, int(last_action_id))
  314. action12_id = int(round(time.time() * 1000))
  315. """
  316. 发送第12条指令
  317. 对评论框进行赋值
  318. """
  319. reply = redis_client.get(device_id + "douyin" + "comments")
  320. if reply is None:
  321. # 调用AIGC获取评论失败
  322. del_key_vague(device_id)
  323. return_dict = {
  324. "data": "",
  325. "code": -2,
  326. "message": "fail, result_text is null"
  327. }
  328. callback_task(500, '获取到的内容标题为null,无法评论', task_id, device_id, 0, None)
  329. return return_dict
  330. action12_dict = send_text_by_control(action12_id, target_app="douyin", target_version="28.8.0",
  331. package_name="com.ss.android.ugc.aweme.lite",
  332. control_id="com.ss.android.ugc.aweme.lite:id/brv",
  333. content=reply, timeout=5)
  334. redis_client.set(device_id + "operate", action12_id)
  335. redis_client.set(f"{device_id}_step12", "1")
  336. redis_client.delete(f"{device_id}_step11")
  337. loggerKit.info("设备:{0}, action12_id:{1}", device_id, action12_id)
  338. return action12_dict
  339. step12 = redis_client.get(f"{device_id}_step12")
  340. if step12 is not None and int(step12) == 1 and last_action_id is not None and int(perform_action_id) == int(
  341. last_action_id) \
  342. and perform_action_result == "success":
  343. loggerKit.info("设备:{0}, action13_id_mem:{1}", device_id, int(last_action_id))
  344. action13_id = int(round(time.time() * 1000))
  345. """
  346. 发送第13条指令
  347. 发送评论
  348. """
  349. action12_dict = single_click_by_control(action13_id, target_app="douyin", target_version="28.8.0",
  350. package_name="com.ss.android.ugc.aweme.lite",
  351. control_id="com.ss.android.ugc.aweme.lite:id/bcw", timeout=5)
  352. redis_client.set(device_id + "operate", action13_id)
  353. redis_client.set(f"{device_id}_step13", "1")
  354. redis_client.delete(f"{device_id}_step12")
  355. loggerKit.info("设备:{0}, action13_id:{1}", device_id, action12_dict)
  356. return action12_dict
  357. """
  358. 停止app
  359. """
  360. step13 = redis_client.get(f"{device_id}_step13")
  361. if step13 is not None and int(step13) == 1 and last_action_id is not None and int(perform_action_id) == int(
  362. last_action_id) and perform_action_result == "success":
  363. loggerKit.info("设备:{0}, action14_id_mem:{1}", device_id, int(last_action_id))
  364. action14_id = int(round(time.time() * 1000))
  365. """
  366. 停止指令
  367. 停止app
  368. """
  369. action14_dict = stop_app(action14_id, target_app="douyin", target_version="28.8.0",
  370. package_name="com.ss.android.ugc.aweme.lite", timeout=5)
  371. redis_client.delete(f"{device_id}_step4")
  372. del_key_vague(device_id)
  373. loggerKit.info("设备:{0}, action14_id:{1}", device_id, action14_id)
  374. # 回调任务中心修改任务状态
  375. callback_task(None, None, task_id, device_id, 1, None)
  376. return action14_dict
  377. else:
  378. action0_id = int(round(time.time() * 1000))
  379. """
  380. 启动指令
  381. 启动app
  382. """
  383. action0_dict = start_app(action0_id, target_app="douyin", target_version="28.8.0",
  384. package_name="com.ss.android.ugc.aweme.lite")
  385. redis_client.set(device_id + "operate", action0_id)
  386. redis_client.set(f"{device_id}_step0", "1")
  387. redis_client.delete(f"{device_id}_step9")
  388. loggerKit.info("设备:{0}, action0_id:{1}", device_id, action0_id)
  389. return action0_dict
  390. # 批量模糊删除缓存
  391. # def del_key_vague(device_id):
  392. # # 批量模糊删除keys
  393. # keys = redis_client.match_pattern_prefix(device_id)
  394. # if len(keys) > 0:
  395. # # 需要判断是否有匹配的值, 没有的话会报错
  396. # for key in keys:
  397. # redis_client.delete(key)
  398. # loggerKit.info(f"clear {device_id} keys success...")
  399. # else:
  400. # loggerKit.info(f"{device_id} keys none ...")
  401. # post请求
  402. # def call_back_request(error_code, error_msg, task_id, task_status, task_execute_response, content, demo_flag):
  403. # response = {
  404. # "errorCode": error_code,
  405. # "errorMsg": error_msg,
  406. # "taskId": task_id,
  407. # "taskStatus": task_status,
  408. # "taskExecuteResponse": task_execute_response,
  409. # "content": content,
  410. # "demoFlag": demo_flag
  411. # }
  412. # return response
  413. #
  414. #
  415. # # 回调任务中心接口
  416. # def callback_task(err_code, err_msg, task_id, device_id, execute_status, result):
  417. # callback_request2 = call_back_request(err_code, err_msg, task_id, execute_status, result, None, None)
  418. # loggerKit.info("thread[{0}=>{1}], taskId:{2}, 设备号:{3}, url:{4} 。回调开始", threading.current_thread().name,
  419. # threading.get_ident(), task_id, device_id, task_callback_url)
  420. # current_timeout = (5, 10)
  421. # callback_response2 = requests.post(task_callback_url, json=callback_request2, timeout=current_timeout)
  422. # loggerKit.info("thread[{0}=>{1}], taskId:{2},设备号:{3}。回调结束:{4}", threading.current_thread().name,
  423. # threading.get_ident(), task_id, device_id, json.dumps(callback_response2.text, ensure_ascii=False))
  424. # return callback_response2