python小练习:网络视频下载
python小练习:网络视频下载
互联网上有很多视频网站,提供大量视频。可是大多都要求你使用它提供的专有软件才能下载,或者根本没提供下载的地方。在linux下怎么办?总是有办法的。浏览器扩展,you-get,直接从硕鼠解析出地址自己下载……
这不是重点,重点是:自己动手玩一玩。 - 顺便学习下几个python标准库:=urllib=、=urllib2=、=re=。 - 初步学习http报头知识 Extra bonus: - flv文件结构
都是随便看看。
下载视频
简单起见,直接从硕鼠抓取地址。
首先我们随便找一个视频地址,比如来自sina的憨豆特工。我们把地址用硕鼠解析出来看看:
哇哦,一个电影被分成15个文件了。
我们接下来要做的就是抓取这十五个视频的地址并把他们下载下来。
也许,用正则是个不错的办法。查看该页面源码,可以找到这样的内容:
<input type="hidden" name="inf" value="<R>憨豆特工 <T>0 <F>http://video.sina.com.cn/v/b/56925622-2257301331.html <QX>normal <$> <N>憨豆特工-0001 <P>新浪网 <U>http://edge.v.iask.com/56926940.hlv?KID=sina,viask&Expires=1354550400&ssig=0G8Acouy32 <X>0001 <C>aHR0cDovL3YuaWFzay5jb20vdl9wbGF5LnBocD92aWQ9NTY5MjU2MjItMjI1NzMwMTMzMSZyPXZpZGVvLnNpbmEuY29tLmNu <EXPLODEID>1 <&> <$> <N>憨豆特工-0002 <P>新浪网 <U>http://edge.v.iask.com/56921791.hlv?KID=sina,viask&Expires=1354550400&ssig=aDBPWf%2B2YH <X>0001 <C>aHR0cDovL3YuaWFzay5jb20vdl9wbGF5LnBocD92aWQ9NTY5MjU2MjItMjI1NzMwMTMzMSZyPXZpZGVvLnNpbmEuY29tLmNu <EXPLODEID>2 <&> <$> <N>憨豆特工-0003 <P>新浪网 ......
显然,=<N>=后面是片名而=<U>=后面是地址。
另外,我们观察一下硕鼠当前页面的url地址。
http://www.flvcd.com/parse.php?kw=http%3A%2F%2Fvideo.sina.com.cn%2Fv%2Fb%2F56925622-2257301331.html
显然,kw参数后面是之前sina视频页面地址,只不过已经经过转码处理。
至此,足够我们用python来完成这一切了。
打开ipython:
In [1]: import urllib In [2]: import urllib2 In [3]: videourl = 'http://video.sina.com.cn/v/b/56925622-2257301331.html' In [4]: url = 'http://www.flvcd.com/parse.php?kw=' + urllib.quote(videourl) In [5]: req = urllib2.Request(url); In [6]: req.add_header('host', 'www.flvcd.com'); In [7]: res = urllib2.urlopen(req) In [8]: html = res.read() In [9]: print unicode(html,'gbk') # 注意硕鼠的页面编码是charset=GB2312
至此,我们完成了从硕鼠读取整个网页的操作。并把读取的内容保存在html中。
接下来开始抓地址,根据之前的观察,很容易通过正则表达式完成:
In [13]: import re In [14]: pattern = re.compile('<input\s+type="hidden"\s+name="inf"\s+value="([^"]+)') In [15]: match = pattern.search(html) In [16]: urls = match.group(1) In [17]: urls = unicode(urls, 'gbk') In [18]: urlpattern = re.compile('<[NU]>(.+)') In [19]: result = urlpattern.findall(urls)
至此,=<N>=和=<U>=后面的文件名和地址都被以列表的形式保存在result中了。我们可以遍历它来完成下载:
先简单处理下,以文件名-地址成对保存:
In [28]: data = [result[i:i+2] for i in range(0, len(result), 2)]
然后遍历下载:
In [32]: for k, v in enumerate(data): print ' >downloading Block %.2d ...' % (k+1,) urllib.urlretrieve(v[1], v[0] + '.flv') print ' downloaded Block.%.2d completely<' % (k+1,)
然后?等着……目前的下载器相当简陋,木有进度条,木有断点……
之后就是合并flv的问题了。
合并flv文件
简单起见,直接用这里join\flv.py来完成。
python2 join_flv.py -o out.flv flv1.flv flv2.flv ...
如果你想深入了解flv文件结构,参考further reading部分和flv文件规范。
Practice
抓取这里的视频。并按名称保存他们:
- https://class.coursera.org/ml/lecture/preview
- http://v.163.com/special/opencourse/machinelearning.html
作为正则和urllib、urllib2的练习。
Further Reading
- 在线视频下载(Using Python / Bash / C / Reguar Expressions)
- flv文件详解
- FLV文件格式解析
- you-get