一 前言

暑假在家,精神状态一直不是很好,闲来无事,便学起了python。借助这一平台,想谈谈自己在学习中的心得与困惑,也算是记录暑期生活的一种方式。从6月底开始自学python爬虫,到今天断断续续学习了一个多月,期间看网上视频教程,翻各种帖子博客,收获颇多。可能是有点matlab的基础,学习中上手很快,期间爬过视频网站、淘宝、京东、百度图片、QQ好友空间图片、堆糖图片、政府网站获取文本信息等等,也写过小游戏,玩过数据库。后续如果有时间,会将自己写的代码整理好,分享在这里,以供交流学习。


曾在知乎上看到一句话,原话为“师兄说:‘matlab除了不能生孩子,其他什么都能实现’”。额,学了一个多月python后给我的感觉是,python不仅什么都能做,而且能生孩子,而且还能生一堆。。当然这里不是黑matlab,只是说它的适用范围不如python广泛。好了,废话不多说,进入今天的主题python爬虫视频网站。

二 解析网站

所说的视频网站是一部影院,这个网站提供很多vip视频资源,可免费在线观看。该网站的视频源有很多,例如:iqiyi,youku,mgtv,acfun,papapa(一开始这个视频源我也不知道是什么,翻了源码才知道是pptvyun)等等。

分析网站源代码

以电影摔跤吧爸爸为例http://www.yibuyy.com/play/37751-0-0.html打开网站源代码
可见有papapa和mgtv两个资源,后面都跟着字符串。mgtv$$第1集$http://www.mgtv.com/b/314894/4000292.html$mgtv$,其实中间就是芒果TV的播放地址;papapa中间夹的字符串,先不管papapa中间是什么,统一叫url_id吧,后面方便称呼。

审查元素抓包分析

打开审查元素,进行抓包分析,可在other中找到一个get请求,Request Url是:
http://sapi.goudaitv.com/youkuyun/url.php?xml=http://www.mgtv.com/b/314894/4000292.html&type=mgtv&hd=cq&wap=0&siteuser=123&lg=
此Request Url是可以拼凑出来:“网站名(据经验来看,网站名经常变动,任意一个都行,比如我在程序中使用的是http://api.goudaitv.com/youkuyun/url.php?xml,但是会影响其Preview的网页布局,使用正则时需要改变参数) + url_id &type=视频源”*,后面的参数可以省略。


然后,查看此get请求的Preview,在video里发现一个https链接:
https://disp.titan.mgtv.com/vod.do?fmt=4&pno=1121&fid=D37570B18EB50AF1EDC92A3A24A07248&file=/c1/2017/07/04_0/D37570B18EB50AF1EDC92A3A24A07248_20170704_1_1_776.mp4,这便就是视频的绝对地址。好了,只要把视频的真实地址找到,就可以放心大胆的在python中用urllib.request.urlretrieve去下载了。问题在于,直接访问这个get请求,会出错,也就是说访问缺少参数,所以将Referer和User-Agent作为头部信息提交。

mgtv视频解析

看到这儿,我们做一个大胆的假设,既然芒果视频在一部影院中的url_id是其本身的播放链接,是不是所有芒果视频的链接(包含vip)都可以这种方法解析?答案是可以的。下面动手来操作,首先进入mgtv随便找到一个视频链接,以异星觉醒为例,以下提供代码:

import requests
import re#mgtv的异星觉醒链接
mgtv_link = 'http://www.mgtv.com/b/311566/4010142.html'
#拼凑出get请求的url
url = 'http://api.goudaitv.com/youkuyun/url.php?xml=%s&type=mgtv'%(mgtv_link)#添加头部信息
headers = {'Referer':'http://api.goudaitv.com/youkuyun/ckplayer/ckplayer.swf','User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}#访问get请求
r = requests.get(url, timeout = 30, headers = headers)
print(r.text)#正则匹配视频的绝对地址
parse = re.findall(r'CDATA(.*?)]', r.text)
print('\n视频的绝对地址是:%s'%parse[1][1:])

程序运行结果:

看!视频的绝对地址解析出来了,只要在程序中换掉mgtv的视频链接,就可以想解析啥就解析啥了。

结语

至此,初步解析怎么获得视频的绝对地址。但是没有考虑视频分段的情况,本文编写的程序只提供mgtv和papapa资源的下载,其它资源大多分段,暂时只提供观看。这里吐槽一下,一部影院的papapa资源源代码设计混乱,网页源码存在问题。下面提供python代码,剖析视频爬虫结合GUI展现出来。


最近找到一个可以获得视频绝对地址的解析网站,支持各大视频网站,我用PhantomJS尝试去爬取,结果成功了,下篇准备将其结合tkinter进行编程。

三 程序源代码的实现

整体思路剖析(请结合源代码):

1.设置整体tkinter,然后通过Button(Bone)按钮传递到body函数;
2.body函数执行getlinks,通过entry输入的关键字,从一部影院进行资源搜索;然后通过Button按钮传递至middle函数;
3.middle函数执行getinfo,通过my_entry输入的视频资源编号,进行子资源进行爬取;然后通过Button按钮传递至player函数;
4.player函数通过my_entry(这里使用同一个Entry)输入的子视频的播放\下载源编号,然后根据播放源选择观看、下载,即通过Button按钮传递至choice_down(选择下载剧集)函数或者browser(选择观看剧集)函数;
5.choice_down函数通过my_entry输入的视频剧集,到网站爬取分集下载链接;通过Button按钮传递至start_down(开启下载线程)函数;
6.start_down函数指定一个进程(设置了两个下载进程),通过Button按钮传递至download函数;
7.download函数根据线程,设置下载进度以及相关设置。

python源码:

import requests
import re
from bs4 import BeautifulSoup
import urllib
import webbrowser
from tkinter import *
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
import time
import threading
import os #在一部影院中从关键字获取所有资源链接
def getlinks():global links global keywordkeyword = var2.get()url = 'http://www.yibuyy.com/search.php?searchword='+keyword r = requests.get(url, timeout = 30, headers = headers)  top = r.text.find('<!-- 头部结束 -->')bottom = r.text.find('<!-- 尾部开始 -->')link_all = r.text[top:bottom]req = re.compile(r'a href="(.*?)"[\s\S]*?"sTit">(.*?)<')links = re.findall(req, link_all) #找到所有的资源名和资源链接return links#根据gui里选择的资源,访问该资源
def getinfo(links, origin):try:r = requests.get('http://www.yibuyy.com'+links[origin-1][0], timeout = 30)r.encoding = 'utf-8'except:print('没有找到分页链接或访问超时')req = re.compile(r'span id=.*?<a>(.*?)</a>')play_root = re.findall(req, r.text)soup = BeautifulSoup(r.text, 'lxml')group = soup.find_all('div', class_="downlist mb clearfix")req_subset = re.compile(r'href="(.*?)".*?title="(.*?)"')url_total = []for each in group:links_subset = re.findall(req_subset, str(each))url_total.append(links_subset)info = list(zip(play_root, url_total)) #找到相关资源的播放源和分集信息return info#选择下载资源
def choice_down(event = None): global flagglobal download_infoflag = 1   #流动字幕传入参数,控制字幕breakif len(info[play_origin-1][1]) == 1: #当视频只有一集时,设置匹配字符num = 1subset = info[play_origin-1][1][0][1]reg = re.compile(r'%s\$\$%s\$(.*?)\$%s'%(info[play_origin-1][0], subset, info[play_origin-1][0]))else:#当视频有多集时,设置匹配字符num = int(var5.get())subset =info[play_origin-1][1][num-1][1]reg = re.compile(r'%s.*?%s\$(.*?)\$'%(info[play_origin-1][0], subset))    try:r = requests.get('http://www.yibuyy.com'+info[play_origin-1][1][num-1][0],timeout = 30)#访问视频分集源代码r.encoding = 'utf-8'video_url = re.findall(reg, r.text) #找到url_id,用于拼凑最后的get请求链接if info[play_origin-1][0] == 'mgtv':res = requests.get('http://api.goudaitv.com/youkuyun/url.php?xml=%s&type=%s'%(video_url[0],'mgtv'), timeout = 30, headers = head)#访问get请求,提交头部信息else:res = requests.get('http://api.goudaitv.com/youkuyun/url.php?xml=%s&type=%s'%(video_url[0],'pptvyun'), timeout = 30,headers = head)#访问get请求,提交头部信息parse = re.findall(r'CDATA(.*?)]', res.text) #从res中找到视频的真实地址download_info = list(zip([subset],[parse[1]]))#下载集数和视频真实地址text.insert(END,'\n%s %s下载链接:\n%s'%(keyword, download_info[0][0],download_info[0][1][1:]))#将信息插入在window中的text里print(download_info)label = Label(window, font=('楷体',10), fg = 'red',textvariable=var6).grid(row=7, column=0, columnspan=3)var6.set('……全力加速,准备下载……')var0.set('---点击开始---')button = Button(window, text='开始', width=7, height=3, bg='blue', fg='white',font=('微软雅黑',18), command = start_down)#转到下载button.focus_force()button.bind("<KeyPress-Return>", start_down)button.grid(row=4, column=2)return download_infoexcept:var3.set('访问下载链接失败或访问超时,请重试或切换播放\下载源') def start_down(event = None):global threadthread += 1th = threading.Thread(target = download)#定义多线程下载视频th.start()def openfile(event = None):os.system('explorer '+os.getcwd()+'\download')  #打开文件夹#设置下载进度1
def process1(a, b, c):per = 100.0 * a * b / cif per > 100:per = 100var6.set('%s  下载进度:%.2f%%  %.2fM/%.2fM   用时: %02d:%02d' % (t1,per, a*b/1024/1024, c/1024/1024, int(time.clock()-s1)//60 ,int(time.clock()-s1)- 60*(int(time.clock()-s1)//60)))if per == 100:var6.set('……%s 下载完毕,用时: %02d:%02d……'%(t1,int(time.clock()-s1)//60 ,int(time.clock()-s1)- 60*(int(time.clock()-s1)//60)))#设置下载进度1
def process2(a, b, c):per = 100.0 * a * b / cif per > 100:per = 100var7.set('%s  下载进度:%.2f%%  %.2fM/%.2fM   用时: %02d:%02d' % (t2,per, a*b/1024/1024, c/1024/1024, int(time.clock()-s2)//60 ,int(time.clock()-s2)- 60*(int(time.clock()-s2)//60)))if per == 100:var7.set('……%s 下载完毕,用时: %02d:%02d……'%(t2,int(time.clock()-s2)//60 ,int(time.clock()-s2)- 60*(int(time.clock()-s2)//60)))#进行下载
def download(event = None):global s1  #线程1 时间global s2  #线程2 时间global t1  #线程1 下载信息global t2  #线程2 下载信息global threadtime.sleep(1)var3.set('<---下载过程中请勿关闭本窗口--->')var0.set('---打开下载文件夹---')button = Button(window, text='打开', width=7, height=3, bg='blue', fg='white',font=('微软雅黑',18), command = openfile)button.focus_force()button.bind("<KeyPress-Return>", openfile)button.grid(row=4, column=2)if not os.path.exists('download'):os.mkdir('download')if thread == 1:  #如果是一条下载线程label = Label(window, font=('楷体',10), fg = 'red',textvariable=eval('var%d'%(thread+6))).grid(row=thread+7, column=0, columnspan=3)eval('var%d'%(thread+6)).set('……可继续添加下载……')t1 = '%s %s'%(keyword,download_info[0][0])s1 = time.clock()if thread == 2:  #如果是两条下载线程label = Label(window, font=('楷体',10), fg = 'red',textvariable=eval('var%d'%(thread+6))).grid(row=thread+7, column=0, columnspan=3)eval('var%d'%(thread+6)).set('╮(╯▽╰)╭只设置了两条下载线程╮(╯▽╰)╭')t2 = '%s %s'%(keyword,download_info[0][0])s2 = time.clock()print(thread)urllib.request.urlretrieve(download_info[0][1][1:], "download\%s.mp4" %eval('t%d'%thread), eval('process%d'%thread))thread -= 1  #下载完毕,腾出线程#打开浏览器进行观看
def browser(event = None):num = int(var5.get())var3.set('已在浏览器中打开,请移步浏览器进行观看')webbrowser.open('http://www.yibuyy.com'+info[play_origin-1][1][num-1][0],0) #定义button
def button(function):global _button_button = Button(window, text='确定',width=8, bg='blue', fg='white', font=('微软雅黑', 14), command = function, activebackground= 'red')_button.grid(row=6, column=2) _button.bind("<KeyPress-Return>", function)return _button#定义lab
def lab(picture):label = Label(window, image = picture).grid(row=4, column=2)#
def player(event = None):global play_origintry:play_origin = int(var5.get())print(play_origin)if play_origin in down_num:lab(img)var0.set('---扫一扫,加关注---')  var3.set('<---下载链接为视频真实地址,选中Crtl+c可在浏览器进行观看\下载--->')var4.set('请选择下载的集数:')my_entry.delete(0, END)_button.grid_forget()button(choice_down)         else:if len(info[play_origin-1][1]) == 1:var3.set('<---已在浏览器中打开,请移步浏览器进行观看--->')webbrowser.open('http://www.yibuyy.com'+info[play_origin-1][1][0][0],0)    else:my_entry.delete(0, END) var4.set('请输入观看的集数:')my_entry.focus_force()_button.grid_forget()button(browser)     except:var3.set('<---您输入有误,请重新输入--->')my_entry.delete(0, END)def middle(event = None):global infoglobal down_numtry:origin = int(var5.get())info = getinfo(links, origin)var3.set('<---访问papapa资源下载速度较慢,建议选择mgtv--->')text.delete(0.0, END)down_num = []for i in range(len(info)):if len(info[i][1]) == 1:if info[i][0] == 'papapa' or info[i][0] == 'mgtv':text.insert(END, '%s  %s(下载):%s = %s'%(links[origin-1][1], info[i][0], info[i][1][0][1], str(i+1))+'\n')down_num.append(i+1)else:text.insert(END, '%s  %s(观看):%s = %s'%(links[origin-1][1], info[i][0], info[i][1][0][1], str(i+1))+'\n')else:if info[i][0] == 'papapa' or info[i][0] == 'mgtv':text.insert(END, '%s  %s(下载):共%s集 = %s'%(links[origin-1][1], info[i][0], len(info[i][1]), str(i+1))+'\n')down_num.append(i+1)else:text.insert(END, '%s  %s(观看):共%s集 = %s'%(links[origin-1][1], info[i][0], len(info[i][1]), str(i+1))+'\n')my_entry.delete(0, END)    lab(godie_qr)var0.set('---微信公众号---')  var4.set('请选择播放\下载源:')my_entry.focus_force()_button.grid_forget()button(player)except:var3.set('<---您输入有误,请重新输入--->')my_entry.delete(0, END)def body(event = None):global my_entryglobal buttonlinks = getlinks()text.delete(0.0, END)if len(links) != 0:for i in range(len(links)):var3.set('<---为您找到以上资源--->')var7 = 'author:tianwen'lab(godie)var0.set('---狗带TV---')text.insert(END,links[i][1]+' = '+str(i+1)+'\n')label = Label(window, font=('楷体',14), textvariable=var4).grid(row=6, column=0)var4.set('请选择资源:')my_entry = Entry(window, textvariable=var5, font=('微软雅黑',14),relief = 'ridge')my_entry.focus_force()my_entry.icursor(10) my_entry.grid(row=6, column=1)button(middle)      else:var3.set('没有找到该资源,请重新输入关键词')entry.delete(0, END)def callback():  if messagebox.askokcancel('Quit?', 'Do you really want to quit?'):  window.destroy()       headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
head = {'Referer':'http://api.goudaitv.com/youkuyun/ckplayer/ckplayer.swf','User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}if __name__ == '__main__': global threadthread = 0#Start GUIwindow = Tk()window.title('一部影院')window.geometry('+450+210')window.resizable(False, False)window.iconbitmap('material\i.ico')photo = PhotoImage(file= 'material\ic.png')godie = PhotoImage(file= 'material\godie.png')godie_qr = PhotoImage(file= 'material\godie_qr.png')img = PhotoImage(file= 'material\ma_qr.png')var0 = StringVar()var1 = StringVar()var3 = StringVar()var2 = StringVar()var4 = StringVar()var5 = StringVar()var6 = StringVar()var7 = StringVar()var8 = StringVar()    label = Label(window, font=('楷体',14), textvariable=var1).grid(row=1, column=0)var1.set('请输入影视信息:')entry = Entry(window, textvariable=var2, font=('微软雅黑',14), relief = 'ridge')entry.focus_force()entry.grid(row=1, column=1)Bone = Button(window, text='搜索', width=8,bg='blue', fg='white', font=('微软雅黑', 14), command = body,activebackground= 'red')Bone.grid(row=1, column=2)Bone.bind("<KeyPress-Return>", body)lab(photo)#label = Label(window, image = photo).grid(row=4, column=2)label = Label(window, textvariable=var0, font=('微软雅黑',8)).grid(row=3, column=2)var0.set('---信息来源---')text = ScrolledText(window, font=('楷体',13), fg='blue',height=9,width=47)text.grid(row=3, column=0, rowspan=2, columnspan=2)text.insert(1.0,'此软件仅用于交流学习,请勿用于商业用途')label = Label(window,font=('楷体',9),fg='red',textvariable=var3).grid(row=5, column=0, columnspan=2)var3.set('<---程序准备就绪--->')window.protocol("WM_DELETE_WINDOW", callback) #询问退出 canvas = Canvas(window, height=11, width=530)canvas.grid(row=0, column=0, columnspan=3)flag = 0while True:#流动字幕string = '交流学习使用,请勿用于商业用途(Author:Tian Wen)'c=canvas.create_text(-150,8,text=string,fill='red', font=('楷体',9))  for x in range(0,300):canvas.move(c,3,0)  window.update()         time.sleep(0.05) if flag:canvas.move(c,1000,0)breakif flag:breakwindow.mainloop()

存在的问题:

1.流动字幕和开启的下载进程不能很好的融合,无奈之下,只能将while True的流动字幕break掉;
2.本文设置了Button的回车执行事件,但是好像不符合用户的习惯,下次尝试在Entry中加入回车执行事件;
3.只支持两个下载进程,并且在进度显示上存在问题:两个进程同时下载,第一个线程下载完毕后,继续添加下载,会将原第二个线程下载进度遮住;
4.tkinter布局稍显混乱,也没用根据具体电脑分辨率做相应调整;
5.初学python,程序存在很多bug,还有代码写的实在乱,万望见谅。

程序打包

最后使用pyinstaller将程序打包成exe文件,可在windows上运行,软件截图:


软件下载地址:

此软件交流学习使用,请勿用做商业用途。
百度云下载链接:http://pan.baidu.com/s/1o7XlRbc 密码:w7qf

python 爬虫视频网站相关推荐

  1. python爬虫—视频爬虫2(m3u8)

    python爬虫-视频爬虫2(m3u8) 一.视频爬虫的分析 今天我们爬的视频比上一期的要特殊一些,一些网站使用m3u8来进行视频的播放工作,特意去搜了一下m3u8与mp4相比的一些优势: 1.HTM ...

  2. python百度云盘搜索引擎_2016百度云网盘搜索引擎源码,附带Python爬虫+PHP网站+Xunsearch搜索引擎...

    品牌: 其他 语言: PHP 数据库: Mysql 源文件: 完全开源(含全部源文件) 授权: 免授权 规格: 整站源码 移动端: 无移动端 安装服务: 收费安装(另补差价) 操作系统: Window ...

  3. 视频教程-Python爬虫视频课程:中国女性胸部大小分析-Python

    Python爬虫视频课程:中国女性胸部大小分析 东北大学计算机专业硕士研究生,欧瑞科技创始人&CEO,曾任国内著名软件公司项目经理,畅销书作者,企业IT内训讲师,CSDN学院专家讲师,制作视频 ...

  4. Python爬虫视频课程:中国女性胸部大小分析-李宁-专题视频课程

    Python爬虫视频课程:中国女性胸部大小分析-830人已学习 课程介绍         本课程使用Python3作为编程语言,通过Python爬虫技术从天猫和京东抓取了近20000条胸罩销售数据来分 ...

  5. python爬虫练习网站,墙裂安利这个可以练习爬虫的网站

    python爬虫练习网站,墙裂安利这个可以练习爬虫的网站 今天无意间发现的一个大佬做的网站,http://www.glidedsky.com/,需要注册登录后跟着大佬提供的题目做,刚刚完成了第一个题目 ...

  6. Python爬虫——12306网站车次信息

    Python爬虫--12306网站车次信息 相信每一个人都听说过谷歌.百度等浏览器,我们在在输入栏中输入我们想要的关键字,便会出现与我们输入关键字有关的网页.那么这些数据时是怎么来的呢?其实这跟网络爬 ...

  7. python爬虫视频 下载 黑马_Python爬虫能爬视频么(python爬虫零基础视频教程)

    Python爬虫能爬视频么 他视频没有的,但是跑了之后你要处理这个视频,就是问题的?你只需要,得到视频的播放地址,还是要把视频完整的下载到本地的.如果只是爬那个视频的下载地址,很简单,如果要下载的话, ...

  8. python爬虫! 网站维护人员:真的求求你们了,不要再来爬取了,受不了了!!

    话说 在很久很久以前 小明不小心发现了一个叫做 学习python的正确姿势 从此一发不可收拾 看到什么网站都想爬取 有一天 小明发现了一个小黄网 里面的小姐姐 一个比一个诱人 看了一会这个小黄网 小明 ...

  9. Python爬虫之网站验证码识别(三)

    视频链接:Python爬虫7天速成(2020全新合集)无私分享 Python: 章节p29-p31 文章目录 前言 一.云打码平台使用流程 操作流程 二.代码编写⭐ 2.1 使用超级鹰云平台 2.2 ...

最新文章

  1. WPF框架教程 | 从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器
  2. 利用JQuery插件CleverTabs实现多页签打开效果
  3. 08-07 性能测试--性能监听平台
  4. matlab模式识别实验二,模式识别实验二
  5. “快陪练”获1000万美元Pre-A轮融资,单月营收破千万,俞敏洪跟投...
  6. 企业微信之发送图片消息(源码下载)
  7. 在线制作证件照教程,只需30秒
  8. 常用PHP开发工具都有哪些(2021整理)
  9. Android挂逼修练之行--微信聊天消息修改器插件开发详解
  10. Win平台ZIP版本MySql启动问题
  11. SANGFOR SCSA——协议基础
  12. ExcelToMySQL-批量导入Excel文件到MySQL数据库的自动化工具
  13. 推荐12个国外免费自助建站网站
  14. ios -生成推广海报
  15. zuk android os 流量,原生用户最爱 Cyanogen OS版ZUK Z1固件
  16. 《大圣归来》电影海报原创作者张浩谈商业海报制作思路
  17. 【是题解】luogu1726上白泽慧音
  18. telerik学习记录-RadButton(下)
  19. 创客筑梦,第二届机智云智能硬件36小时开发大赛圆满落幕
  20. 三星 android miracast,三星S7 edge连接电视、显示器、投影仪的方法详解

热门文章

  1. 一、JDK、JRE、JVM的区别
  2. 服务器防沉迷系统,明日之后防沉迷系统解读 两个小时也能领跑服务器
  3. MicroStrategy 小技巧 笔记
  4. 如何短接电脑电源使电源启动
  5. 活用Word的查找替换功能(兼有正则表达式)
  6. 可信AI治理框架探索与实践
  7. Kafka 核心源码解读【三】--Controller模块
  8. 读英语原版书两年经验分享
  9. 老鼠出迷宫详解(人人能搞懂)
  10. python 函数作用于矩阵_图解NumPy:常用函数的内在机制