最近着迷化学, 特别是古代的冶炼技术,感叹古人的聪明。

春秋时期的炼铁方法是块炼铁,即在较低的冶炼温度下,将铁矿石固态还原获得海绵铁,再经锻打成的铁块。冶炼块炼铁,一般采用地炉、平地筑炉和竖炉3种。铁矿石在温度较高的炼铁炉中高温还原并渗碳,得到含碳达到3~4%的液态生铁。战国初期,我国已掌握了脱碳、热处理技术方法,发明了韧性铸铁。

在中国,钢铁的总产量在唐代年产已达到1200吨,宋朝为4700吨,明朝最多达到4万吨。在13世纪,中国是世界上最大的铁的生产国和消费国,直到17世纪仍保持着这一领先地位。从汉代到明朝,中国人不仅在数量上处于领先地位,而且还拥有世界上最先进的钢铁冶炼技术。
铸铁脱碳钢 将含碳3~4%的低硅铸铁器在氧化气氛中加热,在适当条件下,特别是厚度不大的情况下,可以避免石墨的形成。早期炼铁温度较低,含硅量低,石墨析出较慢,有利于脱碳,使制造韧性铸铁的工艺发展成为铸铁脱碳成钢的方法。这种钢称为铸铁脱碳钢,这类钢板可加工成的铁镞、环首刀。

炒钢 向熔化的生铁鼓风,同时进行搅拌促使生铁中的碳氧化。用这种方法可将生铁制成熟铁,再经过渗碳锻打成钢。也可有控制地把生铁含碳量炒到需要的程度,再锻制成钢制品。这种钢中含有的硅酸铁夹杂物成分比较一致而数量较少。炒钢技术始于西汉末年,到东汉已相当普及。江苏出土新莽残剑,徐州出土建初二年(77)五十炼钢剑,山东临沂苍山出土的永初六年(112)三十炼钢刀等所用的原料都属于这一类型。曹操(155~220)在《内诫令》提到“百炼利器”,孙权(182~252)有以“百炼”命名的宝刀。初步可以认为百炼钢是用炒钢反复叠打变形,细化晶粒和夹杂物而成的,甚至可以用不同含碳钢材复合组成。炼数大致相当于反复折叠锻打后最后的层数。炼数增多,表明加工量加大,晶粒和夹杂进一步细化,质量提高。炒钢技术的发明是炼钢史上的一次革命。

来源:http://wenku.baidu.com/view/7c9bd28d84868762caaed5ed.html

哎! 就在查找古人是如何冶炼金属、铸造钱币、分离金属元素时,找到了这个大连理工大学讲的“化学与社会”公开课。讲的很有调理,让读者很容易理解,越看越觉的这个公开课是一个经典课程,想收藏页面怕以后链接会失效,所以决定把这个经典的公开课下载下来。

那么问题来了,下载网页嵌入的flash 视频,不是容易的事。试了网上好多视频下载插件(DownLoad Helper 、 VDownLoad嗅探器、flv视频下载、ImovieBox)也么有分析出网页的链接视频。好吧,我使用F12 调试网页工具查看网络响应,发现有type=video/mp4,然后另存为就可以了,但问题是课程有近100个,不可能一个个打开链接,查看网页Network点击视频让其加载出type=video/mp4 类型,再另存为。这样太麻烦了。开动脑筋想用程序直接把视频下载链接分析出来,然后保存在本地。

1. 获取链接地址

查看:http://ptr.chaoxing.com/course/2533204.html 源码,课程的list写在了clas=“p20” ul里面的li标签列表中
通过PyQuery可以获取所有课程的视频播放地址

  1. d = self.pq('http://ptr.chaoxing.com/course/2533204.html')
  2. DomTree = d('.p20 ul li a')
  3. for my_div in DomTree.items():
  4. URL = 'http://ptr.chaoxing.com' + my_div.attr('href') # 课时detail URL
  5. l = my_div.find('.l').html() # 课时章节NO
  6. r = my_div.find('.r').html() # 课时Name
  7. self.LessonList.append({'url': URL, "name": l + r})

2. 分析下载地址

打开一个课程视频播放时,都会XHR请求加载一个链接,该链接的内容是:

然而我们发现,每一个视频地址页面都会请求一个类似于这样的地址:http://ptr.chaoxing.com/ananas/status/************?k=&_dc=1476770383911
该地址返回一个带有视频mp4路径的Json格式字符串。其中filename为当前视频课程的名称,http为(standard)标准清晰视频 sd.mp4, httphd为(high)高清视频 hd.mp4
进一步的分析我们发现,在该地址请求之前有一个类型为Document的html加载出页面内容区域的html flash播放器

当这个播放器加载完成通过all-classes.js?v=20141027:1的Ajax请求http://ptr.chaoxing.com/ananas/status/************?k=&_dc=***。查看网页源代码,查找status后的这一串字符串发现这个字符串应该是视频播放的objectID

在iframe标签的data属性里面。试着复制一个视频的objectID去模拟请求http://ptr.chaoxing.com/ananas/status/************发现居然成功了!不知道此方法是否也使用其他flash视频下载。
这样下载课程视频的思路就出来了:在第一步获取下载链接,通过每一个视频页面源码中的objectID去请求http://ptr.chaoxing.com/ananas/status/************ 获取下载地址。然后下载视频教程。so easy!

3. 下载视频

通过上一步分析地址,已经知道获取flash视频objectID并Ajax 请求http://ptr.chaoxing.com/ananas/status/************ 就能获取视频地址。这一步我们就下载视频。
通过PyQuery 获取视频页面中的objectID

  1. def getVideo(self, url):
  2. '''
  3. 获取视频
  4. '''
  5. d = self.pq(url)
  6. DomTree = d("iframe")
  7. jsonData = DomTree.attr('data')
  8. objectid = json.loads(jsonData)['objectid'] # 获取下载资源视频的对象
  9. downloadUrl = self.pq('http://ptr.chaoxing.com/ananas/status/' + objectid) # 获取下载资源的URL
  10. jsonData = json.loads(downloadUrl.html())['httphd'] # 在这里,我们要下载的是高清视频
  11. return jsonData

在视频下载中遇到了些小问题,可参考:https://www.zhihu.com/question/41132103

完整代码:

  1. # -*- coding: UTF8 -*-
  2. from pyquery import PyQuery as pq
  3. import sys, os
  4. import json
  5. import requests
  6. from contextlib import closing
  7.  
  8. class SaveVideo():
  9. LessonList = []
  10.  
  11. def __init__(self):
  12. pass
  13.  
  14. # 获取课时的列表
  15. def getLesson(self):
  16. try:
  17. # 该网站请求时必须带上User-Agent
  18. d = self.pq('http://ptr.chaoxing.com/course/2533204.html')
  19. DomTree = d('.p20 ul li a')
  20. for my_div in DomTree.items():
  21. URL = 'http://ptr.chaoxing.com' + my_div.attr('href') # 课时detail URL
  22. l = my_div.find('.l').html() # 课时章节NO
  23. r = my_div.find('.r').html() # 课时Name
  24. self.LessonList.append({'url': URL, "name": l + r})
  25. except Exception as e:
  26. print(e)
  27.  
  28. if (len(self.LessonList) > 0):
  29. if not os.path.exists('./Video'):
  30. os.makedirs('./Video')
  31.  
  32. for lesson in self.LessonList:
  33. video = self.getVideo(lesson['url'])
  34. if video:
  35. self.downloadVideo(video, lesson['name'])
  36.  
  37. print('完成下载!!!')
  38.  
  39. def getVideo(self, url):
  40. '''
  41. 获取视频
  42. '''
  43. d = self.pq(url)
  44. DomTree = d("iframe")
  45. jsonData = DomTree.attr('data')
  46. video=''
  47. try:
  48. objectid = json.loads(jsonData)['objectid'] # 获取下载资源视频的对象
  49. downloadUrl = self.pq('http://ptr.chaoxing.com/ananas/status/' + objectid) # 获取下载资源的URL
  50. video = json.loads(downloadUrl.html())['httphd'] # 在这里,我们要下载的是高清视频
  51. except:
  52. pass
  53. return video
  54.  
  55. def pq(self, url, headers=None):
  56. '''
  57. 将PyQuery 请求写成方法
  58. '''
  59. d = pq(url=url, headers={
  60. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'})
  61. return d
  62.  
  63. def downloadVideo(self, url, file_name=''):
  64. '''
  65. 下载视频
  66. :param url: 下载url路径
  67. :return: 文件
  68. '''
  69. with closing(requests.get(url, stream=True)) as response:
  70. chunk_size = 1024
  71. content_size = int(response.headers['content-length'])
  72. file_D='./Video/' + file_name + '.mp4'
  73. if(os.path.exists(file_D) and os.path.getsize(file_D)==content_size):
  74. print('跳过'+file_name)
  75. else:
  76. progress = ProgressBar(file_name, total=content_size, unit="KB", chunk_size=chunk_size, run_status="正在下载",fin_status="下载完成")
  77. with open(file_D, "wb") as file:
  78. for data in response.iter_content(chunk_size=chunk_size):
  79. file.write(data)
  80. progress.refresh(count=len(data))
  81.  
  82. '''
  83. 下载进度
  84. '''
  85. class ProgressBar(object):
  86. def __init__(self, title, count=0.0, run_status=None, fin_status=None, total=100.0, unit='', sep='/',
  87. chunk_size=1.0):
  88. super(ProgressBar, self).__init__()
  89. self.info = "[%s] %s %.2f %s %s %.2f %s"
  90. self.title = title
  91. self.total = total
  92. self.count = count
  93. self.chunk_size = chunk_size
  94. self.status = run_status or ""
  95. self.fin_status = fin_status or " " * len(self.statue)
  96. self.unit = unit
  97. self.seq = sep
  98.  
  99. def __get_info(self):
  100. # 【名称】状态 进度 单位 分割线 总数 单位
  101. _info = self.info % (
  102. self.title, self.status, self.count / self.chunk_size, self.unit, self.seq, self.total / self.chunk_size,
  103. self.unit)
  104. return _info
  105.  
  106. def refresh(self, count=1, status=None):
  107. self.count += count
  108. # if status is not None:
  109. self.status = status or self.status
  110. end_str = "\r"
  111. if self.count >= self.total:
  112. end_str = '\n'
  113. self.status = status or self.fin_status
  114. print(self.__get_info(), end=end_str)
  115.  
  116. if __name__ == '__main__':
  117. C = SaveVideo()
  118. C.getLesson()
  119. sys.exit()

通过pyinstaller打包

  1. import sys
  2.  
  3. if __name__ == '__main__':
  4. from PyInstaller import __main__
  5. params = ['-F','-c','--noupx', '--icon=favicon.ico', 'save.py']
  6. __main__.run(params)

查看:

4:分享课程视频

已经将视频打包分享到云盘中,有兴趣的可以在这   下载

Python 下载网络mp4视频资源的更多相关文章

  1. python下载网络文件

    python下载网络文件 制作人:全心全意 下载图片 #!/usr/bin/python #-*- coding: utf-8 -*- import requests url = "http ...

  2. 快速生成网络mp4视频缩略图技术

    背景 由于网络原因,在下载视频之前我们往往会希望能够先生成一些视频的缩略图,大致浏览视频内容,再确定是否应花时间下载.如何能够快速得到视频多个帧的缩略图的同时尽量少的下载视频的内容,是一个值得研究的问 ...

  3. 手把手教你用 Python 下载手机小视频

    今天为大家介绍使用 mitmproxy 这个抓包工具如何监控手机上网,并且通过抓包,把我们想要的数据下载下来. 启动 mitmproxy 首先我们通过执行命令 mitmweb 启动mitmproxy, ...

  4. python爬取快手视频 多线程下载

    就是为了兴趣才搞的这个,ok 废话不多说 直接开始. 环境: python 2.7 + win10 工具:fiddler postman 安卓模拟器 首先,打开fiddler,fiddler作为htt ...

  5. Python 爬虫实例(13) 下载 m3u8 格式视频

    Python  requests  下载  m3u8 格式    视频 最近爬取一个视频网站,遇到  m3u8 格式的视频需要下载. 抓包分析,视频文件是多个  ts 文件,什么是 ts文件,请去百度 ...

  6. You-Get 一键下载全网视频资源

      下载视频 无论是单纯的下载视频收藏,还是以便离线收看,都离不开“下载”,好的工具让你把注意力更好的放在视频的本身,而不用考虑要如何下载视频.下载视频从来不乏方法,之前也介绍了下载 Youtube ...

  7. 不用 qlv 格式转换成 mp4 - 优雅的下载腾讯视频(mp4 格式)

    不用 qlv 格式转换成 mp4 - 优雅的下载腾讯视频(mp4 格式) 问题描述: 朋友说离线腾讯视频是 qlv 格式的,只能使用腾讯视频软件打开.让我帮忙想想办法,能不能将 qlv 格式转换成 m ...

  8. 使用原生node.js搭建HTTP服务器,支持MP4视频、图片传输,支持下载rar文件

    前言 如何安装node.js,如何搭建一个简易的http服务器我这里就不再赘述了,不懂的同学可以先去学习一下.当然了,我写的也就属于简易版的增强版,大家有什么高见的欢迎提出,然后进入正题. 目录结构 ...

  9. [Python] 使用Python 3 下载麦子学院视频

    本文基于Python 3,下载麦子学院的视频课程. 本项目只是针对某个具体课程的链接,去寻找该课程所有课时的视频链接并进行下载. 整个项目是非常简单的. 主要涉及的Python: 网络相关:reque ...

随机推荐

  1. 【原】小玩node+express爬虫-2

    上周写了一个node+experss的爬虫小入门.今天继续来学习一下,写一个爬虫2.0版本. 这次我们不再爬博客园了,咋玩点新的,爬爬电影天堂.因为每个周末都会在电影天堂下载一部电影来看看. talk ...

  2. .net Socket 通信简单实例(初级入门)

    c/s控制台应用程序,Server.Client分别在两个项目中 服务端 using System; using System.Collections.Generic; using System.Li ...

  3. 分享公司Basecode的用法

    主题 公司在basecode的用法上是比较有新意的,所以准备记录分享下公司的用法. 说明 basecode公司的一个主要用途就是用于一些基础的代码表,参数表的前台操作.这些表有很多,用spring d ...

  4. iPhone屏幕尺寸/launch尺寸/icon尺寸

    屏幕尺寸 6p/6sp     414 X 736 6/6s         375 X 667 5/5s         320 X 568  4/4s         320 X 480   la ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. python之numpy

    一.矩阵的拼接合并 列拼接:np.column_stack() >>> import numpy as np >>> a = np.arange(9).reshap ...

  7. VirtualBox COM对象获取失败

    问题描述: Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works. ...

  8. MATLAB-RSP 随笔

    1.Getting Started with Signal Analyzer App 161216 (1) 在命令行中输入:signalAnalyzer. (2)在工作空间中选择要分析的信号

  9. mysql怎么查询一条记录的前一条记录和后一条记录

    上一条:select * from 表 where 数据id<@当前显示数据id order by 数据_id asc) limit 1下一条:select * from 表 where 数据i ...

  10. ASP.NET中Ajax的用法

    在ASP.NET中应用Ajax的格式如下: 前台代码(用JQuery库) $.ajax({ type: "POST", async: true, url: "../Aja ...