xigua_follow.py 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. # -*- coding: utf-8 -*-
  2. # @Author: wangkun
  3. # @Time: 2023/2/17
  4. import base64
  5. import json
  6. import os
  7. import random
  8. import shutil
  9. import string
  10. import sys
  11. import time
  12. from hashlib import md5
  13. import requests
  14. import urllib3
  15. from requests.adapters import HTTPAdapter
  16. # from selenium.webdriver import DesiredCapabilities
  17. # from selenium.webdriver.chrome.service import Service
  18. # from selenium.webdriver.common.by import By
  19. # from selenium import webdriver
  20. from lxml import etree
  21. sys.path.append(os.getcwd())
  22. from common.db import MysqlHelper
  23. from common.getuser import getUser
  24. from common.common import Common
  25. from common.feishu import Feishu
  26. from common.publish import Publish
  27. from common.public import get_user_from_mysql, random_title, get_config_from_mysql
  28. class Follow:
  29. # 个人主页视频翻页参数
  30. offset = 0
  31. platform = "西瓜视频"
  32. tag = "西瓜视频爬虫,定向爬虫策略"
  33. @classmethod
  34. def get_rule(cls, log_type, crawler):
  35. try:
  36. while True:
  37. rule_sheet = Feishu.get_values_batch(log_type, crawler, "4kxd31")
  38. if rule_sheet is None:
  39. Common.logger(log_type, crawler).warning("rule_sheet is None! 10秒后重新获取")
  40. time.sleep(10)
  41. continue
  42. rule_dict = {
  43. "play_cnt": int(rule_sheet[1][2]),
  44. "comment_cnt": int(rule_sheet[2][2]),
  45. "like_cnt": int(rule_sheet[3][2]),
  46. "duration": int(rule_sheet[4][2]),
  47. "publish_time": int(rule_sheet[5][2]),
  48. "video_width": int(rule_sheet[6][2]),
  49. "video_height": int(rule_sheet[7][2]),
  50. }
  51. return rule_dict
  52. except Exception as e:
  53. Common.logger(log_type, crawler).error(f"get_rule:{e}\n")
  54. # 下载规则
  55. @classmethod
  56. def download_rule(cls, video_info_dict, rule_dict):
  57. if video_info_dict['play_cnt'] >= rule_dict['play_cnt']:
  58. if video_info_dict['comment_cnt'] >= rule_dict['comment_cnt']:
  59. if video_info_dict['like_cnt'] >= rule_dict['like_cnt']:
  60. if video_info_dict['duration'] >= rule_dict['duration']:
  61. if video_info_dict['video_width'] >= rule_dict['video_width'] \
  62. or video_info_dict['video_height'] >= rule_dict['video_height']:
  63. return True
  64. else:
  65. return False
  66. else:
  67. return False
  68. else:
  69. return False
  70. else:
  71. return False
  72. else:
  73. return False
  74. # 过滤词库
  75. @classmethod
  76. def filter_words(cls, log_type, crawler):
  77. try:
  78. while True:
  79. filter_words_sheet = Feishu.get_values_batch(log_type, crawler, 'KGB4Hc')
  80. if filter_words_sheet is None:
  81. Common.logger(log_type, crawler).warning(f"filter_words_sheet:{filter_words_sheet} 10秒钟后重试")
  82. continue
  83. filter_words_list = []
  84. for x in filter_words_sheet:
  85. for y in x:
  86. if y is None:
  87. pass
  88. else:
  89. filter_words_list.append(y)
  90. return filter_words_list
  91. except Exception as e:
  92. Common.logger(log_type, crawler).error(f'filter_words异常:{e}\n')
  93. @classmethod
  94. def get_out_user_info(cls, log_type, crawler, out_uid):
  95. try:
  96. headers = {
  97. 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41',
  98. 'referer': f'https://www.ixigua.com/home/{out_uid}',
  99. 'Cookie': f'ixigua-a-s=1; support_webp=true; support_avif=false; csrf_session_id=a5355d954d3c63ed1ba35faada452b4d; __ac_signature={cls.random_signature()}; MONITOR_WEB_ID=67cb5099-a022-4ec3-bb8e-c4de6ba51dd0; s_v_web_id=verify_lef4i99x_32SosrdH_Qrtk_4LJn_8S7q_fhu16xe3s8ZV; tt_scid=QLJjPuHf6wxVqu6IIq6gHiJXQpVrCwrdhjH2zpm7-E3ZniE1RXBcP6M8b41FJOdo41e1; ttwid=1%7CHHtv2QqpSGuSu8r-zXF1QoWsvjmNi1SJrqOrZzg-UCY%7C1677047013%7C5866a444e5ae10a9df8c11551db75010fb77b657f214ccf84e503fae8d313d09; msToken=PerXJcDdIsZ6zXkGITsftXX4mDaVaW21GuqtzSVdctH46oXXT2GcELIs9f0XW2hunRzP6KVHLZaYElRvNYflLKUXih7lC27XKxs3HjdZiXPK9NQaoKbLfA==; ixigua-a-s=1', }
  100. url = f"https://www.ixigua.com/home/{out_uid}"
  101. urllib3.disable_warnings()
  102. s = requests.session()
  103. # max_retries=3 重试3次
  104. s.mount('http://', HTTPAdapter(max_retries=3))
  105. s.mount('https://', HTTPAdapter(max_retries=3))
  106. response = s.get(url=url, headers=headers, proxies=Common.tunnel_proxies(), verify=False, timeout=5).text
  107. html = etree.HTML(response)
  108. out_follow_str = html.xpath('//div[@class="userDetailV3__header__detail2"]/*[1]/span')[0].text.encode(
  109. 'raw_unicode_escape').decode()
  110. out_fans_str = html.xpath('//div[@class="userDetailV3__header__detail2"]/*[2]/span')[0].text.encode(
  111. 'raw_unicode_escape').decode()
  112. out_like_str = html.xpath('//div[@class="userDetailV3__header__detail2"]/*[3]/span')[0].text.encode(
  113. 'raw_unicode_escape').decode()
  114. out_avatar_url = f"""https:{html.xpath('//span[@class="component-avatar__inner"]//img/@src')[0]}"""
  115. if "万" in out_follow_str:
  116. out_follow = int(float(out_follow_str.split("万")[0]) * 10000)
  117. else:
  118. out_follow = int(out_follow_str.replace(",", ""))
  119. if "万" in out_fans_str:
  120. out_fans = int(float(out_fans_str.split("万")[0]) * 10000)
  121. else:
  122. out_fans = int(out_fans_str.replace(",", ""))
  123. if "万" in out_like_str:
  124. out_like = int(float(out_like_str.split("万")[0]) * 10000)
  125. else:
  126. out_like = int(out_like_str.replace(",", ""))
  127. out_user_dict = {
  128. "out_follow": out_follow,
  129. "out_fans": out_fans,
  130. "out_like": out_like,
  131. "out_avatar_url": out_avatar_url,
  132. }
  133. # for k, v in out_user_dict.items():
  134. # print(f"{k}:{v}")
  135. return out_user_dict
  136. except Exception as e:
  137. Common.logger(log_type, crawler).error(f"get_out_user_info:{e}\n")
  138. # 获取用户信息(字典格式). 注意:部分 user_id 字符类型是 int / str
  139. @classmethod
  140. def get_user_list(cls, log_type, crawler, sheetid, env, machine):
  141. try:
  142. while True:
  143. user_sheet = Feishu.get_values_batch(log_type, crawler, sheetid)
  144. if user_sheet is None:
  145. Common.logger(log_type, crawler).warning(f"user_sheet:{user_sheet} 10秒钟后重试")
  146. continue
  147. our_user_list = []
  148. for i in range(1, len(user_sheet)):
  149. # for i in range(428, len(user_sheet)):
  150. out_uid = user_sheet[i][2]
  151. user_name = user_sheet[i][3]
  152. our_uid = user_sheet[i][6]
  153. our_user_link = user_sheet[i][7]
  154. if out_uid is None or user_name is None:
  155. Common.logger(log_type, crawler).info("空行\n")
  156. else:
  157. Common.logger(log_type, crawler).info(f"正在更新 {user_name} 用户信息\n")
  158. if our_uid is None:
  159. try:
  160. out_user_info = cls.get_out_user_info(log_type, crawler, out_uid)
  161. except Exception as e:
  162. continue
  163. out_user_dict = {
  164. "out_uid": out_uid,
  165. "user_name": user_name,
  166. "out_avatar_url": out_user_info["out_avatar_url"],
  167. "out_create_time": '',
  168. "out_tag": '',
  169. "out_play_cnt": 0,
  170. "out_fans": out_user_info["out_fans"],
  171. "out_follow": out_user_info["out_follow"],
  172. "out_friend": 0,
  173. "out_like": out_user_info["out_like"],
  174. "platform": cls.platform,
  175. "tag": cls.tag,
  176. }
  177. our_user_dict = getUser.create_user(log_type=log_type, crawler=crawler,
  178. out_user_dict=out_user_dict, env=env, machine=machine)
  179. our_uid = our_user_dict['our_uid']
  180. our_user_link = our_user_dict['our_user_link']
  181. Feishu.update_values(log_type, crawler, sheetid, f'G{i + 1}:H{i + 1}',
  182. [[our_uid, our_user_link]])
  183. Common.logger(log_type, crawler).info(f'站内用户信息写入飞书成功!\n')
  184. our_user_list.append(our_user_dict)
  185. else:
  186. our_user_dict = {
  187. 'out_uid': out_uid,
  188. 'user_name': user_name,
  189. 'our_uid': our_uid,
  190. 'our_user_link': our_user_link,
  191. }
  192. our_user_list.append(our_user_dict)
  193. return our_user_list
  194. except Exception as e:
  195. Common.logger(log_type, crawler).error(f'get_user_id_from_feishu异常:{e}\n')
  196. @classmethod
  197. def random_signature(cls):
  198. src_digits = string.digits # string_数字
  199. src_uppercase = string.ascii_uppercase # string_大写字母
  200. src_lowercase = string.ascii_lowercase # string_小写字母
  201. digits_num = random.randint(1, 6)
  202. uppercase_num = random.randint(1, 26 - digits_num - 1)
  203. lowercase_num = 26 - (digits_num + uppercase_num)
  204. password = random.sample(src_digits, digits_num) + random.sample(src_uppercase, uppercase_num) + random.sample(
  205. src_lowercase, lowercase_num)
  206. random.shuffle(password)
  207. new_password = 'AAAAAAAAAA' + ''.join(password)[10:-4] + 'AAAB'
  208. new_password_start = new_password[0:18]
  209. new_password_end = new_password[-7:]
  210. if new_password[18] == '8':
  211. new_password = new_password_start + 'w' + new_password_end
  212. elif new_password[18] == '9':
  213. new_password = new_password_start + 'x' + new_password_end
  214. elif new_password[18] == '-':
  215. new_password = new_password_start + 'y' + new_password_end
  216. elif new_password[18] == '.':
  217. new_password = new_password_start + 'z' + new_password_end
  218. else:
  219. new_password = new_password_start + 'y' + new_password_end
  220. return new_password
  221. # @classmethod
  222. # def get_signature(cls, log_type, crawler, out_uid, machine):
  223. # try:
  224. # # 打印请求配置
  225. # ca = DesiredCapabilities.CHROME
  226. # ca["goog:loggingPrefs"] = {"performance": "ALL"}
  227. #
  228. # # 不打开浏览器运行
  229. # chrome_options = webdriver.ChromeOptions()
  230. # chrome_options.add_argument("--headless")
  231. # chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36')
  232. # chrome_options.add_argument("--no-sandbox")
  233. #
  234. # # driver初始化
  235. # if machine == 'aliyun' or machine == 'aliyun_hk':
  236. # driver = webdriver.Chrome(desired_capabilities=ca, options=chrome_options)
  237. # elif machine == 'macpro':
  238. # driver = webdriver.Chrome(desired_capabilities=ca, options=chrome_options,
  239. # service=Service('/Users/lieyunye/Downloads/chromedriver_v86/chromedriver'))
  240. # elif machine == 'macair':
  241. # driver = webdriver.Chrome(desired_capabilities=ca, options=chrome_options,
  242. # service=Service('/Users/piaoquan/Downloads/chromedriver'))
  243. # else:
  244. # driver = webdriver.Chrome(desired_capabilities=ca, options=chrome_options, service=Service('/Users/wangkun/Downloads/chromedriver/chromedriver_v110/chromedriver'))
  245. # driver.implicitly_wait(10)
  246. # driver.get(f'https://www.ixigua.com/home/{out_uid}/')
  247. # time.sleep(3)
  248. # data_src = driver.find_elements(By.XPATH, '//img[@class="tt-img BU-MagicImage tt-img-loaded"]')[1].get_attribute("data-src")
  249. # signature = data_src.split("x-signature=")[-1]
  250. # return signature
  251. # except Exception as e:
  252. # Common.logger(log_type, crawler).error(f'get_signature异常:{e}\n')
  253. # 获取视频详情
  254. @classmethod
  255. def get_video_url(cls, log_type, crawler, gid):
  256. try:
  257. url = 'https://www.ixigua.com/api/mixVideo/information?'
  258. headers = {
  259. "accept-encoding": "gzip, deflate",
  260. "accept-language": "zh-CN,zh-Hans;q=0.9",
  261. "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
  262. "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15",
  263. "referer": "https://www.ixigua.com/7102614741050196520?logTag=0531c88ac04f38ab2c62",
  264. }
  265. params = {
  266. 'mixId': gid,
  267. 'msToken': 'IlG0wd0Pylyw9ghcYiB2YseUmTwrsrqqhXrbIcsSaTcLTJyVlbYJzk20zw3UO-CfrfC'
  268. 'NVVIOBNjIl7vfBoxnVUwO9ZyzAI3umSKsT5-pef_RRfQCJwmA',
  269. 'X-Bogus': 'DFSzswVupYTANCJOSBk0P53WxM-r',
  270. '_signature': '_02B4Z6wo0000119LvEwAAIDCuktNZ0y5wkdfS7jAALThuOR8D9yWNZ.EmWHKV0WSn6Px'
  271. 'fPsH9-BldyxVje0f49ryXgmn7Tzk-swEHNb15TiGqa6YF.cX0jW8Eds1TtJOIZyfc9s5emH7gdWN94',
  272. }
  273. cookies = {
  274. 'ixigua-a-s': '1',
  275. 'msToken': 'IlG0wd0Pylyw9ghcYiB2YseUmTwrsrqqhXrbIcsSaTcLTJyVlbYJzk20zw3UO-CfrfCNVVIOB'
  276. 'NjIl7vfBoxnVUwO9ZyzAI3umSKsT5-pef_RRfQCJwmA',
  277. 'ttwid': '1%7C_yXQeHWwLZgCsgHClOwTCdYSOt_MjdOkgnPIkpi-Sr8%7C1661241238%7Cf57d0c5ef3f1d7'
  278. '6e049fccdca1ac54887c34d1f8731c8e51a49780ff0ceab9f8',
  279. 'tt_scid': 'QZ4l8KXDG0YAEaMCSbADdcybdKbUfG4BC6S4OBv9lpRS5VyqYLX2bIR8CTeZeGHR9ee3',
  280. 'MONITOR_WEB_ID': '0a49204a-7af5-4e96-95f0-f4bafb7450ad',
  281. '__ac_nonce': '06304878000964fdad287',
  282. '__ac_signature': '_02B4Z6wo00f017Rcr3AAAIDCUVxeW1tOKEu0fKvAAI4cvoYzV-wBhq7B6D8k0no7lb'
  283. 'FlvYoinmtK6UXjRIYPXnahUlFTvmWVtb77jsMkKAXzAEsLE56m36RlvL7ky.M3Xn52r9t1IEb7IR3ke8',
  284. 'ttcid': 'e56fabf6e85d4adf9e4d91902496a0e882',
  285. '_tea_utm_cache_1300': 'undefined',
  286. 'support_avif': 'false',
  287. 'support_webp': 'false',
  288. 'xiguavideopcwebid': '7134967546256016900',
  289. 'xiguavideopcwebid.sig': 'xxRww5R1VEMJN_dQepHorEu_eAc',
  290. }
  291. urllib3.disable_warnings()
  292. s = requests.session()
  293. # max_retries=3 重试3次
  294. s.mount('http://', HTTPAdapter(max_retries=3))
  295. s.mount('https://', HTTPAdapter(max_retries=3))
  296. response = s.get(url=url, headers=headers, params=params, cookies=cookies, verify=False,
  297. proxies=Common.tunnel_proxies(), timeout=5)
  298. response.close()
  299. if 'data' not in response.json() or response.json()['data'] == '':
  300. Common.logger(log_type, crawler).warning('get_video_info: response: {}', response)
  301. else:
  302. video_info = response.json()['data']['gidInformation']['packerData']['video']
  303. video_url_dict = {}
  304. # video_url
  305. if 'videoResource' not in video_info:
  306. video_url_dict["video_url"] = ''
  307. video_url_dict["audio_url"] = ''
  308. video_url_dict["video_width"] = 0
  309. video_url_dict["video_height"] = 0
  310. elif 'dash_120fps' in video_info['videoResource']:
  311. if "video_list" in video_info['videoResource']['dash_120fps'] and 'video_4' in \
  312. video_info['videoResource']['dash_120fps']['video_list']:
  313. video_url = video_info['videoResource']['dash_120fps']['video_list']['video_4']['backup_url_1']
  314. audio_url = video_info['videoResource']['dash_120fps']['video_list']['video_4']['backup_url_1']
  315. if len(video_url) % 3 == 1:
  316. video_url += '=='
  317. elif len(video_url) % 3 == 2:
  318. video_url += '='
  319. elif len(audio_url) % 3 == 1:
  320. audio_url += '=='
  321. elif len(audio_url) % 3 == 2:
  322. audio_url += '='
  323. video_url = base64.b64decode(video_url).decode('utf8')
  324. audio_url = base64.b64decode(audio_url).decode('utf8')
  325. video_width = video_info['videoResource']['dash_120fps']['video_list']['video_4']['vwidth']
  326. video_height = video_info['videoResource']['dash_120fps']['video_list']['video_4']['vheight']
  327. video_url_dict["video_url"] = video_url
  328. video_url_dict["audio_url"] = audio_url
  329. video_url_dict["video_width"] = video_width
  330. video_url_dict["video_height"] = video_height
  331. elif "video_list" in video_info['videoResource']['dash_120fps'] and 'video_3' in \
  332. video_info['videoResource']['dash_120fps']['video_list']:
  333. video_url = video_info['videoResource']['dash_120fps']['video_list']['video_3']['backup_url_1']
  334. audio_url = video_info['videoResource']['dash_120fps']['video_list']['video_3']['backup_url_1']
  335. if len(video_url) % 3 == 1:
  336. video_url += '=='
  337. elif len(video_url) % 3 == 2:
  338. video_url += '='
  339. elif len(audio_url) % 3 == 1:
  340. audio_url += '=='
  341. elif len(audio_url) % 3 == 2:
  342. audio_url += '='
  343. video_url = base64.b64decode(video_url).decode('utf8')
  344. audio_url = base64.b64decode(audio_url).decode('utf8')
  345. video_width = video_info['videoResource']['dash_120fps']['video_list']['video_3']['vwidth']
  346. video_height = video_info['videoResource']['dash_120fps']['video_list']['video_3']['vheight']
  347. video_url_dict["video_url"] = video_url
  348. video_url_dict["audio_url"] = audio_url
  349. video_url_dict["video_width"] = video_width
  350. video_url_dict["video_height"] = video_height
  351. elif "video_list" in video_info['videoResource']['dash_120fps'] and 'video_2' in \
  352. video_info['videoResource']['dash_120fps']['video_list']:
  353. video_url = video_info['videoResource']['dash_120fps']['video_list']['video_2']['backup_url_1']
  354. audio_url = video_info['videoResource']['dash_120fps']['video_list']['video_2']['backup_url_1']
  355. if len(video_url) % 3 == 1:
  356. video_url += '=='
  357. elif len(video_url) % 3 == 2:
  358. video_url += '='
  359. elif len(audio_url) % 3 == 1:
  360. audio_url += '=='
  361. elif len(audio_url) % 3 == 2:
  362. audio_url += '='
  363. video_url = base64.b64decode(video_url).decode('utf8')
  364. audio_url = base64.b64decode(audio_url).decode('utf8')
  365. video_width = video_info['videoResource']['dash_120fps']['video_list']['video_2']['vwidth']
  366. video_height = video_info['videoResource']['dash_120fps']['video_list']['video_2']['vheight']
  367. video_url_dict["video_url"] = video_url
  368. video_url_dict["audio_url"] = audio_url
  369. video_url_dict["video_width"] = video_width
  370. video_url_dict["video_height"] = video_height
  371. elif "video_list" in video_info['videoResource']['dash_120fps'] and 'video_1' in \
  372. video_info['videoResource']['dash_120fps']['video_list']:
  373. video_url = video_info['videoResource']['dash_120fps']['video_list']['video_1']['backup_url_1']
  374. audio_url = video_info['videoResource']['dash_120fps']['video_list']['video_1']['backup_url_1']
  375. if len(video_url) % 3 == 1:
  376. video_url += '=='
  377. elif len(video_url) % 3 == 2:
  378. video_url += '='
  379. elif len(audio_url) % 3 == 1:
  380. audio_url += '=='
  381. elif len(audio_url) % 3 == 2:
  382. audio_url += '='
  383. video_url = base64.b64decode(video_url).decode('utf8')
  384. audio_url = base64.b64decode(audio_url).decode('utf8')
  385. video_width = video_info['videoResource']['dash_120fps']['video_list']['video_1']['vwidth']
  386. video_height = video_info['videoResource']['dash_120fps']['video_list']['video_1']['vheight']
  387. video_url_dict["video_url"] = video_url
  388. video_url_dict["audio_url"] = audio_url
  389. video_url_dict["video_width"] = video_width
  390. video_url_dict["video_height"] = video_height
  391. elif 'dynamic_video' in video_info['videoResource']['dash_120fps'] \
  392. and 'dynamic_video_list' in video_info['videoResource']['dash_120fps']['dynamic_video'] \
  393. and 'dynamic_audio_list' in video_info['videoResource']['dash_120fps']['dynamic_video'] \
  394. and len(
  395. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_video_list']) != 0 \
  396. and len(
  397. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_audio_list']) != 0:
  398. video_url = \
  399. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_video_list'][-1][
  400. 'backup_url_1']
  401. audio_url = \
  402. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_audio_list'][-1][
  403. 'backup_url_1']
  404. if len(video_url) % 3 == 1:
  405. video_url += '=='
  406. elif len(video_url) % 3 == 2:
  407. video_url += '='
  408. elif len(audio_url) % 3 == 1:
  409. audio_url += '=='
  410. elif len(audio_url) % 3 == 2:
  411. audio_url += '='
  412. video_url = base64.b64decode(video_url).decode('utf8')
  413. audio_url = base64.b64decode(audio_url).decode('utf8')
  414. video_width = \
  415. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_video_list'][-1][
  416. 'vwidth']
  417. video_height = \
  418. video_info['videoResource']['dash_120fps']['dynamic_video']['dynamic_video_list'][-1][
  419. 'vheight']
  420. video_url_dict["video_url"] = video_url
  421. video_url_dict["audio_url"] = audio_url
  422. video_url_dict["video_width"] = video_width
  423. video_url_dict["video_height"] = video_height
  424. else:
  425. video_url_dict["video_url"] = ''
  426. video_url_dict["audio_url"] = ''
  427. video_url_dict["video_width"] = 0
  428. video_url_dict["video_height"] = 0
  429. elif 'dash' in video_info['videoResource']:
  430. if "video_list" in video_info['videoResource']['dash'] and 'video_4' in \
  431. video_info['videoResource']['dash']['video_list']:
  432. video_url = video_info['videoResource']['dash']['video_list']['video_4']['backup_url_1']
  433. audio_url = video_info['videoResource']['dash']['video_list']['video_4']['backup_url_1']
  434. if len(video_url) % 3 == 1:
  435. video_url += '=='
  436. elif len(video_url) % 3 == 2:
  437. video_url += '='
  438. elif len(audio_url) % 3 == 1:
  439. audio_url += '=='
  440. elif len(audio_url) % 3 == 2:
  441. audio_url += '='
  442. video_url = base64.b64decode(video_url).decode('utf8')
  443. audio_url = base64.b64decode(audio_url).decode('utf8')
  444. video_width = video_info['videoResource']['dash']['video_list']['video_4']['vwidth']
  445. video_height = video_info['videoResource']['dash']['video_list']['video_4']['vheight']
  446. video_url_dict["video_url"] = video_url
  447. video_url_dict["audio_url"] = audio_url
  448. video_url_dict["video_width"] = video_width
  449. video_url_dict["video_height"] = video_height
  450. elif "video_list" in video_info['videoResource']['dash'] and 'video_3' in \
  451. video_info['videoResource']['dash']['video_list']:
  452. video_url = video_info['videoResource']['dash']['video_list']['video_3']['backup_url_1']
  453. audio_url = video_info['videoResource']['dash']['video_list']['video_3']['backup_url_1']
  454. if len(video_url) % 3 == 1:
  455. video_url += '=='
  456. elif len(video_url) % 3 == 2:
  457. video_url += '='
  458. elif len(audio_url) % 3 == 1:
  459. audio_url += '=='
  460. elif len(audio_url) % 3 == 2:
  461. audio_url += '='
  462. video_url = base64.b64decode(video_url).decode('utf8')
  463. audio_url = base64.b64decode(audio_url).decode('utf8')
  464. video_width = video_info['videoResource']['dash']['video_list']['video_3']['vwidth']
  465. video_height = video_info['videoResource']['dash']['video_list']['video_3']['vheight']
  466. video_url_dict["video_url"] = video_url
  467. video_url_dict["audio_url"] = audio_url
  468. video_url_dict["video_width"] = video_width
  469. video_url_dict["video_height"] = video_height
  470. elif "video_list" in video_info['videoResource']['dash'] and 'video_2' in \
  471. video_info['videoResource']['dash']['video_list']:
  472. video_url = video_info['videoResource']['dash']['video_list']['video_2']['backup_url_1']
  473. audio_url = video_info['videoResource']['dash']['video_list']['video_2']['backup_url_1']
  474. if len(video_url) % 3 == 1:
  475. video_url += '=='
  476. elif len(video_url) % 3 == 2:
  477. video_url += '='
  478. elif len(audio_url) % 3 == 1:
  479. audio_url += '=='
  480. elif len(audio_url) % 3 == 2:
  481. audio_url += '='
  482. video_url = base64.b64decode(video_url).decode('utf8')
  483. audio_url = base64.b64decode(audio_url).decode('utf8')
  484. video_width = video_info['videoResource']['dash']['video_list']['video_2']['vwidth']
  485. video_height = video_info['videoResource']['dash']['video_list']['video_2']['vheight']
  486. video_url_dict["video_url"] = video_url
  487. video_url_dict["audio_url"] = audio_url
  488. video_url_dict["video_width"] = video_width
  489. video_url_dict["video_height"] = video_height
  490. elif "video_list" in video_info['videoResource']['dash'] and 'video_1' in \
  491. video_info['videoResource']['dash']['video_list']:
  492. video_url = video_info['videoResource']['dash']['video_list']['video_1']['backup_url_1']
  493. audio_url = video_info['videoResource']['dash']['video_list']['video_1']['backup_url_1']
  494. if len(video_url) % 3 == 1:
  495. video_url += '=='
  496. elif len(video_url) % 3 == 2:
  497. video_url += '='
  498. elif len(audio_url) % 3 == 1:
  499. audio_url += '=='
  500. elif len(audio_url) % 3 == 2:
  501. audio_url += '='
  502. video_url = base64.b64decode(video_url).decode('utf8')
  503. audio_url = base64.b64decode(audio_url).decode('utf8')
  504. video_width = video_info['videoResource']['dash']['video_list']['video_1']['vwidth']
  505. video_height = video_info['videoResource']['dash']['video_list']['video_1']['vheight']
  506. video_url_dict["video_url"] = video_url
  507. video_url_dict["audio_url"] = audio_url
  508. video_url_dict["video_width"] = video_width
  509. video_url_dict["video_height"] = video_height
  510. elif 'dynamic_video' in video_info['videoResource']['dash'] \
  511. and 'dynamic_video_list' in video_info['videoResource']['dash']['dynamic_video'] \
  512. and 'dynamic_audio_list' in video_info['videoResource']['dash']['dynamic_video'] \
  513. and len(video_info['videoResource']['dash']['dynamic_video']['dynamic_video_list']) != 0 \
  514. and len(video_info['videoResource']['dash']['dynamic_video']['dynamic_audio_list']) != 0:
  515. video_url = video_info['videoResource']['dash']['dynamic_video']['dynamic_video_list'][-1][
  516. 'backup_url_1']
  517. audio_url = video_info['videoResource']['dash']['dynamic_video']['dynamic_audio_list'][-1][
  518. 'backup_url_1']
  519. if len(video_url) % 3 == 1:
  520. video_url += '=='
  521. elif len(video_url) % 3 == 2:
  522. video_url += '='
  523. elif len(audio_url) % 3 == 1:
  524. audio_url += '=='
  525. elif len(audio_url) % 3 == 2:
  526. audio_url += '='
  527. video_url = base64.b64decode(video_url).decode('utf8')
  528. audio_url = base64.b64decode(audio_url).decode('utf8')
  529. video_width = video_info['videoResource']['dash']['dynamic_video']['dynamic_video_list'][-1][
  530. 'vwidth']
  531. video_height = video_info['videoResource']['dash']['dynamic_video']['dynamic_video_list'][-1][
  532. 'vheight']
  533. video_url_dict["video_url"] = video_url
  534. video_url_dict["audio_url"] = audio_url
  535. video_url_dict["video_width"] = video_width
  536. video_url_dict["video_height"] = video_height
  537. else:
  538. video_url_dict["video_url"] = ''
  539. video_url_dict["audio_url"] = ''
  540. video_url_dict["video_width"] = 0
  541. video_url_dict["video_height"] = 0
  542. elif 'normal' in video_info['videoResource']:
  543. if "video_list" in video_info['videoResource']['normal'] and 'video_4' in \
  544. video_info['videoResource']['normal']['video_list']:
  545. video_url = video_info['videoResource']['normal']['video_list']['video_4']['backup_url_1']
  546. audio_url = video_info['videoResource']['normal']['video_list']['video_4']['backup_url_1']
  547. if len(video_url) % 3 == 1:
  548. video_url += '=='
  549. elif len(video_url) % 3 == 2:
  550. video_url += '='
  551. elif len(audio_url) % 3 == 1:
  552. audio_url += '=='
  553. elif len(audio_url) % 3 == 2:
  554. audio_url += '='
  555. video_url = base64.b64decode(video_url).decode('utf8')
  556. audio_url = base64.b64decode(audio_url).decode('utf8')
  557. video_width = video_info['videoResource']['normal']['video_list']['video_4']['vwidth']
  558. video_height = video_info['videoResource']['normal']['video_list']['video_4']['vheight']
  559. video_url_dict["video_url"] = video_url
  560. video_url_dict["audio_url"] = audio_url
  561. video_url_dict["video_width"] = video_width
  562. video_url_dict["video_height"] = video_height
  563. elif "video_list" in video_info['videoResource']['normal'] and 'video_3' in \
  564. video_info['videoResource']['normal']['video_list']:
  565. video_url = video_info['videoResource']['normal']['video_list']['video_3']['backup_url_1']
  566. audio_url = video_info['videoResource']['normal']['video_list']['video_3']['backup_url_1']
  567. if len(video_url) % 3 == 1:
  568. video_url += '=='
  569. elif len(video_url) % 3 == 2:
  570. video_url += '='
  571. elif len(audio_url) % 3 == 1:
  572. audio_url += '=='
  573. elif len(audio_url) % 3 == 2:
  574. audio_url += '='
  575. video_url = base64.b64decode(video_url).decode('utf8')
  576. audio_url = base64.b64decode(audio_url).decode('utf8')
  577. video_width = video_info['videoResource']['normal']['video_list']['video_3']['vwidth']
  578. video_height = video_info['videoResource']['normal']['video_list']['video_3']['vheight']
  579. video_url_dict["video_url"] = video_url
  580. video_url_dict["audio_url"] = audio_url
  581. video_url_dict["video_width"] = video_width
  582. video_url_dict["video_height"] = video_height
  583. elif "video_list" in video_info['videoResource']['normal'] and 'video_2' in \
  584. video_info['videoResource']['normal']['video_list']:
  585. video_url = video_info['videoResource']['normal']['video_list']['video_2']['backup_url_1']
  586. audio_url = video_info['videoResource']['normal']['video_list']['video_2']['backup_url_1']
  587. if len(video_url) % 3 == 1:
  588. video_url += '=='
  589. elif len(video_url) % 3 == 2:
  590. video_url += '='
  591. elif len(audio_url) % 3 == 1:
  592. audio_url += '=='
  593. elif len(audio_url) % 3 == 2:
  594. audio_url += '='
  595. video_url = base64.b64decode(video_url).decode('utf8')
  596. audio_url = base64.b64decode(audio_url).decode('utf8')
  597. video_width = video_info['videoResource']['normal']['video_list']['video_2']['vwidth']
  598. video_height = video_info['videoResource']['normal']['video_list']['video_2']['vheight']
  599. video_url_dict["video_url"] = video_url
  600. video_url_dict["audio_url"] = audio_url
  601. video_url_dict["video_width"] = video_width
  602. video_url_dict["video_height"] = video_height
  603. elif "video_list" in video_info['videoResource']['normal'] and 'video_1' in \
  604. video_info['videoResource']['normal']['video_list']:
  605. video_url = video_info['videoResource']['normal']['video_list']['video_1']['backup_url_1']
  606. audio_url = video_info['videoResource']['normal']['video_list']['video_1']['backup_url_1']
  607. if len(video_url) % 3 == 1:
  608. video_url += '=='
  609. elif len(video_url) % 3 == 2:
  610. video_url += '='
  611. elif len(audio_url) % 3 == 1:
  612. audio_url += '=='
  613. elif len(audio_url) % 3 == 2:
  614. audio_url += '='
  615. video_url = base64.b64decode(video_url).decode('utf8')
  616. audio_url = base64.b64decode(audio_url).decode('utf8')
  617. video_width = video_info['videoResource']['normal']['video_list']['video_1']['vwidth']
  618. video_height = video_info['videoResource']['normal']['video_list']['video_1']['vheight']
  619. video_url_dict["video_url"] = video_url
  620. video_url_dict["audio_url"] = audio_url
  621. video_url_dict["video_width"] = video_width
  622. video_url_dict["video_height"] = video_height
  623. elif 'dynamic_video' in video_info['videoResource']['normal'] \
  624. and 'dynamic_video_list' in video_info['videoResource']['normal']['dynamic_video'] \
  625. and 'dynamic_audio_list' in video_info['videoResource']['normal']['dynamic_video'] \
  626. and len(video_info['videoResource']['normal']['dynamic_video']['dynamic_video_list']) != 0 \
  627. and len(video_info['videoResource']['normal']['dynamic_video']['dynamic_audio_list']) != 0:
  628. video_url = video_info['videoResource']['normal']['dynamic_video']['dynamic_video_list'][-1][
  629. 'backup_url_1']
  630. audio_url = video_info['videoResource']['normal']['dynamic_video']['dynamic_audio_list'][-1][
  631. 'backup_url_1']
  632. if len(video_url) % 3 == 1:
  633. video_url += '=='
  634. elif len(video_url) % 3 == 2:
  635. video_url += '='
  636. elif len(audio_url) % 3 == 1:
  637. audio_url += '=='
  638. elif len(audio_url) % 3 == 2:
  639. audio_url += '='
  640. video_url = base64.b64decode(video_url).decode('utf8')
  641. audio_url = base64.b64decode(audio_url).decode('utf8')
  642. video_width = video_info['videoResource']['normal']['dynamic_video']['dynamic_video_list'][-1][
  643. 'vwidth']
  644. video_height = video_info['videoResource']['normal']['dynamic_video']['dynamic_video_list'][-1][
  645. 'vheight']
  646. video_url_dict["video_url"] = video_url
  647. video_url_dict["audio_url"] = audio_url
  648. video_url_dict["video_width"] = video_width
  649. video_url_dict["video_height"] = video_height
  650. else:
  651. video_url_dict["video_url"] = ''
  652. video_url_dict["audio_url"] = ''
  653. video_url_dict["video_width"] = 0
  654. video_url_dict["video_height"] = 0
  655. else:
  656. video_url_dict["video_url"] = ''
  657. video_url_dict["audio_url"] = ''
  658. video_url_dict["video_width"] = 0
  659. video_url_dict["video_height"] = 0
  660. return video_url_dict
  661. except Exception as e:
  662. Common.logger(log_type, crawler).error(f'get_video_url:{e}\n')
  663. @classmethod
  664. def get_videolist(cls, log_type, crawler, strategy, our_uid, out_uid, oss_endpoint, env, machine):
  665. try:
  666. signature = cls.random_signature()
  667. while True:
  668. url = "https://www.ixigua.com/api/videov2/author/new_video_list?"
  669. params = {
  670. 'to_user_id': str(out_uid),
  671. 'offset': str(cls.offset),
  672. 'limit': '30',
  673. 'maxBehotTime': '0',
  674. 'order': 'new',
  675. 'isHome': '0',
  676. # 'msToken': 'G0eRzNkw189a8TLaXjc6nTHVMQwh9XcxVAqTbGKi7iPJdQcLwS3-XRrJ3MZ7QBfqErpxp3EX1WtvWOIcZ3NIgr41hgcd-v64so_RRj3YCRw1UsKW8mIssNLlIMspsg==',
  677. # 'X-Bogus': 'DFSzswVuEkUANjW9ShFTgR/F6qHt',
  678. '_signature': signature,
  679. }
  680. headers = {
  681. 'referer': f'https://www.ixigua.com/home/{out_uid}/video/?preActiveKey=hotsoon&list_entrance=userdetail',
  682. 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41',
  683. }
  684. urllib3.disable_warnings()
  685. s = requests.session()
  686. # max_retries=3 重试3次
  687. s.mount('http://', HTTPAdapter(max_retries=3))
  688. s.mount('https://', HTTPAdapter(max_retries=3))
  689. response = s.get(url=url, headers=headers, params=params, proxies=Common.tunnel_proxies(), verify=False,
  690. timeout=5)
  691. response.close()
  692. cls.offset += 30
  693. if response.status_code != 200:
  694. Common.logger(log_type, crawler).warning(f"get_videolist_response:{response.text}\n")
  695. cls.offset = 0
  696. return
  697. elif 'data' not in response.text:
  698. Common.logger(log_type, crawler).warning(f"get_videolist_response:{response.text}\n")
  699. cls.offset = 0
  700. return
  701. elif not response.json()["data"]['videoList']:
  702. Common.logger(log_type, crawler).warning(f"get_videolist_response:{response.json()}\n")
  703. cls.offset = 0
  704. return
  705. else:
  706. videoList = response.json()['data']['videoList']
  707. for i in range(len(videoList)):
  708. # video_title
  709. if 'title' not in videoList[i]:
  710. video_title = 0
  711. else:
  712. video_title = videoList[i]['title'].strip().replace('手游', '') \
  713. .replace('/', '').replace('\/', '').replace('\n', '').replace('"', '').replace("'", '')
  714. # video_id
  715. if 'video_id' not in videoList[i]:
  716. video_id = 0
  717. else:
  718. video_id = videoList[i]['video_id']
  719. # gid
  720. if 'gid' not in videoList[i]:
  721. gid = 0
  722. else:
  723. gid = videoList[i]['gid']
  724. # play_cnt
  725. if 'video_detail_info' not in videoList[i]:
  726. play_cnt = 0
  727. elif 'video_watch_count' not in videoList[i]['video_detail_info']:
  728. play_cnt = 0
  729. else:
  730. play_cnt = videoList[i]['video_detail_info']['video_watch_count']
  731. # comment_cnt
  732. if 'comment_count' not in videoList[i]:
  733. comment_cnt = 0
  734. else:
  735. comment_cnt = videoList[i]['comment_count']
  736. # like_cnt
  737. if 'digg_count' not in videoList[i]:
  738. like_cnt = 0
  739. else:
  740. like_cnt = videoList[i]['digg_count']
  741. # share_cnt
  742. share_cnt = 0
  743. # video_duration
  744. if 'video_duration' not in videoList[i]:
  745. video_duration = 0
  746. else:
  747. video_duration = int(videoList[i]['video_duration'])
  748. # send_time
  749. if 'publish_time' not in videoList[i]:
  750. publish_time = 0
  751. else:
  752. publish_time = videoList[i]['publish_time']
  753. publish_time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(publish_time))
  754. # is_top
  755. if 'is_top' not in videoList[i]:
  756. is_top = 0
  757. else:
  758. is_top = videoList[i]['is_top']
  759. # user_name
  760. if 'user_info' not in videoList[i]:
  761. user_name = 0
  762. elif 'name' not in videoList[i]['user_info']:
  763. user_name = 0
  764. else:
  765. user_name = videoList[i]['user_info']['name']
  766. # user_id
  767. if 'user_info' not in videoList[i]:
  768. user_id = 0
  769. elif 'user_id' not in videoList[i]['user_info']:
  770. user_id = 0
  771. else:
  772. user_id = videoList[i]['user_info']['user_id']
  773. # avatar_url
  774. if 'user_info' not in videoList[i]:
  775. avatar_url = 0
  776. elif 'avatar_url' not in videoList[i]['user_info']:
  777. avatar_url = 0
  778. else:
  779. avatar_url = videoList[i]['user_info']['avatar_url']
  780. # cover_url
  781. if 'video_detail_info' not in videoList[i]:
  782. cover_url = 0
  783. elif 'detail_video_large_image' not in videoList[i]['video_detail_info']:
  784. cover_url = 0
  785. elif 'url' in videoList[i]['video_detail_info']['detail_video_large_image']:
  786. cover_url = videoList[i]['video_detail_info']['detail_video_large_image']['url']
  787. else:
  788. cover_url = videoList[i]['video_detail_info']['detail_video_large_image']['url_list'][0][
  789. 'url']
  790. Common.logger(log_type, crawler).info(f'---开始读取规则---')
  791. rule_dict = cls.get_rule(log_type, crawler)
  792. Common.logger(log_type, crawler).info(f'---读取规则完成---')
  793. if gid == 0 or video_id == 0 or cover_url == 0:
  794. Common.logger(log_type, crawler).info('无效视频\n')
  795. elif is_top is True and int(time.time()) - int(publish_time) > 3600 * 24 * rule_dict[
  796. 'publish_time']:
  797. Common.logger(log_type, crawler).info(
  798. f'置顶视频,且发布时间:{publish_time_str} 超过{rule_dict["publish_time"]}天\n')
  799. elif int(time.time()) - int(publish_time) > 3600 * 24 * rule_dict['publish_time']:
  800. Common.logger(log_type, crawler).info(
  801. f'发布时间:{publish_time_str}超过{rule_dict["publish_time"]}天\n')
  802. cls.offset = 0
  803. return
  804. else:
  805. video_url_dict = cls.get_video_url(log_type, crawler, gid)
  806. video_url = video_url_dict["video_url"]
  807. audio_url = video_url_dict["audio_url"]
  808. video_width = video_url_dict["video_width"]
  809. video_height = video_url_dict["video_height"]
  810. video_dict = {'video_title': video_title,
  811. 'video_id': video_id,
  812. 'gid': gid,
  813. 'play_cnt': play_cnt,
  814. 'comment_cnt': comment_cnt,
  815. 'like_cnt': like_cnt,
  816. 'share_cnt': share_cnt,
  817. 'video_width': video_width,
  818. 'video_height': video_height,
  819. 'duration': video_duration,
  820. 'publish_time_stamp': publish_time,
  821. 'publish_time_str': publish_time_str,
  822. 'is_top': is_top,
  823. 'user_name': user_name,
  824. 'user_id': user_id,
  825. 'avatar_url': avatar_url,
  826. 'cover_url': cover_url,
  827. 'audio_url': audio_url,
  828. 'video_url': video_url,
  829. 'session': signature}
  830. for k, v in video_dict.items():
  831. Common.logger(log_type, crawler).info(f"{k}:{v}")
  832. cls.download_publish(log_type=log_type,
  833. crawler=crawler,
  834. video_dict=video_dict,
  835. rule_dict=rule_dict,
  836. strategy=strategy,
  837. our_uid=our_uid,
  838. oss_endpoint=oss_endpoint,
  839. env=env,
  840. machine=machine)
  841. except Exception as e:
  842. Common.logger(log_type, crawler).error(f"get_videolist:{e}\n")
  843. @classmethod
  844. def repeat_video(cls, log_type, crawler, video_id, env, machine):
  845. sql = f""" select * from crawler_video where platform="{cls.platform}" and out_video_id="{video_id}"; """
  846. repeat_video = MysqlHelper.get_values(log_type, crawler, sql, env, machine)
  847. return len(repeat_video)
  848. # 下载 / 上传
  849. @classmethod
  850. def download_publish(cls, log_type, crawler, strategy, video_dict, rule_dict, our_uid, oss_endpoint, env, machine):
  851. try:
  852. filter_words = get_config_from_mysql(log_type, crawler, env, text='filter')
  853. for filter_word in filter_words:
  854. if filter_word in video_dict['video_title']:
  855. Common.logger(log_type, crawler).info('标题已中过滤词:{}\n', video_dict['video_title'])
  856. return
  857. if cls.download_rule(video_dict, rule_dict) is False:
  858. Common.logger(log_type, crawler).info('不满足抓取规则\n')
  859. elif cls.repeat_video(log_type, crawler, video_dict['video_id'], env, machine) != 0:
  860. Common.logger(log_type, crawler).info('视频已下载\n')
  861. else:
  862. # 下载视频
  863. Common.download_method(log_type=log_type, crawler=crawler, text='xigua_video',
  864. title=video_dict['video_title'], url=video_dict['video_url'])
  865. # 下载音频
  866. Common.download_method(log_type=log_type, crawler=crawler, text='xigua_audio',
  867. title=video_dict['video_title'], url=video_dict['audio_url'])
  868. # 合成音视频
  869. Common.video_compose(log_type=log_type, crawler=crawler,
  870. video_dir=f"./{crawler}/videos/{video_dict['video_title']}")
  871. md_title = md5(video_dict['video_title'].encode('utf8')).hexdigest()
  872. if os.path.getsize(f"./{crawler}/videos/{md_title}/video.mp4") == 0:
  873. # 删除视频文件夹
  874. shutil.rmtree(f"./{crawler}/videos/{md_title}")
  875. Common.logger(log_type, crawler).info("视频size=0,删除成功\n")
  876. return
  877. # ffmpeg_dict = Common.ffmpeg(log_type, crawler, f"./{crawler}/videos/{video_dict['video_title']}/video.mp4")
  878. # if ffmpeg_dict is None or ffmpeg_dict['size'] == 0:
  879. # Common.logger(log_type, crawler).warning(f"下载的视频无效,已删除\n")
  880. # # 删除视频文件夹
  881. # shutil.rmtree(f"./{crawler}/videos/{video_dict['video_title']}")
  882. # return
  883. # 下载封面
  884. Common.download_method(log_type=log_type, crawler=crawler, text='cover',
  885. title=video_dict['video_title'], url=video_dict['cover_url'])
  886. # 保存视频信息至txt
  887. Common.save_video_info(log_type=log_type, crawler=crawler, video_dict=video_dict)
  888. # 上传视频
  889. Common.logger(log_type, crawler).info("开始上传视频...")
  890. our_video_id = Publish.upload_and_publish(log_type=log_type,
  891. crawler=crawler,
  892. strategy=strategy,
  893. our_uid=our_uid,
  894. env=env,
  895. oss_endpoint=oss_endpoint)
  896. if env == 'dev':
  897. our_video_link = f"https://testadmin.piaoquantv.com/cms/post-detail/{our_video_id}/info"
  898. else:
  899. our_video_link = f"https://admin.piaoquantv.com/cms/post-detail/{our_video_id}/info"
  900. Common.logger(log_type, crawler).info("视频上传完成")
  901. if our_video_id is None:
  902. # 删除视频文件夹
  903. shutil.rmtree(f"./{crawler}/videos/{video_dict['video_title']}")
  904. return
  905. # 视频写入飞书
  906. Feishu.insert_columns(log_type, 'xigua', "e075e9", "ROWS", 1, 2)
  907. upload_time = int(time.time())
  908. values = [[time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(upload_time)),
  909. "定向榜",
  910. video_dict['video_title'],
  911. str(video_dict['video_id']),
  912. our_video_link,
  913. video_dict['gid'],
  914. video_dict['play_cnt'],
  915. video_dict['comment_cnt'],
  916. video_dict['like_cnt'],
  917. video_dict['share_cnt'],
  918. video_dict['duration'],
  919. str(video_dict['video_width']) + '*' + str(video_dict['video_height']),
  920. video_dict['publish_time_str'],
  921. video_dict['user_name'],
  922. video_dict['user_id'],
  923. video_dict['avatar_url'],
  924. video_dict['cover_url'],
  925. video_dict['video_url'],
  926. video_dict['audio_url']]]
  927. time.sleep(1)
  928. Feishu.update_values(log_type, 'xigua', "e075e9", "F2:Z2", values)
  929. Common.logger(log_type, crawler).info(f"视频已保存至云文档\n")
  930. # 视频信息保存数据库
  931. insert_sql = f""" insert into crawler_video(video_id,
  932. user_id,
  933. out_user_id,
  934. platform,
  935. strategy,
  936. out_video_id,
  937. video_title,
  938. cover_url,
  939. video_url,
  940. duration,
  941. publish_time,
  942. play_cnt,
  943. crawler_rule,
  944. width,
  945. height)
  946. values({our_video_id},
  947. {our_uid},
  948. "{video_dict['user_id']}",
  949. "{cls.platform}",
  950. "定向爬虫策略",
  951. "{video_dict['video_id']}",
  952. "{video_dict['video_title']}",
  953. "{video_dict['cover_url']}",
  954. "{video_dict['video_url']}",
  955. {int(video_dict['duration'])},
  956. "{video_dict['publish_time_str']}",
  957. {int(video_dict['play_cnt'])},
  958. '{json.dumps(rule_dict)}',
  959. {int(video_dict['video_width'])},
  960. {int(video_dict['video_height'])}) """
  961. Common.logger(log_type, crawler).info(f"insert_sql:{insert_sql}")
  962. MysqlHelper.update_values(log_type, crawler, insert_sql, env, machine)
  963. Common.logger(log_type, crawler).info('视频信息插入数据库成功!\n')
  964. except Exception as e:
  965. Common.logger(log_type, crawler).error(f'download_publish异常:{e}\n')
  966. @classmethod
  967. def get_follow_videos(cls, log_type, crawler, strategy, oss_endpoint, env, machine):
  968. user_list = get_user_from_mysql(log_type, crawler, crawler, env)
  969. for user in user_list:
  970. spider_link = user["spider_link"]
  971. out_uid = spider_link.split('/')[-1]
  972. user_name = user["nick_name"]
  973. our_uid = user["media_id"]
  974. Common.logger(log_type, crawler).info(f"开始抓取 {user_name} 用户主页视频\n")
  975. cls.get_videolist(log_type=log_type,
  976. crawler=crawler,
  977. strategy=strategy,
  978. our_uid=our_uid,
  979. out_uid=out_uid,
  980. oss_endpoint=oss_endpoint,
  981. env=env,
  982. machine=machine)
  983. cls.offset = 0
  984. if __name__ == '__main__':
  985. Follow.get_follow_videos('follow', 'xigua', '定向抓取策略', 'inner', 'prod', 'aliyun')