近期,《哪吒之魔童降世》在各大视频软件可以看了,然而却是一贯的套路,非会员谢绝观看!!!只能从国内那些五花八门的视频网站上找着看了,或者通过之前本人说的 Chrome 的油猴插件,传送门 https://www.cnblogs.com/weijiutao/p/10608107.html,进行观看。
经过分析,通过油猴插件观看某奇艺等主流视频网站的方法其实就是在视频网页链接的前面加上一个视频解析的链接地址,如下:
播放传送门
http://www.iqiyi.com/lib/m_217405614.html?src=search
http://jx.618g.com/?url=http://www.iqiyi.com/lib/m_217405614.html?src=search
通过上面的分析,本人萌生了一个将 Tampermonkey 和 主流视频网站 联系起来的一个小工具,通过自己输入想要观看的视频,然后通过油猴插件里面的视频解析网站解析出来,效果如下:
首先我们要做的就是从某奇艺等网站上获取到我们想要的视频信息,如海报,电影名,演员,导演,简介和播放链接等信息。
本人选用了 Python 语言开发,结合 Tornado 框架将想要的信息呈现到 web 页面上。目录结构如下:
项目的主入口为 app.py ,代码如下:
1 import tornado.web 2 import tornado.ioloop 3 import tornado.httpserver 4 import tornado.options 5 import os 6 7 import spider.tv.tencent 8 import spider.tv.aiqiyi 9 10 import spider.movie.tencent 11 import spider.movie.aiqiyi 12 13 import spider.variety.tencent 14 import spider.variety.aiqiyi 15 16 from tornado.options import options 17 from tornado.web import RequestHandler, StaticFileHandler 18 19 tornado.options.define("port", type=int, default=8000, help="服务器端口") 20 21 22 class IndexHandler(RequestHandler): 23 24 # 主页处理类 25 def get(self): 26 self.render("index.html") 27 28 def post(self): 29 self.render("index.html") 30 31 32 class TvpalyHandler(RequestHandler): 33 def post(self): 34 name = self.get_argument("name") 35 type = self.get_argument("type") 36 if type == '1': 37 resultTencent = spider.tv.tencent.tencents(self, name) 38 resultAiqiyi = spider.tv.aiqiyi.aiqiyi(self, name) 39 data = { 40 "tencent": resultTencent, 41 "aiqiyi": resultAiqiyi, 42 } 43 self.write(data) 44 elif type == '2': 45 resultTencent = spider.movie.tencent.tencents(self, name) 46 resultAiqiyi = spider.movie.aiqiyi.aiqiyi(self, name) 47 data = { 48 "tencent": resultTencent, 49 "aiqiyi": resultAiqiyi, 50 } 51 self.write(data) 52 elif type == '3': 53 resultTencent = spider.variety.tencent.tencents(self, name) 54 resultAiqiyi = spider.variety.aiqiyi.aiqiyi(self, name) 55 data = { 56 "tencent": resultTencent, 57 "aiqiyi": resultAiqiyi, 58 } 59 self.write(data) 60 61 62 if __name__ == '__main__': 63 tornado.options.parse_command_line() 64 current_path = os.path.dirname(__file__) 65 app = tornado.web.Application( 66 [ 67 68 (r'/', IndexHandler), 69 (r'/api/tvplay', TvpalyHandler), 70 (r'/(.*)', StaticFileHandler, { 71 "path": os.path.join(current_path, "statics/html"), 72 "default_filename": "index.html" 73 }), 74 ], 75 static_path=os.path.join(current_path, "static"), 76 template_path=os.path.join(current_path, "template"), 77 debug=True, 78 autoescape=None 79 ) 80 81 http_server = tornado.httpserver.HTTPServer(app) 82 http_server.listen(options.port) 83 tornado.ioloop.IOLoop.current().start()
由于本人没有经过系统的 Python 学习,完全都是自学而来,所以代码中如有什么不妥之处请大神批评指正。
在上面的代码中,我们做的内容其实是接收前端发来的 POST 请求,并通过 type 类型去目录 spider 中调用不同类型的内容(电影,电视剧,综艺),上面我们在 web 页面搜索 哪吒 其实就是 type == 2 时所要做的处理,即调用目录 spider->movie 下的 aiqiyi.py 和 tencent.py,由于某酷的web页面全是动态js加载的,内容不好做处理,这里就忽略了。
我们以 aiqiyi.py 为例,tencent.py 代码其实大同小异,思路一样。代码如下:
1 from urllib import request, parse 2 from lxml import etree 3 import ssl 4 5 # 取消 https 代理验证 6 ssl._create_default_https_context = ssl._create_unverified_context 7 8 9 def aiqiyi(self, name): 10 # 报头 11 user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' 12 headers = {'User-Agent': user_agent} 13 url = "https://so.iqiyi.com/so/q_" + parse.quote(name) 14 req = request.Request(url, headers=headers) 15 try: 16 response = request.urlopen(req) 17 # 获取每页的HTML源码字符串 18 html = response.read().decode('utf-8') 19 # 解析html 为 HTML 文档 20 selector = etree.HTML(html) 21 22 # 来源 23 source = "爱奇艺视频" 24 25 # 剧照 26 pic = 'https:' + \ 27 selector.xpath('//ul[@class="mod_result_list"]/li[1]/a//img/@src')[0] 28 29 # 导演 30 director = selector.xpath( 31 "//ul[@class='mod_result_list']/li[1]//div[@class='info_item'][1]/div[@class='result_info_cont result_info_cont-half'][1]/a[@class='result_info_link']/text()") 32 # 主演 33 actor = selector.xpath( 34 "//ul[@class='mod_result_list']/li[1]//div[@class='info_item'][1]/div[@class='result_info_cont result_info_cont-half'][2]/a[@class='result_info_link']/text()") 35 36 # 简介 37 desc = selector.xpath( 38 "//ul[@class='mod_result_list']/li[@class='list_item'][1]//div[@class='info_item'][2]//span[@class='result_info_txt']/text()")[ 39 0] 40 41 # 链接 42 link = selector.xpath('//ul[@class="mod_result_list"]/li[1]/a/@href')[0] 43 defalut_result = { 44 "source": source, 45 "name": name, 46 "pic": pic, 47 "director": director, 48 "actor": actor, 49 "desc": desc, 50 "list": [{'title': '播放', 'link': link}] 51 } 52 return defalut_result 53 except Exception: 54 print(url, Exception) 55 data = {"code": -1, "message": "error", "data": None} 56 return data
我们要解析的页面其实是 'https://so.iqiyi.com/so/q_' + 要搜索的内容,如下图所示:
然后我们就可以通过 python 爬虫来抓取页面中的内容信息了,从上面的页面截图可以发现我们输入的搜索字其实搜索到了一些其他的信息,这些信息在提取过程中会出现很多复杂情况,所以再这里本人就只提取了第一个内容,即可以播放的 哪吒之魔童降世 的完整视频。
本人选用的是通过 xpath 的形式来抓取,具体 dom 抓取操作可以看本人之前的文章,传送门
https://www.cnblogs.com/weijiutao/p/10879871.html
https://www.cnblogs.com/weijiutao/p/10880805.html
https://www.cnblogs.com/weijiutao/p/10614694.html
通过 aiqiyi.py 我们就爬取到了我们想要的视频内容,然后将获取到的信息返回给前端页面即可,
前端页面 teplate->index.html 代码如下:
1 DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>videotitle> 6 <link rel="stylesheet" href="/static/css/element.css"> 7 <link rel="stylesheet" href="/static/css/style.css"> 8 <script src="/static/js/common/vue.js">script> 9 <script src="/static/js/common/axios.js">script> 10 <script src="/static/js/common/element.js">script> 11 <script src="/static/js/common/qs.js">script> 12 <script src="/static/js/common/request.js">script> 13 <script src="/static/js/common/jquery.js">script> 14 head> 15 <body> 16 <div id="app" v-cloak> 17 18 19 <el-container> 20 <el-header> 21 <template v-for="item in apiLink"> 22 <el-button type="text" @click="openLinkClick(item.link)">接口[[item.id]]el-button> 23 template> 24 el-header> 25 <el-container class="main_container"> 26 <el-aside width="200px"> 27 <div class="friends_link"> 28 <h3>友情链接h3> 29 <template v-for="(item,index) in friendsLink"> 30 <template v-if="index%3 ==0"> 31 <a :href="item.link" target="_blank"> 32 <el-tag type="warning">[[item.name]]el-tag> 33 a> 34 template> 35 <template v-else-if="index%4 ==0"> 36 <a :href="item.link" target="_blank"> 37 <el-tag type="success">[[item.name]]el-tag> 38 a> 39 template> 40 <template v-else-if="index%5 ==0"> 41 <a :href="item.link" target="_blank"> 42 <el-tag type="primary">[[item.name]]el-tag> 43 a> 44 template> 45 <template v-else-if="index%7 ==0"> 46 <a :href="item.link" target="_blank"> 47 <el-tag type="danger">[[item.name]]el-tag> 48 a> 49 template> 50 <template v-else> 51 <a :href="item.link" target="_blank"> 52 <el-tag type="info">[[item.name]]el-tag> 53 a> 54 template> 55 template> 56 div> 57 58 el-aside> 59 <el-container> 60 <el-main> 61 <el-link type="success">将主流网站,如腾讯、爱奇艺、优酷等网站上的播放视频页的 url 链接复制在下方,然后选择接口,点击播放即可el-link> 62 <el-form :inline="true" :model="formCopyLink"> 63 <el-form-item> 64 <el-input v-model="formCopyLink.copyLink" placeholder="请输入内容">el-input> 65 el-form-item> 66 <el-form-item> 67 <el-select style="width: 120px;" v-model="formCopyLink.apiLink" placeholder="请选择"> 68 <el-option 69 v-for="item in apiLink" 70 :key="item.id" 71 :label="'接口'+item.id" 72 :value="item.link" 73 > 74 el-option> 75 el-select> 76 el-form-item> 77 <el-form-item> 78 <el-button type="primary" @click="openCopyLinkPlayClick">播放el-button> 79 el-form-item> 80 el-form> 81 <el-link type="success">目前只支持爱奇艺,腾讯视频简单搜索,然后选择视频类型,点击搜索即可,后续功能完善中...el-link> 82 <el-form :inline="true" :model="formTv"> 83 <el-form-item> 84 <el-input v-model="formTv.name" placeholder="请输入内容">el-input> 85 el-form-item> 86 <el-form-item> 87 <el-select style="width: 120px;" v-model="formTv.type" placeholder="请选择"> 88 <el-option label="电视剧" value="1">el-option> 89 <el-option label="电影" value="2">el-option> 90 <el-option label="综艺" value="3">el-option> 91 el-select> 92 el-form-item> 93 <el-form-item> 94 <el-button type="primary" @click="requestGetTvPlay">搜索el-button> 95 el-form-item> 96 el-form> 97 98 99 <tv-movie 100 :tvMovie="aiqiyiData" 101 @select-link="selectLinkClick" 102 >tv-movie> 103 104 <tv-movie 105 :tvMovie="tencentData" 106 @select-link="selectLinkClick" 107 >tv-movie> 108 109 el-main> 110 <el-footer>el-footer> 111 el-container> 112 el-container> 113 el-container> 114 115 116 div> 117 body> 118 <script> 119 120 121 Vue.component('tv-movie', { 122 delimiters: ["[[", "]]"], 123 props: ['tvmovie'], 124 data: function () { 125 return {} 126 }, 127 methods: { 128 selectLinkChange(link) { 129 this.$emit('select-link', link) 130 } 131 }, 132 template: ` 133 <div class="tv_movie"> 134 <template v-if="tvmovie"> 135 <h3 class="tv_movie_source">[[tvmovie.source]]</h3> 136 <div class="tv_movie_content"> 137 <div class="tv_movie_content_left"> 138 <el-image :src="tvmovie.pic"></el-image> 139 </div> 140 <div class="tv_movie_content_right"> 141 <div> 142 <p>[[tvmovie.name]]</p> 143 </div> 144 <div> 145 <p>导演:[[tvmovie.director]]</p> 146 <p>演员:[[tvmovie.actor]]</p> 147 </div> 148 <div> 149 <p>简介:[[tvmovie.desc]]</p> 150 </div> 151 <div> 152 <template v-for="item in tvmovie.list"> 153 <el-button size="mini" @click="selectLinkChange(item.link)">[[item.title]] 154 </el-button> 155 </template> 156 </div> 157 </div> 158 </div> 159 </template> 160 </div> 161 162 ` 163 }) 164 165 let app = new Vue({ 166 delimiters: ["[[", "]]"], 167 el: "#app", 168 data: { 169 formCopyLink: { 170 copyLink: "", 171 apiLink: "", 172 }, 173 formTv: { 174 name: "", 175 type: "1", 176 }, 177 apiLink: [], 178 friendsLink: [], 179 aiqiyiData: null, 180 tencentData: null, 181 selectLink: null, 182 }, 183 mounted() { 184 this.requestGetMockApiLink(); 185 this.requestGetMockFriendsLink(); 186 }, 187 methods: { 188 requestGetTvPlay() { 189 if (!this.formTv.name) return this.$message.warning("请输入要播放的内容"); 190 let data = {...this.formTv}; 191 requestFunc(null, '/api/tvplay', data, (data) => { 192 if (!data.aiqiyi) this.$message.warning("爱奇艺没搜到数据"); 193 if (!data.tencent) this.$message.warning("腾讯没搜到数据"); 194 this.aiqiyiData = data.aiqiyi; 195 this.tencentData = data.tencent; 196 }) 197 }, 198 requestGetMockApiLink() { 199 requestFunc('get', '/static/mock/apiLink.json', null, (data) => { 200 this.apiLink = data; 201 }) 202 }, 203 requestGetMockFriendsLink() { 204 requestFunc('get', '/static/mock/friendsLink.json', null, (data) => { 205 this.friendsLink = data; 206 }) 207 }, 208 selectLinkClick(link) { 209 this.selectLink = link; 210 }, 211 openLinkClick(link) { 212 if (!this.selectLink) return this.$message.warning("请选择要播放的剧集"); 213 window.open(link + this.selectLink, '_blank'); 214 }, 215 openCopyLinkPlayClick() { 216 if (!this.formCopyLink.copyLink) return this.$message.warning("请输入要播放 url 链接"); 217 if (!this.formCopyLink.apiLink) return this.$message.warning("请选择要播放的接口"); 218 window.open(this.formCopyLink.apiLink + this.selectLink, '_blank'); 219 } 220 221 }, 222 }); 223 224 script> 225 html>
在上面的代码中,我们使用了 vue+elementUi 来写前端的代码,并且引入了一些本人所知道的一些五花八门的视频网站的友情链接,其中这些友情链接和 Tampermonkey 中的视频解析链接存在了本地的文件 static->mock 的 json 文件中。
就此,一个简单的破解VIP视频的小工具就完成了。有需要代码可以去码云上查看:https://gitee.com/vijtor/video。
声明:上面的代码只是一个简单的实现思路,代码中如有不妥之处请大神批评指正!同时本人严正声明尊重知识产权和版权,对于上面的敏感信息不做任何商业用途,如有侵权问题请及时联系本人,蟹蟹!!!