Python+Tornado+Tampermonkey 獲取某訊等主流視頻網站的會員視頻解析播放


近期,《哪吒之魔童降世》在各大視頻軟件可以看了,然而卻是一貫的套路,非會員謝絕觀看!!!只能從國內那些五花八門的視頻網站上找着看了,或者通過之前本人說的 Chrome 的油猴插件,傳送門 https://www.cnblogs.com/weijiutao/p/10608107.html,進行觀看。

經過分析,通過油猴插件觀看某奇藝等主流視頻網站的方法其實就是在視頻網頁鏈接的前面加上一個視頻解析的鏈接地址,如下:

播放傳送門

 http://jx.618g.com/?url=http://www.iqiyi.com/lib/m_217405614.html?src=search

                                      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>video</title>
  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

聲明:上面的代碼只是一個簡單的實現思路,代碼中如有不妥之處請大神批評指正!同時本人嚴正聲明尊重知識產權和版權,對於上面的敏感信息不做任何商業用途,如有侵權問題請及時聯系本人,蟹蟹!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM