py_cctv_2024.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. #coding=utf-8
  2. #!/usr/bin/python
  3. import random
  4. import sys
  5. sys.path.append('..')
  6. from base.spider import Spider
  7. import json
  8. import time
  9. import base64
  10. import datetime
  11. import re
  12. from urllib import request, parse
  13. import urllib
  14. import urllib.request
  15. import time
  16. class Spider(Spider): # 元类 默认的元类 type
  17. def getName(self):
  18. return "中央电视台"#可搜索
  19. def init(self,extend=""):
  20. print("============{0}============".format(extend))
  21. pass
  22. def isVideoFormat(self,url):
  23. pass
  24. def manualVideoCheck(self):
  25. pass
  26. def homeContent(self,filter):
  27. result = {}
  28. cateManual = {
  29. "栏目大全": "栏目大全",
  30. "特别节目": "特别节目",
  31. "纪录片": "纪录片",
  32. "电视剧": "电视剧",
  33. "动画片": "动画片"
  34. }
  35. classes = []
  36. for k in cateManual:
  37. classes.append({
  38. 'type_name':k,
  39. 'type_id':cateManual[k]
  40. })
  41. result['class'] = classes
  42. if(filter):
  43. result['filters'] = self.config['filter']
  44. return result
  45. def homeVideoContent(self):
  46. result = {
  47. 'list':[]
  48. }
  49. return result
  50. def categoryContent(self,tid,pg,filter,extend):
  51. result = {}
  52. month = ""#月
  53. year = ""#年
  54. area=''#地区
  55. channel=''#频道
  56. datafl=''#类型
  57. letter=''#字母
  58. pagecount=24
  59. if tid=='动画片':
  60. id=urllib.parse.quote(tid)
  61. if 'datadq-area' in extend.keys():
  62. area=urllib.parse.quote(extend['datadq-area'])
  63. if 'dataszm-letter' in extend.keys():
  64. letter=extend['dataszm-letter']
  65. if 'datafl-sc' in extend.keys():
  66. datafl=urllib.parse.quote(extend['datafl-sc'])
  67. url='https://api.cntv.cn/list/getVideoAlbumList?channelid=CHAL1460955899450127&area={0}&sc={4}&fc={1}&letter={2}&p={3}&n=24&serviceId=tvcctv&topv=1&t=json'.format(area,id,letter,pg,datafl)
  68. elif tid=='纪录片':
  69. id=urllib.parse.quote(tid)
  70. if 'datapd-channel' in extend.keys():
  71. channel=urllib.parse.quote(extend['datapd-channel'])
  72. if 'datafl-sc' in extend.keys():
  73. datafl=urllib.parse.quote(extend['datafl-sc'])
  74. if 'datanf-year' in extend.keys():
  75. year=extend['datanf-year']
  76. if 'dataszm-letter' in extend.keys():
  77. letter=extend['dataszm-letter']
  78. url='https://api.cntv.cn/list/getVideoAlbumList?channelid=CHAL1460955924871139&fc={0}&channel={1}&sc={2}&year={3}&letter={4}&p={5}&n=24&serviceId=tvcctv&topv=1&t=json'.format(id,channel,datafl,year,letter,pg)
  79. elif tid=='电视剧':
  80. id=urllib.parse.quote(tid)
  81. if 'datafl-sc' in extend.keys():
  82. datafl=urllib.parse.quote(extend['datafl-sc'])
  83. if 'datadq-area' in extend.keys():
  84. area=urllib.parse.quote(extend['datadq-area'])
  85. if 'datanf-year' in extend.keys():
  86. year=extend['datanf-year']
  87. if 'dataszm-letter' in extend.keys():
  88. letter=extend['dataszm-letter']
  89. url='https://api.cntv.cn/list/getVideoAlbumList?channelid=CHAL1460955853485115&area={0}&sc={1}&fc={2}&year={3}&letter={4}&p={5}&n=24&serviceId=tvcctv&topv=1&t=json'.format(area,datafl,id,year,letter,pg)
  90. elif tid=='特别节目':
  91. id=urllib.parse.quote(tid)
  92. if 'datapd-channel' in extend.keys():
  93. channel=urllib.parse.quote(extend['datapd-channel'])
  94. if 'datafl-sc' in extend.keys():
  95. datafl=urllib.parse.quote(extend['datafl-sc'])
  96. if 'dataszm-letter' in extend.keys():
  97. letter=extend['dataszm-letter']
  98. url='https://api.cntv.cn/list/getVideoAlbumList?channelid=CHAL1460955953877151&channel={0}&sc={1}&fc={2}&bigday=&letter={3}&p={4}&n=24&serviceId=tvcctv&topv=1&t=json'.format(channel,datafl,id,letter,pg)
  99. elif tid=='栏目大全':
  100. cid=''#频道
  101. if 'cid' in extend.keys():
  102. cid=extend['cid']
  103. fc=''#分类
  104. if 'fc' in extend.keys():
  105. fc=extend['fc']
  106. fl=''#字母
  107. if 'fl' in extend.keys():
  108. fl=extend['fl']
  109. url = 'https://api.cntv.cn/lanmu/columnSearch?&fl={0}&fc={1}&cid={2}&p={3}&n=20&serviceId=tvcctv&t=json&cb=ko'.format(fl,fc,cid,pg)
  110. pagecount=20
  111. else:
  112. url = 'https://tv.cctv.com/epg/index.shtml'
  113. videos=[]
  114. htmlText =self.webReadFile(urlStr=url,header=self.header)
  115. if tid=='栏目大全':
  116. index=htmlText.rfind(');')
  117. if index>-1:
  118. htmlText=htmlText[3:index]
  119. videos =self.get_list1(html=htmlText,tid=tid)
  120. else:
  121. videos =self.get_list(html=htmlText,tid=tid)
  122. #print(videos)
  123. result['list'] = videos
  124. result['page'] = pg
  125. result['pagecount'] = 9999 if len(videos)>=pagecount else pg
  126. result['limit'] = 90
  127. result['total'] = 999999
  128. return result
  129. def detailContent(self,array):
  130. result={}
  131. aid = array[0].split('###')
  132. tid = aid[0]
  133. logo = aid[3]
  134. lastVideo = aid[2]
  135. title = aid[1]
  136. id= aid[4]
  137. vod_year= aid[5]
  138. actors= aid[6]
  139. brief= aid[7]
  140. fromId='CCTV'
  141. if tid=="栏目大全":
  142. lastUrl = 'https://api.cntv.cn/video/videoinfoByGuid?guid={0}&serviceId=tvcctv'.format(id)
  143. htmlTxt = self.webReadFile(urlStr=lastUrl,header=self.header)
  144. topicId=json.loads(htmlTxt)['ctid']
  145. Url = "https://api.cntv.cn/NewVideo/getVideoListByColumn?id={0}&d=&p=1&n=100&sort=desc&mode=0&serviceId=tvcctv&t=json".format(topicId)
  146. htmlTxt = self.webReadFile(urlStr=Url,header=self.header)
  147. else:
  148. Url='https://api.cntv.cn/NewVideo/getVideoListByAlbumIdNew?id={0}&serviceId=tvcctv&p=1&n=100&mode=0&pub=1'.format(id)
  149. jRoot = ''
  150. videoList = []
  151. try:
  152. if tid=="搜索":
  153. fromId='中央台'
  154. videoList=[title+"$"+lastVideo]
  155. else:
  156. htmlTxt=self.webReadFile(urlStr=Url,header=self.header)
  157. jRoot = json.loads(htmlTxt)
  158. data=jRoot['data']
  159. jsonList=data['list']
  160. videoList=self.get_EpisodesList(jsonList=jsonList)
  161. if len(videoList)<1:
  162. htmlTxt=self.webReadFile(urlStr=lastVideo,header=self.header)
  163. if tid=="电视剧" or tid=="纪录片":
  164. patternTxt=r"'title':\s*'(?P<title>.+?)',\n{0,1}\s*'brief':\s*'(.+?)',\n{0,1}\s*'img':\s*'(.+?)',\n{0,1}\s*'url':\s*'(?P<url>.+?)'"
  165. elif tid=="特别节目":
  166. patternTxt=r'class="tp1"><a\s*href="(?P<url>https://.+?)"\s*target="_blank"\s*title="(?P<title>.+?)"></a></div>'
  167. elif tid=="动画片":
  168. patternTxt=r"'title':\s*'(?P<title>.+?)',\n{0,1}\s*'img':\s*'(.+?)',\n{0,1}\s*'brief':\s*'(.+?)',\n{0,1}\s*'url':\s*'(?P<url>.+?)'"
  169. elif tid=="栏目大全":
  170. patternTxt=r'href="(?P<url>.+?)" target="_blank" alt="(?P<title>.+?)" title=".+?">'
  171. videoList=self.get_EpisodesList_re(htmlTxt=htmlTxt,patternTxt=patternTxt)
  172. fromId='央视'
  173. except:
  174. pass
  175. if len(videoList) == 0:
  176. return {}
  177. vod = {
  178. "vod_id":array[0],
  179. "vod_name":title,
  180. "vod_pic":logo,
  181. "type_name":tid,
  182. "vod_year":vod_year,
  183. "vod_area":"",
  184. "vod_remarks":'',
  185. "vod_actor":actors,
  186. "vod_director":'',
  187. "vod_content":brief
  188. }
  189. vod['vod_play_from'] = fromId
  190. vod['vod_play_url'] = "#".join(videoList)
  191. result = {
  192. 'list':[
  193. vod
  194. ]
  195. }
  196. return result
  197. def get_lineList(self,Txt,mark,after):
  198. circuit=[]
  199. origin=Txt.find(mark)
  200. while origin>8:
  201. end=Txt.find(after,origin)
  202. circuit.append(Txt[origin:end])
  203. origin=Txt.find(mark,end)
  204. return circuit
  205. def get_RegexGetTextLine(self,Text,RegexText,Index):
  206. returnTxt=[]
  207. pattern = re.compile(RegexText, re.M|re.S)
  208. ListRe=pattern.findall(Text)
  209. if len(ListRe)<1:
  210. return returnTxt
  211. for value in ListRe:
  212. returnTxt.append(value)
  213. return returnTxt
  214. def searchContent(self,key,quick):
  215. key=urllib.parse.quote(key)
  216. Url='https://search.cctv.com/ifsearch.php?page=1&qtext={0}&sort=relevance&pageSize=20&type=video&vtime=-1&datepid=1&channel=&pageflag=0&qtext_str={0}'.format(key)
  217. htmlTxt=self.webReadFile(urlStr=Url,header=self.header)
  218. videos=self.get_list_search(html=htmlTxt,tid='搜索')
  219. result = {
  220. 'list':videos
  221. }
  222. return result
  223. def playerContent(self, flag, id, vipFlags):
  224. result = {}
  225. url = ''
  226. parse = 0
  227. headers = {
  228. 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'
  229. }
  230. if flag == 'CCTV':
  231. url = self.get_m3u8(urlTxt=id)
  232. elif flag == '道长在线直播':
  233. # _url = id
  234. title = id.split('||')[0] # 获取标题
  235. _url = f'https://vdn.live.cntv.cn/api2/liveHtml5.do?channel=pc://cctv_p2p_hd{title}&channel_id={title}'
  236. htmlTxt = self.webReadFile(urlStr=_url, header=self.header)
  237. #htmlTxt = self.fetch(_url).text
  238. # print(htmlTxt)
  239. vdata = self.regStr(htmlTxt, "var .*?=.*?'(.*?)';")
  240. vdata = self.str2json(vdata)
  241. print(vdata)
  242. url = vdata['hls_url']['hls1']
  243. print(url)
  244. url = self.fixm3u8_url(url)
  245. else:
  246. try:
  247. htmlTxt = self.webReadFile(urlStr=id, header=self.header)
  248. #htmlTxt = self.fetch(id).text
  249. guid = self.get_RegexGetText(Text=htmlTxt, RegexText=r'var\sguid\s*=\s*"(.+?)";', Index=1)
  250. url = self.get_m3u8(urlTxt=guid)
  251. except:
  252. url = id
  253. parse = 1
  254. if url.find('https:') < 0:
  255. url = id
  256. parse = 1
  257. result["parse"] = parse # 1=嗅探,0=播放
  258. result["playUrl"] = ''
  259. result["url"] = url
  260. result["header"] = headers
  261. return result
  262. config = {
  263. "player": {},
  264. "filter": {
  265. "电视剧":[
  266. {"key":"datafl-sc","name":"类型","value":[{"n":"全部","v":""},{"n":"谍战","v":"谍战"},{"n":"悬疑","v":"悬疑"},{"n":"刑侦","v":"刑侦"},{"n":"历史","v":"历史"},{"n":"古装","v":"古装"},{"n":"武侠","v":"武侠"},{"n":"军旅","v":"军旅"},{"n":"战争","v":"战争"},{"n":"喜剧","v":"喜剧"},{"n":"青春","v":"青春"},{"n":"言情","v":"言情"},{"n":"偶像","v":"偶像"},{"n":"家庭","v":"家庭"},{"n":"年代","v":"年代"},{"n":"革命","v":"革命"},{"n":"农村","v":"农村"},{"n":"都市","v":"都市"},{"n":"其他","v":"其他"}]},
  267. {"key":"datadq-area","name":"地区","value":[{"n":"全部","v":""},{"n":"中国大陆","v":"中国大陆"},{"n":"中国香港","v":"香港"},{"n":"美国","v":"美国"},{"n":"欧洲","v":"欧洲"},{"n":"泰国","v":"泰国"}]},
  268. {"key":"datanf-year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"}]},
  269. {"key":"dataszm-letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"C","v":"C"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]}
  270. ],
  271. "动画片":[
  272. {"key":"datafl-sc","name":"类型","value":[{"n":"全部","v":""},{"n":"亲子","v":"亲子"},{"n":"搞笑","v":"搞笑"},{"n":"冒险","v":"冒险"},{"n":"动作","v":"动作"},{"n":"宠物","v":"宠物"},{"n":"体育","v":"体育"},{"n":"益智","v":"益智"},{"n":"历史","v":"历史"},{"n":"教育","v":"教育"},{"n":"校园","v":"校园"},{"n":"言情","v":"言情"},{"n":"武侠","v":"武侠"},{"n":"经典","v":"经典"},{"n":"未来","v":"未来"},{"n":"古代","v":"古代"},{"n":"神话","v":"神话"},{"n":"真人","v":"真人"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"奇幻","v":"奇幻"},{"n":"童话","v":"童话"},{"n":"剧情","v":"剧情"},{"n":"夺宝","v":"夺宝"},{"n":"其他","v":"其他"}]},
  273. {"key":"datadq-area","name":"地区","value":[{"n":"全部","v":""},{"n":"中国大陆","v":"中国大陆"},{"n":"美国","v":"美国"},{"n":"欧洲","v":"欧洲"},{"n":"其他","v":"其他地区"}]},
  274. {"key":"dataszm-letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"C","v":"C"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]}
  275. ],
  276. "纪录片":[
  277. {"key":"datapd-channel","name":"频道","value":[{"n":"全部","v":""},{"n":"CCTV1 综合","v":"CCTV-1综合,CCTV-1高清,CCTV-1综合高清"},{"n":"CCTV2 财经","v":"CCTV-2财经,CCTV-2高清,CCTV-2财经高清"},{"n":"CCTV3 综艺","v":"CCTV-3综艺,CCTV-3高清,CCTV-3综艺高清"},{"n":"CCTV4 中文国际","v":"CCTV-4中文国际,CCTV-4高清,CCTV-4中文国际(亚)高清"},{"n":"CCTV5 体育","v":"CCTV-5体育,CCTV-5高清,CCTV-5体育高清"},{"n":"CCTV6 电影","v":"CCTV-6电影,CCTV-6高清,CCTV-6电影高清"},{"n":"CCTV7 国防军事","v":"CCTV-7军事农业,CCTV-7军事农业高清,CCTV-7国防军事高清"},{"n":"CCTV8 电视剧","v":"CCTV-8电视剧,CCTV-8高清,CCTV-8电视剧高清"},{"n":"CCTV9 纪录","v":"CCTV-9纪录,CCTV-9高清,CCTV-9纪录高清"},{"n":"CCTV10 科教","v":"CCTV-10科教,CCTV-10高清,CCTV-10科教高清"},{"n":"CCTV11 戏曲","v":"CCTV-11戏曲,CCTV-11高清,CCTV-11戏曲高清"},{"n":"CCTV12 社会与法","v":"CCTV-12社会与法,CCTV-12高清,CCTV-12社会与法高清"},{"n":"CCTV13 新闻","v":"CCTV-13新闻,CCTV-13高清,CCTV-13新闻高清"},{"n":"CCTV14 少儿","v":"CCTV-14少儿,CCTV-14高清,CCTV-14少儿高清"},{"n":"CCTV15 音乐","v":"CCTV-15音乐,CCTV-15高清,CCTV-15音乐高清"},{"n":"CCTV17 农业农村","v":"CCTV-17农业农村高清"}]},
  278. {"key":"datafl-sc","name":"类型","value":[{"n":"全部","v":""},{"n":"人文历史","v":"人文历史"},{"n":"人物","v":"人物"},{"n":"军事","v":"军事"},{"n":"探索","v":"探索"},{"n":"社会","v":"社会"},{"n":"时政","v":"时政"},{"n":"经济","v":"经济"},{"n":"科技","v":"科技"}]},
  279. {"key":"datanf-year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"}]},
  280. {"key":"dataszm-letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"C","v":"C"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]}
  281. ],
  282. "特别节目":[
  283. {"key":"datapd-channel","name":"频道","value":[{"n":"全部","v":""},{"n":"CCTV1 综合","v":"CCTV-1综合,CCTV-1高清,CCTV-1综合高清"},{"n":"CCTV2 财经","v":"CCTV-2财经,CCTV-2高清,CCTV-2财经高清"},{"n":"CCTV3 综艺","v":"CCTV-3综艺,CCTV-3高清,CCTV-3综艺高清"},{"n":"CCTV4 中文国际","v":"CCTV-4中文国际,CCTV-4高清,CCTV-4中文国际(亚)高清"},{"n":"CCTV5 体育","v":"CCTV-5体育,CCTV-5高清,CCTV-5体育高清"},{"n":"CCTV6 电影","v":"CCTV-6电影,CCTV-6高清,CCTV-6电影高清"},{"n":"CCTV7 国防军事","v":"CCTV-7军事农业,CCTV-7高清,CCTV-7军事农业高清,CCTV-7国防军事高清"},{"n":"CCTV8 电视剧","v":"CCTV-8电视剧,CCTV-8高清,CCTV-8电视剧高清"},{"n":"CCTV9 纪录","v":"CCTV-9纪录,CCTV-9高清,CCTV-9纪录高清"},{"n":"CCTV10 科教","v":"CCTV-10科教,CCTV-10高清,CCTV-10科教高清"},{"n":"CCTV11 戏曲","v":"CCTV-11戏曲,CCTV-11高清,CCTV-11戏曲高清"},{"n":"CCTV12 社会与法","v":"CCTV-12社会与法,CCTV-12高清,CCTV-12社会与法高清"},{"n":"CCTV13 新闻","v":"CCTV-13新闻,CCTV-13高清,CCTV-13新闻高清"},{"n":"CCTV14 少儿","v":"CCTV-14少儿,CCTV-14高清,CCTV-14少儿高清"},{"n":"CCTV15 音乐","v":"CCTV-15音乐,CCTV-15高清,CCTV-15音乐高清"},{"n":"CCTV17 农业农村","v":"CCTV-17农业农村高清"}]},
  284. {"key":"datafl-sc","name":"类型","value":[{"n":"全部","v":""},{"n":"新闻","v":"新闻"},{"n":"经济","v":"经济"},{"n":"综艺","v":"综艺"},{"n":"体育","v":"体育"},{"n":"军事","v":"军事"},{"n":"影视","v":"影视"},{"n":"科教","v":"科教"},{"n":"戏曲","v":"戏曲"},{"n":"青少","v":"青少"},{"n":"音乐","v":"音乐"},{"n":"社会","v":"社会"},{"n":"公益","v":"公益"},{"n":"其他","v":"其他"}]},
  285. {"key":"dataszm-letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"C","v":"C"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]}
  286. ],
  287. "栏目大全":[{"key":"cid","name":"频道","value":[{"n":"全部","v":""},{"n":"CCTV-1综合","v":"EPGC1386744804340101"},{"n":"CCTV-2财经","v":"EPGC1386744804340102"},{"n":"CCTV-3综艺","v":"EPGC1386744804340103"},{"n":"CCTV-4中文国际","v":"EPGC1386744804340104"},{"n":"CCTV-5体育","v":"EPGC1386744804340107"},{"n":"CCTV-6电影","v":"EPGC1386744804340108"},{"n":"CCTV-7国防军事","v":"EPGC1386744804340109"},{"n":"CCTV-8电视剧","v":"EPGC1386744804340110"},{"n":"CCTV-9纪录","v":"EPGC1386744804340112"},{"n":"CCTV-10科教","v":"EPGC1386744804340113"},{"n":"CCTV-11戏曲","v":"EPGC1386744804340114"},{"n":"CCTV-12社会与法","v":"EPGC1386744804340115"},{"n":"CCTV-13新闻","v":"EPGC1386744804340116"},{"n":"CCTV-14少儿","v":"EPGC1386744804340117"},{"n":"CCTV-15音乐","v":"EPGC1386744804340118"},{"n":"CCTV-16奥林匹克","v":"EPGC1634630207058998"},{"n":"CCTV-17农业农村","v":"EPGC1563932742616872"},{"n":"CCTV-5+体育赛事","v":"EPGC1468294755566101"}]},{"key":"fc","name":"分类","value":[{"n":"全部","v":""},{"n":"新闻","v":"新闻"},{"n":"体育","v":"体育"},{"n":"综艺","v":"综艺"},{"n":"健康","v":"健康"},{"n":"生活","v":"生活"},{"n":"科教","v":"科教"},{"n":"经济","v":"经济"},{"n":"农业","v":"农业"},{"n":"法治","v":"法治"},{"n":"军事","v":"军事"},{"n":"少儿","v":"少儿"},{"n":"动画","v":"动画"},{"n":"纪实","v":"纪实"},{"n":"戏曲","v":"戏曲"},{"n":"音乐","v":"音乐"},{"n":"影视","v":"影视"}]},{"key":"fl","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"}]},{"key":"month","name":"月份","value":[{"n":"全部","v":""},{"n":"12","v":"12"},{"n":"11","v":"11"},{"n":"10","v":"10"},{"n":"09","v":"09"},{"n":"08","v":"08"},{"n":"07","v":"07"},{"n":"06","v":"06"},{"n":"05","v":"05"},{"n":"04","v":"04"},{"n":"03","v":"03"},{"n":"02","v":"02"},{"n":"01","v":"01"}]}]
  288. }
  289. }
  290. header = {
  291. "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36",
  292. "Host": "tv.cctv.com",
  293. "Referer": "https://tv.cctv.com/"
  294. }
  295. def localProxy(self,param):
  296. return [200, "video/MP2T", action, ""]
  297. #-----------------------------------------------自定义函数-----------------------------------------------
  298. #访问网页
  299. def webReadFile(self,urlStr,header):
  300. html=''
  301. req=urllib.request.Request(url=urlStr)#,headers=header
  302. with urllib.request.urlopen(req) as response:
  303. html = response.read().decode('utf-8')
  304. return html
  305. #判断网络地址是否存在
  306. def TestWebPage(self,urlStr,header):
  307. html=''
  308. req=urllib.request.Request(url=urlStr,method='HEAD')#,headers=header
  309. with urllib.request.urlopen(req) as response:
  310. html = response.getcode ()
  311. return html
  312. #正则取文本
  313. def get_RegexGetText(self,Text,RegexText,Index):
  314. returnTxt=""
  315. Regex=re.search(RegexText, Text, re.M|re.S)
  316. if Regex is None:
  317. returnTxt=""
  318. else:
  319. returnTxt=Regex.group(Index)
  320. return returnTxt
  321. #取集数
  322. def get_EpisodesList(self,jsonList):
  323. videos=[]
  324. for vod in jsonList:
  325. url = vod['guid']
  326. title =vod['title']
  327. if len(url) == 0:
  328. continue
  329. videos.append(title+"$"+url)
  330. return videos
  331. #取集数
  332. def get_EpisodesList_re(self,htmlTxt,patternTxt):
  333. ListRe=re.finditer(patternTxt, htmlTxt, re.M|re.S)
  334. videos=[]
  335. for vod in ListRe:
  336. url = vod.group('url')
  337. title =vod.group('title')
  338. if len(url) == 0:
  339. continue
  340. videos.append(title+"$"+url)
  341. return videos
  342. #取剧集区
  343. def get_lineList(self,Txt,mark,after):
  344. circuit=[]
  345. origin=Txt.find(mark)
  346. while origin>8:
  347. end=Txt.find(after,origin)
  348. circuit.append(Txt[origin:end])
  349. origin=Txt.find(mark,end)
  350. return circuit
  351. #正则取文本,返回数组
  352. def get_RegexGetTextLine(self,Text,RegexText,Index):
  353. returnTxt=[]
  354. pattern = re.compile(RegexText, re.M|re.S)
  355. ListRe=pattern.findall(Text)
  356. if len(ListRe)<1:
  357. return returnTxt
  358. for value in ListRe:
  359. returnTxt.append(value)
  360. return returnTxt
  361. #删除html标签
  362. def removeHtml(self,txt):
  363. soup = re.compile(r'<[^>]+>',re.S)
  364. txt =soup.sub('', txt)
  365. return txt.replace("&nbsp;"," ")
  366. def hookM3u8(self, url):
  367. url = url or ''
  368. hook1 = lambda x: x.replace('asp/', 'asp//', 1)
  369. hook2 = lambda x: x.replace('hls/', 'hls//', 1)
  370. hook3 = lambda x: x.replace('https://newcntv.qcloudcdn.com', 'https://hls.cntv.myalicdn.com/', 1)
  371. hooks = [hook1, hook2, hook3]
  372. hook = random.choice(hooks)
  373. return hook(url)
  374. # 取m3u8
  375. def get_m3u8(self, urlTxt):
  376. url = "https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid={0}".format(urlTxt)
  377. htmlTxt = self.webReadFile(urlStr=url, header=self.header)
  378. #htmlTxt = self.fetch(url).text
  379. jo = json.loads(htmlTxt)
  380. link = jo['hls_url'].strip()
  381. # print('hls_url:',link)
  382. # 获取域名前缀
  383. urlPrefix = self.get_RegexGetText(Text=link, RegexText='(http[s]?://[a-zA-z0-9.]+)/', Index=1)
  384. # 域名前缀指定替换,然后可以获取到更高质量的视频列表
  385. # /asp/h5e/hls/2000/0303000a/3/default/3628bb15af644f588dc91ec68425b9ac/2000.m3u8
  386. new_link = link.replace(f'{urlPrefix}/asp/hls/', 'https://dh5.cntv.qcloudcdn.com/asp/h5e/hls/').split('?')[0]
  387. # print('new_link:',new_link)
  388. html = self.webReadFile(urlStr=new_link, header=self.header)
  389. content = html.strip()
  390. arr = content.split('\n')
  391. subUrl = arr[-1].split('/')
  392. # hdUrl = urlPrefix + arr[-1]
  393. # subUrl[3] = '2000'
  394. # subUrl[-1] = '2000.m3u8'
  395. # hdUrl = urlPrefix + '/'.join(subUrl)
  396. maxVideo = subUrl[-1].replace('.m3u8', '')
  397. hdUrl = link.replace('main', maxVideo)
  398. hdUrl = hdUrl.replace(urlPrefix, 'https://newcntv.qcloudcdn.com')
  399. hdRsp = self.TestWebPage(urlStr=hdUrl, header=self.header)
  400. if hdRsp == 200:
  401. url = hdUrl.split('?')[0]
  402. url = self.hookM3u8(url)
  403. self.log(f'视频链接: {url}')
  404. else:
  405. url = ''
  406. return url
  407. def fixm3u8_url(self, url):
  408. # 获取域名前缀
  409. urlPrefix = self.get_RegexGetText(Text=url, RegexText='(http[s]?://[a-zA-z0-9.]+)/', Index=1)
  410. # 域名前缀指定替换,然后可以获取到更高质量的视频列表
  411. new_link = url.split('?')[0]
  412. # print(new_link)
  413. html = self.webReadFile(urlStr=new_link, header=self.header)
  414. content = html.strip()
  415. # print(content)
  416. arr = content.split('\n')
  417. subUrl = arr[3] if 'EXT-X-VERSION' in content else arr[2]
  418. hdUrl = self.urljoin(new_link, subUrl).split('?')[0]
  419. # hdUrl = hdUrl.replace(urlPrefix, 'https://newcntv.qcloudcdn.com')
  420. hdRsp = self.TestWebPage(urlStr=hdUrl, header=self.header)
  421. if hdRsp == 200:
  422. url = hdUrl
  423. self.log(f'视频链接: {url}')
  424. else:
  425. url = ''
  426. return url
  427. #搜索
  428. def get_list_search(self,html,tid):
  429. jRoot = json.loads(html)
  430. jsonList=jRoot['list']
  431. videos=[]
  432. for vod in jsonList:
  433. url = vod['urllink']
  434. title =self.removeHtml(txt=vod['title'])
  435. img=vod['imglink']
  436. id=vod['id']
  437. brief=vod['channel']
  438. year=vod['uploadtime']
  439. if len(url) == 0:
  440. continue
  441. guid="{0}###{1}###{2}###{3}###{4}###{5}###{6}###{7}".format(tid,title,url,img,id,year,'',brief)
  442. videos.append({
  443. "vod_id":guid,
  444. "vod_name":title,
  445. "vod_pic":img,
  446. "vod_remarks":year
  447. })
  448. return videos
  449. return videos
  450. def get_list1(self,html,tid):
  451. jRoot = json.loads(html)
  452. videos = []
  453. data=jRoot['response']
  454. if data is None:
  455. return []
  456. jsonList=data['docs']
  457. for vod in jsonList:
  458. id = vod['lastVIDE']['videoSharedCode']
  459. title =vod['column_name']
  460. url=vod['column_website']
  461. img=vod['column_logo']
  462. year=vod['column_playdate']
  463. brief=vod['column_brief']
  464. actors=''
  465. if len(url) == 0:
  466. continue
  467. guid="{0}###{1}###{2}###{3}###{4}###{5}###{6}###{7}".format(tid,title,url,img,id,year,actors,brief)
  468. #print(vod_id)
  469. videos.append({
  470. "vod_id":guid,
  471. "vod_name":title,
  472. "vod_pic":img,
  473. "vod_remarks":''
  474. })
  475. #print(videos)
  476. return videos
  477. #分类取结果
  478. def get_list(self,html,tid):
  479. jRoot = json.loads(html)
  480. videos = []
  481. data=jRoot['data']
  482. if data is None:
  483. return []
  484. jsonList=data['list']
  485. for vod in jsonList:
  486. url = vod['url']
  487. title =vod['title']
  488. img=vod['image']
  489. id=vod['id']
  490. try:
  491. brief=vod['brief']
  492. except:
  493. brief=''
  494. try:
  495. year=vod['year']
  496. except:
  497. year=''
  498. try:
  499. actors=vod['actors']
  500. except:
  501. actors=''
  502. if len(url) == 0:
  503. continue
  504. guid="{0}###{1}###{2}###{3}###{4}###{5}###{6}###{7}".format(tid,title,url,img,id,year,actors,brief)
  505. #print(vod_id)
  506. videos.append({
  507. "vod_id":guid,
  508. "vod_name":title,
  509. "vod_pic":img,
  510. "vod_remarks":''
  511. })
  512. return videos