weiqun_music.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. # -*- coding: utf-8 -*-
  2. # @Author: wangkun
  3. # @Time: 2022/8/11
  4. import os
  5. import random
  6. import shutil
  7. import sys
  8. import time
  9. import ffmpeg
  10. import requests
  11. import urllib3
  12. sys.path.append(os.getcwd())
  13. from main.common import Common
  14. from main.feishu_lib import Feishu
  15. from main.publish import Publish
  16. class Music:
  17. # 获取已下载视频宽高、时长等信息
  18. @classmethod
  19. def get_video_info_from_local(cls, video_path):
  20. probe = ffmpeg.probe(video_path)
  21. # print('video_path: {}'.format(video_path))
  22. # format1 = probe['format']
  23. # bit_rate = int(format1['bit_rate']) / 1000
  24. # duration = format['duration']
  25. # size = int(format1['size']) / 1024 / 1024
  26. video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
  27. if video_stream is None:
  28. print('No video stream found!')
  29. return
  30. width = int(video_stream['width'])
  31. height = int(video_stream['height'])
  32. # num_frames = int(video_stream['nb_frames'])
  33. # fps = int(video_stream['r_frame_rate'].split('/')[0]) / int(video_stream['r_frame_rate'].split('/')[1])
  34. duration = float(video_stream['duration'])
  35. # print('width: {}'.format(width))
  36. # print('height: {}'.format(height))
  37. # print('num_frames: {}'.format(num_frames))
  38. # print('bit_rate: {}k'.format(bit_rate))
  39. # print('fps: {}'.format(fps))
  40. # print('size: {}MB'.format(size))
  41. # print('duration: {}'.format(duration))
  42. return width, height, duration
  43. # 获取视频ID
  44. @classmethod
  45. def get_video_list(cls, log_type):
  46. try:
  47. # 翻10页
  48. for num in range(1, 5):
  49. Common.logger(log_type).info("正在抓取第{}页\n", num)
  50. url = "https://ayg.818ao.com/app/index.php?"
  51. headers = {
  52. "content-type": "application/x-www-form-urlencoded",
  53. "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) "
  54. "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 "
  55. "MicroMessenger/8.0.26(0x18001a2e) NetType/WIFI Language/zh_CN",
  56. "Accept-Encoding": "gzip,compress,br,deflate",
  57. "Referer": "https://servicewechat.com/wx06417203b6ba3e25/1/page-frame.html"
  58. }
  59. query_string = {
  60. "i": "13",
  61. "t": "0",
  62. "m": "jyt_txvideo",
  63. "v": "1.4",
  64. "from": "wxapp",
  65. "c": "entry",
  66. "a": "wxapp",
  67. "do": "videolist",
  68. "sign": "ffccddd4e767cf98e39222026b938015",
  69. }
  70. form = {
  71. "category": "246",
  72. "page": num,
  73. "israndom": "",
  74. "type": "0",
  75. "isview": "",
  76. "noauth": "true"
  77. }
  78. urllib3.disable_warnings()
  79. r = requests.post(url=url, headers=headers, params=query_string, data=form, verify=False)
  80. if "data" not in r.json() or len(r.json()["data"]) == 0:
  81. Common.logger(log_type).warning("get_video_list:response:{}", r.text)
  82. else:
  83. data = r.json()["data"]
  84. for i in range(len(data)):
  85. if "vid" in data[i]:
  86. video_id = data[i]["vid"]
  87. cls.get_video_info(log_type, video_id)
  88. else:
  89. Common.logger(log_type).info("get_video_list获取到无效视频,略过")
  90. except Exception as e:
  91. Common.logger(log_type).error("get_video_list异常:{}", e)
  92. # 根据 video_id 获取 video_url
  93. @classmethod
  94. def get_video_url(cls, logtype, vid):
  95. try:
  96. url = "https://ayg.818ao.com/app/index.php?"
  97. headers = {
  98. "content-type": "application/x-www-form-urlencoded",
  99. "Accept-Encoding": "gzip,compress,br,deflate",
  100. "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) "
  101. "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 "
  102. "MicroMessenger/8.0.26(0x18001a2e) NetType/WIFI Language/zh_CN",
  103. "Referer": "https://servicewechat.com/wx06417203b6ba3e25/1/page-frame.html"
  104. }
  105. query_string = {
  106. "i": "13",
  107. "t": "0",
  108. "m": "jyt_txvideo",
  109. "v": "1.4",
  110. "from": "wxapp",
  111. "c": "entry",
  112. "a": "wxapp",
  113. "do": "videoinfo",
  114. "state": "we7sid-da63afcc7fbfdeb15d94c9683f83dc1f",
  115. "sign": "a449ac59c215b8cab2fbcbb6c3a609e2",
  116. "vid": vid,
  117. "version": "1.0.3",
  118. }
  119. urllib3.disable_warnings()
  120. r = requests.get(url=url, headers=headers, params=query_string, verify=False)
  121. if "data" not in r.json():
  122. Common.logger(logtype).warning("get_video_url:response:{}", r.json())
  123. else:
  124. video_url = r.json()["data"]["res"]
  125. return video_url
  126. except Exception as e:
  127. Common.logger(logtype).error("get_video_url异常:{}", e)
  128. # 获取视频详情
  129. @classmethod
  130. def get_video_info(cls, log_type, vid):
  131. try:
  132. url = "https://ayg.818ao.com/app/index.php?"
  133. headers = {
  134. "content-type": "application/x-www-form-urlencoded",
  135. "user-agent": "User-Agent Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) "
  136. "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.26(0x18001a2e)"
  137. " NetType/WIFI Language/zh_CN",
  138. "Accept-Encoding": "gzip,compress,br,deflate",
  139. "referer": "https://servicewechat.com/wx06417203b6ba3e25/1/page-frame.html"
  140. }
  141. query_string = {
  142. "i": "13",
  143. "t": "0",
  144. "m": "jyt_txvideo",
  145. "v": "1.4",
  146. "from": "wxapp",
  147. "c": "entry",
  148. "a": "wxapp",
  149. "do": "videodetail",
  150. "state": "we7sid-da63afcc7fbfdeb15d94c9683f83dc1f",
  151. "sign": "9b5c05a00fc03363daa1a48622b03bf3",
  152. }
  153. form = {
  154. "vid": vid,
  155. "cate": "246",
  156. "userad": ""
  157. }
  158. urllib3.disable_warnings()
  159. r = requests.post(url=url, headers=headers, params=query_string, data=form, verify=False)
  160. if r.json()["message"] != "视频详情":
  161. Common.logger(log_type).warning("get_video_info:response:{}", r.text)
  162. else:
  163. # video_title
  164. if "vtitle" in r.json()["data"]:
  165. video_title = r.json()["data"]["vtitle"]
  166. else:
  167. video_title = 0
  168. # video_id
  169. video_id = vid
  170. # play_cnt
  171. if "realview" not in r.json()["data"]:
  172. play_cnt = 0
  173. else:
  174. play_cnt = r.json()["data"]["realview"]
  175. # like_cnt
  176. like_cnt = 0
  177. # share_cnt
  178. share_cnt = 0
  179. # comment_cnt
  180. comment_cnt = 0
  181. # send_time
  182. if "create_time" in r.json()["data"]:
  183. send_time = r.json()["data"]["create_time"]
  184. else:
  185. send_time = 0
  186. # video_duration
  187. if "vtime" not in r.json()["data"]:
  188. video_duration = 0
  189. elif r.json()["data"]["vtime"] == "" or r.json()["data"]["vtime"] is None:
  190. video_duration = 0
  191. else:
  192. video_duration = r.json()["data"]["vtime"]
  193. # user_id
  194. if "uid" not in r.json()["data"]:
  195. user_id = 0
  196. else:
  197. user_id = r.json()["data"]["uid"]
  198. # user_name
  199. user_name = "微群视频"
  200. # cover_url
  201. if "poster" not in r.json()["data"]:
  202. cover_url = 0
  203. elif "http" not in r.json()["data"]["poster"]:
  204. cover_url = "http://qiniu.818ao.com/" + r.json()["data"]["poster"]
  205. else:
  206. cover_url = r.json()["data"]["poster"]
  207. # head_url
  208. head_url = cover_url
  209. # video_url
  210. if "vid" not in r.json()["data"]:
  211. video_url = 0
  212. elif r.json()["data"]["vid"] == vid:
  213. video_url = cls.get_video_url(log_type, vid)
  214. else:
  215. video_url = r.json()["data"]["vid"]
  216. Common.logger(log_type).info("video_title:{}", video_title)
  217. Common.logger(log_type).info("video_id:{}", video_id)
  218. # Common.logger(log_type).info("play_cnt:{}", play_cnt)
  219. # Common.logger(log_type).info("like_cnt:{}", like_cnt)
  220. # Common.logger(log_type).info("share_cnt:{}", share_cnt)
  221. # Common.logger(log_type).info("comment_cnt:{}", comment_cnt)
  222. Common.logger(log_type).info("send_time:{}",
  223. time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(int(send_time))))
  224. Common.logger(log_type).info("video_duration:{}", video_duration)
  225. # Common.logger(log_type).info("user_name:{}", user_name)
  226. # Common.logger(log_type).info("user_id:{}", user_id)
  227. # Common.logger(log_type).info("head_url:{}", head_url)
  228. # Common.logger(log_type).info("cover_url:{}", cover_url)
  229. Common.logger(log_type).info("video_url:{}", video_url)
  230. # 过滤无效视频
  231. if video_title == 0 or video_id == 0 or send_time == 0 or cover_url == 0 or video_url == 0:
  232. Common.logger(log_type).info("无效视频\n")
  233. # 已下载视频表去重
  234. elif str(video_id) in [n for m in Feishu.get_values_batch(log_type, "weiqun", "3cd128") for n in m]:
  235. Common.logger(log_type).info("该视频已下载\n")
  236. # music_feeds去重
  237. elif str(video_id) in [n for m in Feishu.get_values_batch(log_type, "weiqun", "JK6npf") for n in m]:
  238. Common.logger(log_type).info("该视频已在music_feeds中\n")
  239. else:
  240. time.sleep(1)
  241. Feishu.insert_columns(log_type, "weiqun", "JK6npf", "ROWS", 1, 2)
  242. get_feeds_time = int(time.time())
  243. values = [[str(time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(get_feeds_time))),
  244. "音乐榜",
  245. str(video_id),
  246. video_title,
  247. int(play_cnt),
  248. comment_cnt,
  249. like_cnt,
  250. share_cnt,
  251. int(video_duration),
  252. time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(int(send_time))),
  253. user_name,
  254. user_id,
  255. head_url,
  256. cover_url,
  257. video_url]]
  258. time.sleep(1)
  259. Feishu.update_values(log_type, "weiqun", "JK6npf", "A2:Q2", values)
  260. Common.logger(log_type).info("添加至music_feeds成功\n")
  261. except Exception as e:
  262. Common.logger(log_type).error("get_video_info异常:{}", e)
  263. # 下载/上传视频
  264. @classmethod
  265. def download_publish(cls, log_type, env):
  266. try:
  267. music_feeds_sheet = Feishu.get_values_batch(log_type, "weiqun", "JK6npf")
  268. for i in range(1, len(music_feeds_sheet)):
  269. download_video_id = music_feeds_sheet[i][2]
  270. download_video_title = music_feeds_sheet[i][3]
  271. download_video_play_cnt = music_feeds_sheet[i][4]
  272. download_video_comment_cnt = music_feeds_sheet[i][5]
  273. download_video_like_cnt = music_feeds_sheet[i][6]
  274. download_video_share_cnt = music_feeds_sheet[i][7]
  275. # download_video_duration = music_feeds_sheet[i][8]
  276. download_video_send_time = music_feeds_sheet[i][9]
  277. download_user_name = music_feeds_sheet[i][10]
  278. download_user_id = music_feeds_sheet[i][11]
  279. download_head_url = music_feeds_sheet[i][12]
  280. download_cover_url = music_feeds_sheet[i][13]
  281. download_video_url = music_feeds_sheet[i][14]
  282. Common.logger(log_type).info("正在判断第{}行", i + 1)
  283. Common.logger(log_type).info("download_video_title:{}", download_video_title)
  284. # Common.logger(log_type).info("download_video_play_cnt:{}", download_video_play_cnt)
  285. # Common.logger(log_type).info("download_video_id:{}", download_video_id)
  286. # Common.logger(log_type).info("download_video_comment_cnt:{}", download_video_comment_cnt)
  287. # Common.logger(log_type).info("download_video_like_cnt:{}", download_video_like_cnt)
  288. # Common.logger(log_type).info("download_video_share_cnt:{}", download_video_share_cnt)
  289. Common.logger(log_type).info("download_video_send_time:{}", download_video_send_time)
  290. # Common.logger(log_type).info("download_user_name:{}", download_user_name)
  291. # Common.logger(log_type).info("download_user_id:{}", download_user_id)
  292. # Common.logger(log_type).info("download_head_url:{}", download_head_url)
  293. # Common.logger(log_type).info("download_cover_url:{}", download_cover_url)
  294. Common.logger(log_type).info("download_video_url:{}", download_video_url)
  295. # 过滤空行
  296. if download_video_id is None or download_video_title is None or download_video_play_cnt is None:
  297. Common.logger(log_type).warning("空行,略过\n")
  298. # 已下载视频表去重
  299. elif str(download_video_id) in [n for m in Feishu.get_values_batch(log_type, "weiqun", "3cd128")
  300. for n in m]:
  301. Feishu.dimension_range(log_type, "weiqun", "JK6npf", "ROWS", i + 1, i + 1)
  302. Common.logger(log_type).info("该视频已下载,删除成功\n")
  303. return
  304. # 满足下载规则
  305. else:
  306. # 下载视频
  307. Common.download_method(log_type=log_type, text="video",
  308. d_name=str(download_video_title), d_url=str(download_video_url))
  309. # 下载封面
  310. Common.download_method(log_type=log_type, text="cover",
  311. d_name=str(download_video_title), d_url=str(download_cover_url))
  312. # 获取视频宽高/时长
  313. video_info = cls.get_video_info_from_local("./videos/" + download_video_title + "/video.mp4")
  314. download_video_resolution = str(video_info[0]) + "*" + str(video_info[1])
  315. download_video_duration = video_info[2]
  316. # 保存视频信息至 "./videos/{download_video_title}/info.txt"
  317. with open("./videos/" + download_video_title
  318. + "/" + "info.txt", "a", encoding="UTF-8") as f_a:
  319. f_a.write(str(download_video_id) + "\n" +
  320. str(download_video_title) + "\n" +
  321. str(int(download_video_duration)) + "\n" +
  322. str(download_video_play_cnt) + "\n" +
  323. str(download_video_comment_cnt) + "\n" +
  324. str(download_video_like_cnt) + "\n" +
  325. str(download_video_share_cnt) + "\n" +
  326. str(download_video_resolution) + "\n" +
  327. str(int(time.mktime(
  328. time.strptime(download_video_send_time, "%Y/%m/%d %H:%M:%S")))) + "\n" +
  329. str(download_user_name) + "\n" +
  330. str(download_head_url) + "\n" +
  331. str(download_video_url) + "\n" +
  332. str(download_cover_url) + "\n" +
  333. "weiqunvideo")
  334. Common.logger(log_type).info("==========视频信息已保存至info.txt==========")
  335. # 上传视频
  336. Common.logger(log_type).info("开始上传视频:{}".format(download_video_title))
  337. our_video_id = Publish.upload_and_publish(log_type, env, "play")
  338. our_video_link = "https://admin.piaoquantv.com/cms/post-detail/" + str(our_video_id) + "/info"
  339. Common.logger(log_type).info("视频上传完成:{}", download_video_title)
  340. # 保存视频 ID 到云文档
  341. Common.logger(log_type).info("保存视频ID至已下载表:{}", download_video_title)
  342. # 视频ID工作表,插入首行
  343. Feishu.insert_columns(log_type, "weiqun", "3cd128", "ROWS", 1, 2)
  344. # 视频ID工作表,首行写入数据
  345. upload_time = int(time.time())
  346. values = [[time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(upload_time)),
  347. "音乐榜",
  348. str(download_video_id),
  349. str(download_video_title),
  350. our_video_link,
  351. download_video_play_cnt,
  352. download_video_comment_cnt,
  353. download_video_like_cnt,
  354. download_video_share_cnt,
  355. int(download_video_duration),
  356. str(download_video_resolution),
  357. str(download_video_send_time),
  358. str(download_user_name),
  359. str(download_user_id),
  360. str(download_head_url),
  361. str(download_cover_url),
  362. str(download_video_url)]]
  363. time.sleep(1)
  364. Feishu.update_values(log_type, "weiqun", "3cd128", "F2:W2", values)
  365. # 删除行或列,可选 ROWS、COLUMNS
  366. Feishu.dimension_range(log_type, "weiqun", "JK6npf", "ROWS", i + 1, i + 1)
  367. Common.logger(log_type).info("视频:{},下载/上传成功\n", download_video_title)
  368. return
  369. except Exception as e:
  370. Feishu.dimension_range(log_type, "weiqun", "JK6npf", "ROWS", 2, 2)
  371. Common.logger(log_type).error("download_publish异常:{},删除成功", e)
  372. # 执行下载/上传
  373. @classmethod
  374. def run_download_publish(cls, log_type, env):
  375. try:
  376. while True:
  377. time.sleep(1)
  378. music_feeds_sheet = Feishu.get_values_batch(log_type, "weiqun", "JK6npf")
  379. if len(music_feeds_sheet) == 1:
  380. Common.logger(log_type).info("下载/上传完成\n")
  381. break
  382. else:
  383. cls.download_publish(log_type, env)
  384. time.sleep(random.randint(1, 3))
  385. except Exception as e:
  386. Common.logger(log_type).error("run_download_publish异常:{}", e)
  387. if __name__ == "__main__":
  388. # Music.get_video_list("weiqun")
  389. # Music.get_video_info("weiqun", "wxv_2228210032582639621")
  390. # print(Music.get_video_url("weiqun", "w3243xgp9i1"))
  391. Music.download_publish("weiqun", "dev")