整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML、CSS 和 JavaScript等前端开发技术,必备入门级学习书单

到前端技术,我们通常都会说到"三大块":HTML、CSS、JavaScript,前端最核心的三项技术。

从逻辑上讲,一个网页可以视为由这三项技术实现的三层架构有机结合体。


· 结构层:表述一个页面中有哪些信息,以及信息之间的关系,由HTML实现。

· 表现层:决定了页面中的信息会以怎样的外观呈现出来,由CSS实现。

· 行为层:控制了页面如何与用户进行交互,由JS实现。


除了基本的"三大块"之外,作为前端开发工程师,还需要掌握以下知识点:

· HTTP相关:由于前端资源都是浏览器通过网络下载的,所以有必要了解相关的网络协议。

· 前端性能优化:让网页更快,减少用户的等待,是前端工程师面临的重要课题,需要掌握前端性能优化相关的工具和方法。

· 前端框架:Web业务日趋复杂,对前端开发提出更高要求。学会使用框架开发,很好地解决了jQuery 称霸时代开发周期太长,复用性低等问题,大大提升了效率。

· Node相关:在Node.js之前,没有任何一种脚本语言能贯穿前后端平台——Node.js可以用JS写后台,这对于熟悉JS的前端人员而言会更容易掌握,并且用Node.js可以快速搭建本地服务器。这是很多前端开发者青睐这项技术的原因。

以下,人邮君就围绕前端开发所需技能列出一份荐书清单,并按照豆瓣评分和读者评价给出了推荐指数,请签收!


超文本标记语言(Hyper Text Markup Language,HTML),用于描述超文本中内容的显示方式,如文字以什么颜色、大小来显示等。HTML从1.0到5.0经历了巨大的变化,已经成为了一种非常成熟的标记语言。

入门

《HTML5权威指南》

推荐指数:☆☆☆☆


作者:[美]Adam Freeman 译者:谢廷晟 牛化成 刘美英

本书是系统学习网页设计的参考图书,全书分为五部分:

· 介绍学习需要的预备知识和HTML、CSS和JavaScript的进展;

· 讨论HTML元素,并详细说明了HTML5中新增和修改的元素;

· 阐述CSS,涵盖了所有控制内容样式的CSS选择器和属性,并辅以大量代码示例和图示;

· 介绍DOM,剖析如何用JavaScript操纵HTML内容;

· 讲解Ajax、多媒体和canvas元素等HTML5特性。

本书面向初学者和中等水平Web开发人员,是牢固掌握HTML5、CSS3和JavaScript的必读之作。


进阶

《HTML5程序设计(第2版)》

推荐指数:☆☆☆


作者:[荷]Peter Lubbers [美]Brian Albers [美]Frank Salim 译者:柳靖 李杰 刘淼

本书主要内容包括:

· HTML5历史背景、新的语义标签及与以往HTML版本相比的根本变化;

· HTML5设计原理;

· SVG和拖放API相关内容;

· 逐一讨论HTML5的Canvas、Geolocation、Communication、WebSocket、Forms、WebWorkers、Storage等API的使用;

· 探索了离线Web应用并展望了HTML5未来的发展前景。

本书面向有一定经验的Web应用开发人员,对HTML5及未来Web应用技术发展有浓厚兴趣的读者也可以学习参考。


级联样式表(Cascading Style Sheet)简称"CSS",通常又称为"风格样式表(Style Sheet)",是用来控制网页外观的一门技术。各种物联网设备,不论屏幕尺寸大小,只要有浏览器就要用到CSS。

入门

《HTML5与CSS3基础教程(第8版)》

推荐指数:☆☆☆☆


作者:[美]Elizabeth Castro [美]Bruce Hyslop 译者:望以文

本书是讲解HTML和CSS入门知识的经典畅销书,全面系统地阐述了HTML5和CSS3基础知识以及实际运用技术,通过大量实例深入浅出地分析了网页制作的方方面面。主要内容有:

· 介绍文本、图像、链接、列表、表格、表单等网页元素;

· 介绍如何为网页设计布局、添加动态效果等;

· 调试和发布;

· 书中的完整代码示例,以及更多实例及进阶参考资料(配套网站)。

通过学习本书,零起点读者即可创建网站,而中水平的开发人员也可以快速了解HTML5新元素、CSS3的奇幻效果、响应式Web设计以及各种最佳实践。


进阶

《CSS揭秘》

推荐指数:☆☆☆☆☆


作者:[希]LEA VEROU 译者:CSS魔法

· 本书是一本注重实践的教程,作者为我们揭示了47个鲜为人知的CSS技巧;

· 主要内容包括背景与边框、形状、视觉效果、字体排印、用户体验、结构与布局、过渡与动画等;

· 本书将带领读者循序渐进地探寻更优雅的解决方案,攻克每天都会遇到的各种网页样式难题。

《CSS揭秘》是前端工程师、网页开发人员的进阶必备书籍。


《CSS世界》

推荐指数:☆☆☆☆


作者:张鑫旭

本书主要内容包括:

· 结构、内容、美化装饰等方面大量的CSS知识点;

· 通过大量的实战案例,详尽解析CSS的相关知识与常见问题;

· 专门的配套网站进行实例展示、问题答疑。

作为一本CSS深入学习的书,书中介绍大量许多前端开发人员都不知道的CSS知识点。通过阅读本书,读者会对CSS世界的深度和广度有一个全新的认识。


《CSS权威指南(第四版)(上下册)》

推荐指数:☆☆☆☆


作者:[美]Eric A. Meyer [美]Estelle Weyl 译者:安道

· 本书全面阐述了 CSS 的实现方式,深入分析了最新的 CSS 规范;

· 展示了如何通过布局、过渡和动画、边框、背景、文本属性,以及许多其他工具和技术来改善用户体验、加快开发速度、避免潜在的错误;

· 如果你是网页设计师或应用开发者,对复杂的页面样式、改进可访问性以及节省时间和精力感兴趣,那你决不能错过这本书。


JavaScript是一种解释型的、基于对象的脚本语言,它能够将网页中的文本、图形、声音和动画等各种媒体形式捆绑在一起,形成一个紧密结合的信息源。无论是桌面开发,还是移动应用,JavaScript都是必须掌握的技术。

入门

《JavaScript高级程序设计(第3版)》

推荐指数:☆☆☆☆☆


作者:[美]Nicholas C.Zakas 译者:李松峰 曹力

本书承继了之前版本全面深入、贴近实战的特点,讲解了JavaScript语言的核心,展示了现有规范及实现为开发Web应用提供的各种支持和特性。本书主要内容包括:

· 解读JavaScript实现各个组成部分;

· 阐述JavaScript面向对象编程;

· 剖析DOM、BOM及浏览器事件模型;

· Web应用基本数据格式JSON、XML及其存取;

· Ajax、Comet服务器端通信和基于File API的拖放式文件上传;

· ECMAScript 5定义的新核心语言特性;

· HTML5涵盖的表单、媒体、Canvas(包括WebGL);

· Selectors、Web、Workers、地理定位及跨文档传递消息等新API;

· 离线应用及客户端存储(包括IndexedDB);

· 维护、性能、部署相关的开发实践;

· 新兴API及ECMAScript Harmony展望。

作为JavaScript技术经典名著,《JavaScript高级程序设计(第3版)》可以说是JavaScript最权威的入门书籍了


《JavaScript DOM编程艺术(第2版)》

推荐指数:☆☆☆☆


作者:[英]Jeremy Keith [加]Jeffrey Sambells 译者:杨涛 王建桥 杨晓云等

本书是超级畅销书的升级版,由倡导Web标准的领军人物执笔,揭示了前端开发的真谛,是学习JavaScript和DOM开发的必读之作。本书主要内容包括:

· JavaScript和DOM的基本知识;

· 通过几个实例演示了专业水准的网页开发技术;

· 透彻阐述了平稳退化等一批至关重要的JavaScript编程原则和实践;

· 全面探讨了HTML5以及jQuery等JavaScript库。

通过阅读本书,读者将看到JavaScript、HTML5和CSS如何协作来创建易用的、与标准兼容的Web设计,以及掌握使用JavaScript和DOM通过客户端动态效果和用户控制的动画来加强Web页面的必备技术;同时,还将对如何利用库提高开发效率有全面深入的理解。


《你不知道的JavaScript》

推荐指数:☆☆☆☆☆


作者:[美]Kyle Simpson 译者:赵望野 梁杰

本书深入理解语言内部的机制,全面介绍了JavaScript中常被人误解和忽视的重要知识点。

· 《你不知道的JavaScript(上卷)》介绍了该系列的两个主题——"作用域和闭包"以及"this和对象原型"。掌握了这些知识之后,无论什么技术、框架和流行词语,你都能轻松理解。本书讲解通透深入,是入门必备书籍

· 《你不知道的JavaScript(中卷)》主要介绍了类型、语法、异步和性能。

· 《你不知道的JavaScript(下卷)》主要介绍了入门知识和对ES6及未来发展趋势的展望。

本书既适合JavaScript语言初学者阅读,又适合经验丰富的JavaScript开发人员深入学习。


《Head First JavaScript程序设计》

推荐指数:☆☆☆☆


作者:[美]Eric T. Freeman [美]Elisabeth Robson 译者:袁国忠

· 本书语言和版式活泼,内容讲解深入浅出,是难得的JavaScript入门书;

· 本书内容涵盖JavaScript的基本知识以及对象、函数和浏览器文档对象模型等高阶主题;

· 书中配备了大量有趣的实例、图示和练习,让读者轻轻松松掌握JavaScript。

本书的读者对象为JavaScript入门读者以及网页设计入门者。

`````````

进阶

《JavaScript忍者秘籍 第2版》

推荐指数:☆☆☆☆☆


作者:[美]John Resig [美]Bear Bibeault [美]Josip Maras 译者:一心一译前端小组

本书共分4个部分,从不同层次讲述了逐步成为JavaScript高手所需的知识:

· 本书从JavaScript语言及重要的特性谈起,由浅入深地探讨了函数、作用域、闭包、生成器函数、对象、数组、模块化、JavaScript与Web页面的交互以及事件等主题;

· 引导读者更加深入地了解JavaScript的方方面面,充分展示了JavaScript语言的各种特性;

· 本书结合ECMAScript 6和7的相关概念,涵盖了流行的JavaScript框架所使用的技术。

本书适合具备一定JavaScript基础知识的读者阅读,也适合从事程序设计工作并想要深入探索JavaScript语言的读者阅读。


《JavaScript设计模式》

推荐指数:☆☆☆☆


作者:张容铭

本书共分六篇四十章:

· 讨论了几种函数的编写方式,体会JavaScript在编程中的灵活性;

· 讲解了面向对象编程的知识,其中讨论了类的创建、数据的封装以及类之间的继承;

· 探讨了各种模式的技术,如简单工厂模式,包括工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式,以及外观模式,包括适配器模式。

· 讲解了几种适配器、代理模式、装饰者模式和MVC模式,讨论了如何实现对数据、视图、控制器的分离。

· 在讲解MVP模式时,讨论了如何解决数据与视图之间的耦合,并实现了一个模板生成器;

· 讲解MVVM模式时,讨论了双向绑定对MVC的模式演化。

本书几乎包含了关于JavaScript设计模式的全部知识,是进行JavaScript高效编程必备的学习手册。


《JavaScript面向对象精要》

推荐指数:☆☆☆☆☆


作者:[美]Nicholas C.Zakas 译者:胡世杰

全书共6章,内容简洁而精妙,关注面向对象的原理和ES5对象新特性,帮助那些已经熟知面向对象编程的读者掌握这些概念是如何在JavaScript中工作的。

· 本书深入探讨了原始类型和引用类型、函数、对象、构造函数和原型对象、继承和对象模式等主题和特性;

· 你将学到JavaScript独特的面向对象的编程方式;

· 你将学到抛弃类的概念和基于类的继承,学习基于原型的继承和构造函数;

· 你将学会如何创建对象、定义自己的类型、使用继承以及其他各种操作来充分使用对象。

总而言之,你将学到JavaScript语言并进行专业编程所需熟知的一切。本书适合熟悉面向对象编程的概念并希望将其应用于JavaScript的开发者阅读,也适合JavaScript新手学习参考。


《锋利的jQuery(第2版)》

推荐指数:☆☆☆☆


作者:单东林 张晓菲 魏然

· 本书介绍了jQuery的各种函数和方法调用;

· 读者可以系统地掌握jQuery的选择器、DOM操作、事件和动画、AJAX应用、插件、jQuery Mobile、jQuery各个版本变化、jQuery性能优化和技巧等知识点,并结合每个章节后面的案例演示进行练习;

· 本书的第8章将前7章讲解的知识点和效果进行了整合,打造出一个非常有个性的网站,并从案例研究、网站材料、网站结构、网站样式和网站脚本等方面指导读者参与到项目建设中来。

《锋利的jQuery(第2版)》适合所有对jQuery技术感兴趣的Web设计者和前端开发人员阅读和参考。


Node.js是建立在Chrome浏览器的JavaScript运行时基础上,用于快速构建可扩展的网络应用的平台。Node旨在帮助开发者编写异步的、事件驱动的应用。在Node中,每一个请求都是异步的,并且几乎所有的I/O都是非阻塞的。因此,Node应用非常高效率,能够处理的"并发"连接的数量也很庞大。

入门

《Node.js实战(第2版)》

推荐指数:☆☆☆


作者:[英]Alex Young [美] Bradley Meck [美] Mike Cantelon [美] Tim Oxley [美] Marc Harter [美] T.J.Holowaychuk [美] Nathan Rajlich 译者:吴海星

· Node.js核心框架贡献者力作 ;

· 展示Node核心技巧 ;

· 涵盖前端构建系统、Web框架选择、数据库交互和Web程序测试与部署等全栈开发所需技术。

本书是Node.js的实战教程,涵盖了为开发产品级Node应用程序所需要的一切特性、技巧以及相关理念。从搭建Node开发环境,到一些简单的演示程序,到开发复杂应用程序所必不可少的异步编程,第2版介绍了全栈开发者所需的全部技术,可作为入门书籍。

进阶

《深入浅出 Node.js》

推荐指数:☆☆☆☆☆


作者:朴灵

《深入浅出Node.js》从不同的视角介绍了 Node 内在的特点和结构。由首章Node介绍为索引,涉及Node的各个方面,主要内容包括:

· 模块机制的揭示;

· 异步I/O实现原理的展现;

· 异步编程的探讨;

· 内存控制的介绍;

· 二进制数据Buffer的细节;

· Node中的网络编程基础;

· Node中的Web开发;

· 进程间的消息传递;

· Node测试以及通过Node构建产品需要的注意事项。

附录介绍了Node的安装、调试、编码规范和NPM仓库等事宜。本书适合想深入了解 Node的人员阅读,是进阶必备书籍。


HTTP & TCP/IP

《HTTP权威指南》

推荐指数:☆☆☆☆☆


作者:[美]David Gourley [美]Brian Totty [美]Marjorie Sayer [美]Sailu Reddy [美]Aushu Aggarwal 译者:陈涓 赵振平

本书由具有多年实践经验的专家编写,通过简洁语言和大量翔实的细节图解帮助读者形象地理解Web幕后所发生的事情,详细说明了Web上每条请求的实际运行情况,主要内容包括:

· HTTP方法、首部以及状态码;

· 优化代理和缓存的方法;

· 设计Web机器人和爬虫的策略;

· Cookies、认证以及安全HTTP;

· 国际化及内容协商;

· 重定向及负载平衡策略。

本书深入说明了Web的工作原理,内容全面,讲解细致,是HTTP协议及相关Web技术方面的著作。


《图解HTTP》

推荐指数:☆☆☆☆


作者:[日]上野 宣 译者:于均良

《图解HTTP》对HTTP协议进行了全面系统的介绍,可以说是一本讲解HTTP协议的神书,简单有趣,图文并茂,生动形象,适合入门,主要内容包括:

· HTTP协议的发展历史;

· HTTP协议的结构剖析;

· 常见通信场景及实战案例;

· Web安全、新技术动向等。

读者可通过本书快速了解并掌握HTTP协议的基础知识。


《图解TCP/IP(第5版)》

推荐指数:☆☆☆


作者:[日]竹下隆史 [日]村山公保 [日]荒井透 [日]苅田幸雄 译者:乌尼日其其格

· 本书是一本图文并茂的网络管理技术书籍,旨在让广大读者理解TCP/IP的基本知识、掌握TCP/IP的基本技能;

· 书中讲解了网络基础知识、TCP/IP基础知识、数据链路、IP协议、IP协议相关技术、TCP与UDP、路由协议、应用协议、网络安全等内容;

· 引导读者了解和掌握TCP/IP,营造一个安全的、使用放心的网络环境。


性能优化

《Web性能权威指南》

推荐指数:☆☆☆☆


作者:[加]Ilya Grigorik 译者:李松峰

本书由谷歌公司高性能团队核心成员创作,堪称实战经验与规范解读结合的产物,获得IETF下一代HTTP协议工作组主席力荐。本书目标是涵盖Web技术体系中应该掌握的所有网络及性能优化知识。本书主要内容有:

· 以性能优化为主线,从TCP、UDP和TLS协议讲起;

· 解释了如何针对这几种协议和基础设施来优化应用;

· 深入探讨了无线和移动网络的工作机制;

· 揭示了HTTP协议的底层细节;

· 同时详细介绍了HTTP 2.0、 XHR、SSE、WebSocket、WebRTC和DataChannel等现代浏览器新增的具有革命性的新能力。

本书适合所有Web应用及站点开发人员阅读,包括但不限于前端、后端、运维、大数据分析、UI/UX、存储、视频、实时消息,以及性能工程师。


前端框架

当前,三大主流前端框架分别是React、Vue、Angular

React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架,另辟蹊径提出了以组件化的形式重新构建页面内容,将页面的内容按特征分块,然后将特定块中的HTML、CSS、JS封装在一起,最后用组件来构建页面内容。

《深入React技术栈》

推荐指数:☆☆☆☆


作者:陈屹

本书从几个维度去介绍 React:

· 一是作为 View 库,它怎么实现组件化,以及它背后的实现原理;

· 二是扩展到 Flux 应用架构及重要的衍生品 Redux,它们怎么与 React 结合做应用开发;

· 三是对 React 与 server 的碰撞产生的一些思考;

· 四是讲述它在可视化方面的优势与劣势。

此外,本书非常重视实战,每一节都有实际的例子,细节丰富,内容翔实,由浅入深,无论你是 React 初学者,还是进阶人士,本书都值得一读!本书适合有一定经验的前端开发人员阅读。


Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue.js 自身不是一个全能框架——它只聚焦于视图层,因此它非常容易学习,并很容易与其它库或已有项目整合。

《深入浅出Vue.js》

推荐指数:☆☆☆☆


作者:刘博文

本书从源码层面分析了Vue.js,主要内容有 :

· 简要介绍Vue.js;

· 讲解内部核心技术"变化侦测",带领大家从0到1实现一个简单的"变化侦测"系统;

· 介绍虚拟DOM技术,包括虚拟DOM的原理及其patching算法;

· 讨论模板编译技术,包括模板解析器的实现原理、优化器的原理以及代码生成器的原理;

· 介绍其整体架构以及提供给我们使用的各种API的内部原理,同时还介绍了生命周期、错误处理、指令系统与模板过滤器等功能的原理。

360奇舞团团长月影和《JavaScript高级程序设计》译者李松峰作序推荐,适合前端开发人员阅读。


Angular是一个用来构建大型应用,高性能的Web应用程序的框架;是一个完整的、从 UI、路由、Http、Socket到依赖注入、编译、优化、测试的框架。Angular上手起来有一定难度,但其工程属性极强,非常适合多团队的大型项目,一旦学会,优势很大。

《Angular权威教程》

推荐指数:☆☆☆☆


作者:[美]Ari Lerner [巴西]Felipe Coury [美]Nate Murray [巴西]Carlos Taborda 译者:Nice Angular社区

· 本书堪称Angular领域的里程碑式著作,几乎涵盖了关于Angular的所有内容;

· 对于没有经验的人,本书平实、通俗的讲解,递进、严密的组织,可以让人毫无压力地登堂入室,迅速领悟新一代Web应用开发的精髓;

· 如果你有相关经验,那本书对Angular概念和技术细节的全面剖析,以及引人入胜、切中肯綮的讲解,将帮助你彻底掌握这个框架,在自己职业技术修炼之路上更进一步。

. MIDI 简介

MIDI 协议即数字音乐接口(Musical Instrument Digital Interface),是电子乐器、合成器等演奏设备之间的一种即时通信协议,用于硬件之间的实时演奏数据传递。MIDI 协议诞生之初希望解决的事情是通过统一通信协议让不同乐器制造商的设备可以互相兼容,比如把 Roland 键盘接入 Yamaha 合成器。MIDI 协议的编码经过拓展后也可以作为一种记录音乐信息的文件格式,被称为“标准 MIDI 文件格式”。

在音乐技术研发中除了需要与音频打交道之外,许多场景中还需要直接处理音符信息。如果说 wav 与 mp3 记录的是音乐的物理现象,那么 MIDI 协议与 MIDI 文件则记录的是音乐这门语言的“文字”。本文的目的是让开发中涉及到音乐“本体”的同学可以了解这一最通用的演奏信息交互和文件存储格式的编码规则。同时通过对 MIDI 事件流等概念的认识,能在开发中更好地抽象自己的业务逻辑。

1.1 MIDI 数据流 & 编码

和 HTTP 这类协议不同,MIDI 作为传输协议时所有传递的信息都需要被实时响应,比如一个触键信息、一个效果器参数的改变都需要立刻被执行,所以其采用数据流的方式进行数据传输。MIDI 定义了一个 8 位的二进制数据流,许多时候我们可以使用 ASCII 码来将其表示为 16 进制的字符用于传输和保存。

对于 MIDI 标准文件格式来说,其存储的内容也是 MIDI 产生的事件流。一段典型的 MIDI 文件长这样:

4D 54 68 64 00 00 00 06 00 01 00 03 01 E0 4D 54
72 6B 00 00 00 1A 00 FF 03 03 31 32 33 00 FF 51
03 08 7A 23 00 FF 58 04 04 02 18 08 00 FF 2F 00
...

上面这个例子可能会造成一些困惑,因为 MIDI 文件确实对人类阅读不太友好,但其编码规则实际上是较易掌握的,下面我们就来逐步认识 MIDI 的编码规则。

注:在本文中,一个字节的最低有效位为第 0 位,最高有效位是第 7 位。比如在 X000 000Y 中,X 为第 7 位,Y 为第 0 位。

1.2 MIDI 消息

MIDI 最核心的功能是用于传输实时的音乐演奏信息,这些信息本质上是一条条包含了音高、力度、效果器参数等信息的指令,我们将这些指令称之为 MIDI 消息(MIDI message)。一条 MIDI 消息通常由数个字节组成,其中第一个字节被称为 STATUS byte,其后面有跟有数个 DATA bytes。STATUS byte 第七位为 1,而 DATA byte 第七位为 0。

开头的 STATUS byte 有两个作用:一个作用是表示系统或者某个信道状态的改变,其二个作用是确定当前 MIDI Message 的类型,MIDI 类型会确定后面 DATA byte 的数量和意义。这样说比较空洞,下面我们举一个例子:

Status byte : 1100 CCCC
Data byte 1 : 0XXX XXXX
Status byte : 1001 CCCC
Data byte 1 : 0PPP PPPP
Data byte 2 : 0VVV VVVV

第一个 STATUS byte 告诉我们这是一个进行乐器选择的 MIDI Message(1100 为乐器选择指令,CCCC 是信道编号)。乐器选择的 MIDI Message 只有一条 DATA byte,而这条 DATA Byte 的数据表示选择的乐器编号。第二条 1001 开头的 STATUS byte 则告诉我们这是一条 Note On 类型 MIDI message,这个类型按照约定有两个 DATA byte。

除了向整个系统发送的 MIDI 消息, STATUS byte 通常包含了信道编号(即例子中的 CCCC),16 个信道分别从 0000 到 1111。而向整个系统发送的 MIDI 信息则以 1111 开头,原来的信道编号变成了指令编号(比如播放指令:1111 1010,终止指令:1111 1100)。

需要注意的是,许多时候我们会连续发送许多相同状态的 MIDI 消息,这个时候可以省略 STATUS byte,合成器会沿用最后一个接收的 STATUS byte,被合成器记录的状态称之为 MIDI RUNNING STATUS。

总结一下:

一条 MIDI message 由 STATUS byte 和 Data byte 构成。

STATUS byte 以 1 开头,DATA byte 以 0 开头。

STATUS byte 确定消息的类型。后面的 DATA 字节数取决于消息的类型。

STATUS byte 通常包含信道编号,除了面向系统发送的指令。

连续相同的 STATUS byte 可以省略。

2. 常用 MIDI Message

MIDI Message 不需要全部掌握,需要的时候可以直接到 MIDI 标准中查询,日常开发中只需要了解常用的几种 MIDI Message 即可。下面笔者介绍最常用的几种 MIDI Message。

2.1 NOTE ON & NOTE OFF - 音符的触发与终止

NOTE ON 和 NOTE OFF 是最主要的两个 MIDI Message。当演奏者敲击音乐键盘的琴键时发送 NOTE ON 消息,它包含了音高以及“力度”的参数。当合成器收到此消息时,它会开始以相应的音高和“力度”播放该音符。当收到 NOTE OFF 消息时,合成器会终止该音符。

每个 NOTE ON 消息都需要相应的 NOTE OFF 消息,否则该音符将一直处于播放状态。但打击乐器可以只发送 NOTE ON,因为打击乐音符会自动停止。但最好养成始终发送 NOTE OFF 的习惯,因为不同合成器对这一特性的实现可能不一样。

下面我们举例说明 NOTE ON:

Status byte : 1001 CCCC
Data byte 1 : 0PPP PPPP
Data byte 2 : 0VVV VVVV

在这个例子中,1001 可以理解为 NOTE ON 事件的编码,CCCC 是信道编号。

PPP PPPP 表示音高值,在 General MIDI 协议中(后文会提到),通常使用 69 表示标准音 A4(440 Hz),音高值增减一,就增减一个半音。比如 60 表示 C4(中央 C), 61 表示 C#4。同样,升高或者降低八度只需要在当前音高上增减 12 即可。

VVV VVVV 表示速率(velocity),这个速率可以理解为敲击键盘的速度,或者管乐器气流的速度。在最基础的合成器中,速率仅用于确定弹奏音符的力度,唯一的效果是音符音量变大或变小。总体来说,下面这张表可以作为速率和乐谱中的力度记号的对应关系参考:

但在在一些复杂的仿真建模合成器中,速率也会影响音色。我们以 Galaxy Steinway 采样器为例:

图片来源:https://zhuanlan.zhihu.com/p/19964066

左侧是小力度敲击的频域图,右侧是大力度敲击的频域图。我们可以看到大力度敲击不仅产生了更多的泛音,也在低频区产生了一些噪音(木材被撞击的声音)。

注:关于 velocity 可以参考附录的介绍。

NOTE OFF 消息和 NOTE ON 消息基本一样:

Status byte : 1000 CCCC
Data byte 1 : 0PPP PPPP
Data byte 2 : 0VVV VVVV

其中 CCCC 和 PPPPPPP 含义同上。VVVVVVV 是释放速率,可以看作是按键抬起的速度,这个值很少使用,通常将其设置为零。另外,在实践中经常使用速率为 0 的 NOTE ON 消息取代 NOTE OFF 消息。

需要额外说明的是 MIDI 协议还提供了一组 All Notes Off 消息,当某个信道接收到 All Note Off 消息之后会关闭所有还在发音的振荡器,通常来说 All Notes Off 消息用于在演奏、播放结束后用于清理状态,这里不多赘述。

2.2 乐器选择

乐器选择消息的格式如下:

Status byte : 1100 CCCC
Data byte 1 : 0XXX XXXX

其中唯一的一个 DATA byte 表示乐器编号,支持 128 个不同的乐器。由于不同的软件上存在的乐器音源并不一致,为了让 A 设备上创建的标准 MIDI 文件在 B 设备上播放时听起来相似,乐器厂商边采用 General MIDI 协议来编排音源。Gerneral MIDI 通常简写为 GM ,它提供了一个标准化的音库,将 128 个乐器排列成 16 个系列,每个系列有 8 个同类型的乐器,并为每个乐器分配一个特定的程序编号。GM 乐器表可以参考:

http://www.harfesoft.de/aixphysik/sound/midi/pages/genmidi.html

在 GM 标准下,信道 10 是保留给打击乐器的(实际上合成器可以在任何信道上使用鼓),在这个信道上乐器编码遵循通用 MIDI 鼓乐器列表(General MIDI drum instruments list),具体可以参考:

https://en.wikipedia.org/wiki/General_MIDI#Percussion

由于鼓是总体上是噪音乐器,所以之前的音高参数则被映射为不同的鼓音效。

注:噪音乐器指没有明确音高的乐器,有明确音高的乐器称为乐音乐器。

2.3 控制器消息

MIDI 设备通常会提供一些控制器用于改变合成器的某个参数,比如混响、增益等。MIDI 协议可以使用控制器消息操作 128 个不同的控制器,控制器消息结构如下:

Status byte : 1011 CCCC
Data byte 1 : 0NNN NNNN
Data byte 2 : 0VVV VVVV

其中 NNN NNNN 是控制器的编号,VVV VVVV 则是控制器的值。

控制器消息一方面可以用于改变合成器的某些参数,比如我们可以用以下指令将某个信道的力度值设置为 100:

Status byte : 1011 CCCC
Data byte 1 : 0000 0111
Data byte 2 : 0110 0100

另一方面,控制器编码可以通过“组合”的方式实现一些更复杂的指令。如前文所述,选择乐器可以通过 1000 开头的 STATUS byte 实现,这个指令可以选择 128 种乐器。对于同一个乐器来说可以应用不同的音色库,比如我可以在钢琴上使用雅马哈的采样、施坦威的采样或者是珠江的采样,由于乐器厂商认为 128 这个数量对于音色库太小了,所以采用的 MSB + LSB 的方式表示音色库,例子如下:

Status byte : 1011 CCCC
Data byte 1 : 0000 0000   // 0 = Sound bank selection (MSB)
Data byte 2 : 0000 0101

Status byte : 1011 CCCC
Data byte 1 : 0010 0000   // 32 = Sound bank selection (LSB)
Data byte 2 : 0000 0001

Status byte : 1100 0000
Data byte 1 : 0000 0010

这段代码选择了一个编号为 2,并且音色编号为 MSB = 0, LSB = 32 的乐器。由于 MSB 和 LSB 的范围都是 2 ^ 7 = 128,所以理论上可以选择的音色为 (2 ^ 7) ^ 2 = 16384

在 MIDI 中控制器消息和音源与效果器的参数密切相关,不同编号的控制器有一些约定俗称的含义,在程序中实现控制器时尽量与已有的规范对齐,具体内容可以参考这个表格:MIDI CC List(https://professionalcomposers.com/midi-cc-list/)

注:MSB 指最高有效字节(most significant byte),LSB 指最低有效字节(least significant byte)。一个 14 位的数据 XXX XXXX YYY YYYY 可以用 MSB + LSB 表示为:0XXX XXXX 0YYY YYYY

2.4 弯音消息

弯音消息也用到了我们刚才提到的 MSB + LSB 表示法,其消息结构如下:

Status byte : 1110 CCCC
Data byte 1 : 0LLL LLLL
Data byte 2 : 0MMM MMMM

其中 LLL LLLL 表示 LSB,MMM MMMM 表示 MSB,弯音值 0x2000(即 0b10000000000000)为同音高,0x3FFF(即 0b11111111111111)表示上方大二度,0x0000(即 0b00000000000000)表示下方大二度。在实践中,我们可以通过连续发送递增或者递减的弯音消息来表现滑音。

2.5 系统独占消息

所有系统消息都以 1111 开头,其中有两个特殊的消息。一个是 1111 0000 它表示后面的消息是系统独有的。另外一个 1111 0111 则表示系统独有消息结束,消息结构如下:

11110000
0iiiiiii
0ddddddd
..
..
0ddddddd
11110111

当合成器监听到 1111 0000 时,检查下一个字节 0iii iiiiiii iiii 是一个 7 位的制造商 ID。如果合成器识别出这个代码则会继续监听后面的数据,否则则忽略掉收到的消息,直到结束消息 1111 0111 出现。

3. 宿主的 MIDI API

许多宿主环境都提供了用于编写 MIDI 交互程序的 API,在浏览器上是 Web MIDI API,在 iOS & Mac 上是 Core MIDI,Android 上则有 AMidi。为了方便读者进行实际操作,我们以 Web MIDI API 为例展示如何编写一个最基本的 MIDI 程序:

const button = document.getElementById('console-message')

button.addEventListener('click', () => {
  if (navigator.requestMIDIAccess) {
    navigator.requestMIDIAccess()
      .then(success, failure);
  }
})

function success (midiAccess) {
    const inputs = midiAccess.inputs.values();
    for (let input of inputs) {
        input.value.onmidimessage = onMIDIMessage;
    }
}

function failure () {
    console.error('No access to your midi devices.')
}

function onMIDIMessage (messageEvent) {
  console.log(messageEvent)
}

在这里,我们可以通过 requestMIDIAccess 向用户索要访问 MIDI 设备的权限,用户允许后我们会拿到一个 midiAccess 对象,可以通过这个对象拿到所有的输入和输出设备。我们可以通过设备对象提供的 onmidimessage 回调监听 midi message。

MIDI 消息的编码存储在 messageEvent 的 data 成员中,通过打印出的信息我们可以发现 Web MIDI API 并不会省略 Status Byte,这是为了便于开发者更容易区分指令属于哪个状态,而不必手动保存 MIDI 的运行状态。

如果想要 MIDI 可以发音,我们可以使用 Web Audio API 提供的振荡器:

const button = document.getElementById('play-sound')
const oscillators = {};
let context


button.addEventListener('click', () => {
  context = new AudioContext()

  if (navigator.requestMIDIAccess) {
    navigator.requestMIDIAccess()
      .then(success, failure);
  }
})

function success (midiAccess) {
    const inputs = midiAccess.inputs.values();

    for (let input of inputs) {
        input.onmidimessage = onMIDIMessage;
    }
}

function failure () {
    console.error('No access to your midi devices.')
}

function onMIDIMessage (message) {
    const frequency = midiNoteToFrequency(message.data[1]);

    // midi 键盘的普通按键默认使用通道 0,所以其 note on 事件为 1100 0000
    if (message.data[0] === 144) {
        playNote(frequency);
    }
    
    // note off
    if (message.data[0] === 128) {
        stopNote(frequency);
    }
}

function midiNoteToFrequency (note) {
    return Math.pow(2, ((note - 69) / 12)) * 440;
}

function playNote (frequency) {
    oscillators[frequency] = context.createOscillator();
    oscillators[frequency].frequency.value = frequency;
    oscillators[frequency].connect(context.destination);
    oscillators[frequency].start(context.currentTime);
}

function stopNote (frequency) {
    oscillators[frequency].stop(context.currentTime);
    oscillators[frequency].disconnect();
}

我们可以使用这个小程序来回顾与验证我们之前讲到的 MIDI Message 知识。

这里有一个笔者以前做的视唱练耳小工具,可以使用 MIDI 键盘进行视唱练耳练习:

演示地址:muse-training(https://muse-training-8gwn0lc039762917-1252681582.tcloudbaseapp.com/)

仓库地址:https://github.com/lipd/muse-training

4. 标准 MIDI 文件格式规范

MIDI 协议解决的是音乐设备之间的即时通讯问题,它本质上是一个硬件之间的通信协议。而当我们想把 MIDI 演奏保存在磁盘上则需要用到标准 MIDI 文件格式规范(Standard MIDI-File Format Spec)。和 MIDI 通信协议一样,MIDI 文件也是 8 位字节流,下文将会说明 MIDI 文件一些最基本的格式规范。

4.1 Chunk

Chunk 是构成 MIDI 文件的基本单元。一个 Chunk 由三个部分组成:Chunk 类型 、Chunk 长度以及 Chunk 数据。Chunk 类型是 4 个 ASCII 字符,之后使用 32 位表示 Chunk 数据的长度,最后才是 Chunk 需要存储的数据。

MIDI 中一共有两种 Chunk,分别为 Header Chunk 和 Track Chunk。Header Chunk 标记为 MThd,存储的是整个 MIDI 文件的基本信息,和 PNG 等文件的 Header Chunk 类似。Track Chunk 标记为 MTrk,每个 Track Chunk 都存储了一个 MIDI 事件流,一个事件流可以包含 16 个 MIDI 信道的消息。一个典型 MIDI 文件的结构如下:

MThd <length>
<MThd data>
MTrk <length>
<MTrk data>
MTrk <length>
<MTrk data>

4.2 Header Chunk

MIDI 文件的 Header Chunk 包含的信息非常简单,我们以上面这个文件为例:

4D 54 68 64    // MThd 的 ASCII 码
00 00 00 06    // MThd 的数据长度,MThd Data 固定为 6 字节
---- DATA 部分 ----
00 01          // MIDI 文件格式,有 0、1、2 三种
00 02          // MIDI 文件的包含的音轨数量,即 Track Chunk 数量
00 DC          // MIDI 文件的时间类型

前两条数据已经介绍过,这里不再赘述。我们来解释一下 MIDI 文件格式与 MIDI 时间类型:

MIDI 文件格式(MIDI File Formats)

MIDI 文件格式分为三种,格式 0 的 MIDI 文件只有一个 Header Chunk 和一个 Track Chunk。对于只有一个轨道的程序可以采用这种格式。

格式 1 有一个 Header Chunk ,和多个 Track Chunk 。其中第一条 Track Chunk 是特殊的,负责记录 MIDI 文件的所有 Meta Event(后面会讲到),而从第二条 Track Chunk 开始才会记录 MIDI Event,所以我们上图中的 MIDI 文件实际上只有一条用于演奏的音轨。目前绝大部分的支持多音轨的程序都采用这种格式,笔者也建议读者尽量使用这种格式。

格式 2 的 MIDI 文件也有多个 Track Chunk,但不同的是格式 1 所有 Track Chunk 共用一条时间轴,所有 Track 应当被视作同时播放的。而格式 2 中 Track Chunk 都有自己独立的时间信息,这种格式非常少见,不建议使用。

我们用一张表总结一下:


音轨数量

时间轴

格式 0

1 个

1 条

格式 1

多个

1 条

格式 2

多个

多条

MIDI 时间类型

MIDI 时间类型主要有两种,为了方便介绍读者可以简单将其理解为“按音符分割的”和“按帧分割的”:

“按音符分割的”时间类型 15 位为 0,被称为 TPQN(Ticks Per Quarter-Note),即一个四分音符中包含了多少 Tick。在前文的例子中 00 DC 表示 TPQN 为 220,那么一个八分音符为 110 Ticks,一个二分音符为 440 Ticks。另外 TPQN 也被称为 Pulses Per Quarter-Note (每四分音符的脉冲数),如果你在代码中看到 PPQ、PPQN 这样的简写,你知道他们是一个意思即可。

“按帧分割的”时间类型 15 为 1,这种格式单纯 MIDI 文件中几乎不用而且比较复杂,建议读者跳过。其编码规则简单说就是使用了 SMPTE 时间码的规范。其 14 - 8 位包含了包含 -24、-25、-29 或 -30 四个值之一,对应于四种标准 SMPTE 时间码格式(-29 对应于 30 个丢帧),并表示每秒的帧数。第 7 到 0 位表示帧内分辨率。我们依然用一张表总结一下:


15 位

14-8位

7-0位

按音符

0

四分音符的Tick数

按帧

1

SMPTE格式

每帧Tick数

4.3 Track Chunk

Track Chunk 的主要功能是用于存储实际的演奏数据。它的 Chunk Data 中存储的是一串事件流,被 Track Chunk 记录的事件我们称为 MTrk 事件,其结构如下:

<MTrk event> = <delta time> <event>

在这个结构中,事件可以指代三类事件:midi 事件、系统独有事件、元事件:

<event> = <midi event> | <sysex event> | <meta event>

delta time

MIDI 通信时所有信息都是即时执行,所以 MIDI 消息并没有记录时间,但是 MIDI 文件则需要记录时间在时间轴上的位置。MIDI 文件采用差量时间来记录 MIDI 事件,即 Δt。delta time 表示的是当前事件与上一个时间相差的 Tick 数。如果要表示同时发生的数个任务,则记录一串 delta time 为 0 的事件流即可。比如我们控制器一章中切换乐器的事件流可以表示为:

Delta time  : 0000 0000
Status byte : 1011 CCCC
Data byte 1 : 0000 0000   // 0 = Sound bank selection (MSB)
Data byte 2 : 0000 0101

Delta time  : 0000 0000
Status byte : 1011 CCCC
Data byte 1 : 0010 0000   // 32 = Sound bank selection (LSB)
Data byte 2 : 0000 0001

Delta time  : 0000 0000
Status byte : 1100 0000
Data byte 1 : 0000 0010

sysex event

即系统独占的消息事件,具体可以参考前文中的系统独占消息。

meta event

所有元事件以 1111 1111 开头,这个指令在 MIDI 消息中表示系统复位。这个指令是一个系统实时信息,通常在使用 MIDI 文件的程序并不会用到,所以在这里用于表示元事件。元事件主要用于指定拍号、调号、速度等。

需要注意的是FF 2F 00 是一个特殊的元事件,表示轨道结束。所有 Track Chunk 都以这个元事件结束。下面这张表是标准中已定义的元事件:


意义

FF 00 02

序列号

FF 01 len text

文本事件

FF 02 len text

版权声明

FF 03 len text

轨道名称

FF 04 len text

轨道中使用的乐器类型

FF 05 len text

歌词

FF 06 len text

某个点的名称,比如“第一乐章”

FF 07 len text

Cue Point 某个舞台事件描述

FF 20 01 cc

MIDI 通道前缀

FF 2F 00

End of Track

FF 51 03 tttttt

设置速度

FF 54 05 hr mn se fr ff

SMPTE Offset

FF 58 04 nn dd cc bb

拍号

FF 59 02 sf mi

调号

5. MIDI 协议的缺陷与改良方案

5.1 MIDI 2.0 & MPE

MIDI 通信协议目前看来主要有两个较明显的缺陷。第一个缺陷是许多值可以表示的范围实在有限,比如 note off 的 velocity 就只有 128 个、乐器也只有 128 个、只有 16 个信道。

另一个问题更为麻烦,MIDI 中控制器、和弯音消息只能发送给某个信道,你根本就没法将它和某个音联系在一起。这一局限在以前并没有引起多少问题,因为传统乐器很少碰到按音处理控制器的情况。而弯音用得最频繁的更多是单声部乐器。

但电子音乐界向来不缺乏整活健将,工程师总是会想方设法突破现有限制。最典型的例子就是 seaboard 键盘,这玩意儿可以在每个键上提供弯音能力。你可以从下面这段演奏上感受到这一乐器的神奇魅力:

原视频链接:https://www.youtube.com/watch?v=6SCug5kUsBs

为了解决让控制器消息能按“音”发送,seaboard 的制造商 ROLI 制订了 MIDI Polyphonic Expression(MPE,MIDI 复音表示法)。其原理基本上可以概括为:让每个发声的音符都会在其 Note On 和 Note Off 之间临时分配一个 MIDI 通道。这样便把控制器消息和弯音消息与特定音符建立了联系,并且很好的兼容了 MIDI 协议。

上述问题现在都正在通过新的 MIDI 2.0 得到解决,在 MIDI 2.0 中 volocity 从 0 - 128 扩展到 0 - 65535,信道从 16 个增加到 256 个,同时 MIDI 2.0 也支持 MPE 以及远程控制。

5.2 如何拓展 MIDI

如果 MIDI 2.0 和 MPE 这类现成的解决方案无法满足你的需求,那么你可以考虑自己来拓展 MIDI 协议或者 MIDI 标准格式。目前来看,可靠的拓展方式有几下几种:

  1. 使用未定义的 MIDI 消息:比如系统消息 1111 0101 的行为在 MIDI 标准中就未被定义。这种方法的好处是不需要进行额外的解析工作,但缺点便是可以使用的指令十分有限。
  2. 使用自定义 Chunk:Chunk 在设计之初便考虑到了拓展的问题,你可以按照 Chunk 的格式自由地声明一个新的 Chunk 类型,主流解析工具在碰到无法解析的 Chunk 时会自动忽略掉,所以不用担心兼容的问题。如果你有整段的数据,既不属于 Track,又不能被 Heaer 所包含,那么可以考虑这种方式。
  3. 使用系统独占消息:如果你需要在 MIDI 通信协议上进行拓展,可以考虑使用系统独占消息,合成器会自动忽略无法解析的独占消息。具体可以参考附录中的系统独占消息一节。
  4. 其他:你也可以参考 MPE 的方式,基于现有的编码方案但是重新定义指令的意义和执行。

6. 思考与讨论

6.1 什么时候使用 MIDI 格式,什么时候不用?

首先我们需要认识到 MIDI 的优点,MIDI 记录的实际上是事件流,最适合的场景就是在现场演奏时用于硬件之间的通信。作为 MIDI 文件格式作为一种存储格式,其优点是数据十分紧凑,体积较小。但 MIDI 的缺点是十分明显的,一方面我们无法快速查询、访问其中某个具体内容的值:比如我们没法快速找到某一个轨道的拍号,或者某个音的音高。

所以我的建议是,尽量避免在现场演奏场景之外使用 MIDI 文件格式,但可以在抽象上对齐 MIDI。在内存中我们尽量把 MIDI 文件转化为实例对象,便于我们快速访问。在需要持久化的场景下则可以使用更容易解析的 JSON 或者 MusicXML 格式。只有在用户需要或者向其他编辑工具导出数据的时候,我们才考虑使用 MIDI 标准文件格式。

6.2 MIDI 协议无法满足的需求如何解决?

绝大部分这类问题可以通过不使用 MIDI 编码来解决。原则很简单,只要不涉及现场演奏场景和向其他工具导出数据,就避免使用 MIDI 编码来做任何事情。只用确保在需要 MIDI 的场景可以导出 MIDI 文件就行。

6.3 如果多数场景不使用 MIDI,那有必要深入学习 MIDI 协议吗?

如果你的开发工作涉及到音乐的“本体”部分,那么我建议多了解一些 MIDI 协议,因为虽然我们可能多数情况下不直接使用 MIDI 协议的编码,但是 MIDI 的事件流是创作场景和存储场景会大量用到的,同时 MIDI 中的多数抽象和概念是行业内通用的。

6.4 如何设计自定义的音乐数据格式?

我的建议是用一个文档维护所有的基础字段和拓展字段,各项目在定义 Model 时尽量参考这个文档。如果现有的拓展字段可以解决你的需求,就不要新增拓展字段。

附录

可变长度数量(Variable-Length Quantities)

由于单个字节表示的最大范围为 0 - 256,所以在 MIDI 文件中表示较大数字时会采用可变长度数量。其每一个字节使用第 7 位表示这个字节是否为最后一个字节,1 表示不是最后一个字节,0 表示是最后一个字节, 0 - 6 位则作为有效位。

举一个例子,数字 127 可以表示为 0111 1111 ,128 则表示为 1000 0001 0000 0000,这样理论上可以表示的数字可以无限大,不过在实践中通常不会使用超过 32 位。

总结一下就是:

7 位

0-6 位

是否为最后一个字节

有效位

速率的解释

note on 中的 velocity 实际上是按键的“触发速率”,你可以把其视为从键盘能感知到下按到下按结束这个过程中的键程除以按下时间,note off 则是反向的“释放速率”。速率的计算方式和更多细节可以参考这篇论文:The Interpretation of MIDI Velocity

一堆速查表

  • 查十进制的 MIDI 消息:Expanded MIDI 1.0 Messages List (Status Bytes)
  • 查 GM 乐器表:General MIDI Instrument List
  • 查 MIDI 事件流:Standard MIDI-File Format Spec. 1.1, updated

参考文献

  • https://www.midi.org/specifications
  • MIDI Tutorial
  • Standard MIDI-File Format Spec. 1.1, updated
  • MIDI Polyphonic Expression (MPE) Specification Adopted
  • 钢琴的触键方式是如何影响弹出来的音色的?(https://zhuanlan.zhihu.com/p/19964066)
  • MIDI Tick、Meta-event、变长数表示法、区分 MIDI 文件中单个字节的含义(https://www.cndzq.com/bbs/thread-117332-1-1.html)
  • MPE in Live 11(https://help.ableton.com/hc/en-us/articles/360019144999-MPE-in-Live-11)
  • GDX-620 使用说明书(https://de.yamaha.com/files/download/other_assets/9/334239/DGX-620_ZH.pdf)

推荐读物

  • 《音乐声学——音响、乐器、计算机音乐、MIDI、音乐厅声学原理及应用》- 龚镇雄
  • The Computer Music Tutorial - Curtis Roads

分享成果,随喜正能量】行走于尘世,繁忙的工作节奏,沉重的生活压力,似乎想让生活过得行云流水,真的不是一件容易的事情,那么何不让它变得简单一些?或许我们不够时尚,至少我们可以简约,或许我们不够精致,至少我们可以简洁。把每一段旅途,都当做最好的修行;把每一段旅途遇到的困难,都当做自己的助力;把每一段旅途中遇到的人,都当做今生的因缘。

《VBA信息获取与处理》教程是我推出第六套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。这部教程给大家讲解的内容有:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网数据抓取、VBA延时操作,剪贴板应用、Split函数扩展、工作表信息与其他应用交互,FSO对象的利用、工作表及文件夹信息的获取、图形信息的获取以及定制工作表信息函数等等内容。程序文件通过32位和64位两种OFFICE系统测试。是非常抽象的,更具研究的价值。

教程共两册,八十四讲。今日的内容是专题六“VBA中利用XMLHTTP完成网抓数据”的第1讲:XMLHTTP的简单讲解

第一节 XMLHTTP的简单讲解及相关概念的介绍

现在的社会是网络的社会,离开了网络,很多工作会变得不通畅。我们日常的生活也是和网络紧密联系一起的,那么网络是如何搭建的呢?我们可以通过本讲的讲解了解到HTTP 超文本传输协议,TCP/IP的介绍,XMLHTTP的介绍,等等。

1 什么是XMLHTTP,它是用来做什么的?

1) XML的介绍 XML指可扩展标记语言(EXtensible Markup Language),设计宗旨是传输数据,是W3C (万维网联盟World Wide Web Consortium)的推荐标准。XML 是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。

2) HTTP的介绍 HTTP 超文本传输协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

3) TCP/IP的介绍 TCP/IP是供已连接因特网的计算机进行通信的通信协议(Transmission Control Protocol / Internet Protocol)。定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准。

TCP 用于应用程序之间的通信。当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。

IP 用于计算机之间的通信。IP 是无连接的通信协议。它不会占用两个正在通信的计算机之间的通信线路。这样,IP 就降低了对网络线路的需求。每条线可以同时满足许多不同的计算机之间的通信需要。通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。IP 负责将每个包路由至它的目的地。

TCP/IP协议意味着 TCP 和 IP 在一起协同工作。TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP 包,然后在它们到达的时候重新组合它们。IP 负责将包发送至接受者。

4) XMLHTTP的介绍 XMLHTTP是一套可以在Javascript、VbScript、Jscript等脚本语言中通过http协议传送或从接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面。

来自MSDN的解释:XmlHttp提供客户端同http服务器通讯的协议。客户端可以通过XmlHttp对象(MSXML2.XMLHTTP.3.0)向http服务器发送请求并使用微软XML文档对象模型Microsoft® XML Document Object Model (DOM)处理回应。

现在的绝对多数浏览器都增加了对XmlHttp的支持,IE中使用ActiveXObject方式创建XmlHttp对象,其他浏览器如:Firefox、Opera等通过window.XMLHttpRequest来创建xmlhttp对象.

2 应用XMLHTTP抓取数据的步骤

1)创建XMLHTTP对象 //需MSXML4.0支持

2)打开与服务端的连接,同时定义指令发送方式,服务网页(URL)和请求权限等。客户端通过Open命令打开与服务端的服务网页的连接。与普通HTTP指令传送一样,可以用"GET"方法或"POST"方法指向服务端的服务网页。 

3)发送指令。 

4)等待并接收服务端返回的处理结果。 

5)释放XMLHTTP对象

3 XMLHTTP的属性及方法

1) XMLHTTP的常见属性: 

onreadystatechange:在同步执行方式下获得返回结果的事件句柄。只能在DOM中调用。 

responseBody:   结果返回为无符号整数数组。 

responseStream:  结果返回为IStream流。 

responseText:   结果返回为字符串。 

responseXML:   结果返回为XML格式数据。

2) XMLHTTP的常用方法: 

① Open(bstrMethod, bstrUrl, varAsync, bstrUser, bstrPassword)创建一个新的http请求,并指定此请求的方法、URL以及验证信息(用户名/密码)打开指定网址

bstrMethod:  数据传送方式,即GET或POST。 

bstrUrl:    服务网页的URL。 

varAsync:   是否同步执行。缺省为True,即同步执行,但只能在DOM中实施同步执行。用中一般将其置为False,即异步执行。 

bstrUser:    用户名,可省略。 

bstrPassword:用户口令,可省略。 

setRequestHeader(bstrHeader, bstrvalue)

bstrHeader:HTTP 头(header) 

bstrvalue: HTTP 头(header)的值 

如果Open方法定义为POST,可以定义表单方式上传: 

xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") 

② Send(varBody)发送请求到http服务器并接收回应

varBody:指令集。可以是XML格式数据,也可以是字符串,流,或者一个无符号整数数组。也可以省略,让指令通过Open方法的URL参数代入。

③ abort 取消当前请求

④ getAllResponseHeaders 获取响应的所有http头

⑤ getResponseHeader 从响应信息中获取指定的http头

以上我给出了一些常用的属性和方法,其他的大家可以参考相关的资料,或许我在今后的课程中会用到时讲解。同时我们还要主要下面的注意点:

1、ResponseBody是二进制的数据,是服务器传来的没有经过任何加工的数据。

2 ResponseText是按照utf-8编码把ResponseBody转换而成,也就是:ResponseText=ByteToStr(ResponseBody,"UTF-8")

本节知识点回向:了解一些概念,HTTP,TCP/IP,XMLHTTP,以及XMLHTTP的常用属性和方法。

我20多年的VBA实践经验,全部浓缩在下面的各个教程中,教程学习顺序: