前面我们已经知道,HTTP协议是一种通用机制。客户端使用HTTP向服务器请求文档,而服务器通过HTTP向客户端提供文档。
然而,HTTP——超文本传输协议的”超文本“如何体现?
其实HTTP的设计初衷并非只是将其作为一种用于传输文件的新方法,也不是将其作为旧式文件传输协议(如FTP)的一个更复杂的提供缓存功能的替代品。当然HTTP能够传输书籍、图片以及视频这些独立的文件,但是尽管如此,HTTP的目的其实远不止于此,它还允许师姐各地的服务器发送文档,并通过相互之间的交叉引用形成一张互相连接的信息网————HTTP就是为万维网(World Wide Web)设计的。
1 超媒体与URL
万维网——可以直接成为Web——的工作所实现的梦想就是把寻找引用的任务交给机器来负责。
假设有一段文字”第九章关于cookie的讨论“,这段文字本来是孤立的,与外界没有联系,但是如果它出现在电脑屏幕上,加了下划线,并且被点击之后可以转到所引用的文本,那么这段文字就成为了一个超链接(hyperlink)。文本中包含内嵌超链接的整个文档就叫做超文本文档。如果文档中又加入了图片、声音以及视频,该文档就成了超媒体(hypermedia)。
其中前缀hyper表示后面的媒介能够理解文档之间相互引用的机制,并且能够为用户生成链接。为了操作超媒体,人们发明了统一资源定位符URL。它不仅为现代的超文本文档提供了一个统一的机制,还能够供以前的FTP文件和telnet服务器使用。在网络浏览器的地址栏可以看到很多类似下面这样的例子。
https://www,python.org http://en.wikipedia.org/wiki/Python_(programming_language) ftp://ssd.jpl.nasa.gov/pub/eph/planets/README.txt
第一个标记(如https、http)即为所使用的机制(scheme),它指明了获取文档所使用的协议。后面跟着一个冒号和两个斜杠,然后是主机名,接着可能还有端口号。URL最后是一个路径,用于在可用服务的所有文档中指明要获取的特定文档。
解析与构造URL:关于URL以及urllib的主要介绍,参见Python核心编程3-Web开发部分 1.Web客户端和服务器的内容,本篇会对链接中没有提到的部分进行一些补充。
- 相对URL:URL中有类似于相对路径的概念。如果一个文档中的所有链接都是绝对URL的话,那么毫无疑问这些链接会指向正确的资源,但是如果文档中包含相对URL的话,我们就需要将文档本身的位置考虑进去了。Python提供了一个urljoin()函数,用于处理标准中的所有相关细节。假设从一个超文本文档中提取出了一个URL,该URL可能是相对的,也可能是绝对的。此时可以将其传递给urljoin(),由它负责填充剩余消息。如果URL是绝对URL,那么不会有任何问题,urljoin()会直接返回该URL。urljoin的参数顺序和os.path.join()是一样的。第一个参数是正在阅读的文档的基地址,第二个参数则是从该文档中提取出的URL。如果第二个参数是相对URL,那么有多种方法可以重写基地址的某些部分。.由于相对URL无需指定使用的协议机制,如果编写网页时并不知道使用HTTP还是HTTPS的话,那么使用相对URL就十分方便了(即使是用来编写网页的静态部分)。在这种情况下,urljoin()只会将基地址的协议复制到第二个参数提供的绝对URL中,构成一个完整的URL,以此作为返回值。 如果准备在网站中使用相对URL的话,有一点是非常重要的:一定要注意页面URL的最后是否包含一个斜杠。因为最后包含斜杠和不包含斜杠的相对URL含义是不同的。第一个URL表示该请求是为了显示rfc3986这一文档而访问包含该文档的html目录,此时的当前工作目录是html目录,而后者则不同了。在真正的文件系统中,只有目录的结尾会有斜杠,因此它把rfc3986本身看作一个正在访问的目录。所以根据第二个URL构建出来的连接会直接在rfc3986/之后添加相对URL参数。 在设计站点时,一定要确保当用户提供错误的URL时能够马上将其重定向至正确的路径。例如,如果要在访问上面例子的第二个URL,那么IETF的网络服务器会检测到后面多加了一个斜杠,然后它会在响应中声明一个Location头,给出正确的URL。 因此,相对URL并不一定相对于HTTP请求中提供的路径。如果网站的响应中包含一个Location头,那么相对URL必须相对于Location头中提供的路径。
2.超文本标记语言(HTML)
现在介绍推动Web发展的核心文档样式的书籍很多。此外还有一些现行的标准也对超文本文档的格式、使用层级样式表(CSS,Cascading Style Sheets)确定超文本文档样式的机制以及Javascript等浏览器内嵌语言的API做了描述。其中,JavaScript等浏览器内核语言可以在用户与页面交互或浏览器从服务器我获取更多信息时对文档进行实时的修改。下面是集合核心标准与资源的链接:http://www.w3.org/TR/html5/ 、 http://www.w3.org/TR/CSS/ 、https://developer.mozilla.org/en-US/docs/Web/JavaScript 、 https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model
HTML是一种使用大量尖括号(<...>)来装饰纯文本的机制。每对尖括号都创建了一个标签(tag),如果标签开头没有斜杠的话,就表示文档中某个新元素(element)的开始,否则就表示元素的结尾。下面的例子展示了一个简单的段落,该段落中包含了一个加粗的单词和一个斜体的单词。
<p>This is a paragraph with <b>bold</b> and <i>italic</i> words.</p>
某些标签是自包含的,不需要之后再使用对应的结束标记。最有名的例子就是<br>标签,它创建了段落中的一个空行。有些更为一丝不苟的开发者会把<br>写为<br/>,这是从扩展标记语言(XML)中学习过来的,但在HTML中这并不是必须的。比如,并不一定要为所有开始标签提供对应的结束标签。当一个用<ul>表示的无序列表结束的时候,无论其内部使用<li>表示的列表元素是否通过</li>标签表示元素结束,HTML解析器都会认为该无序列表包含的所有列表元素都已经结束。
从上面的实例段落中,可以清楚地认识到,HTML的标签是可以层层嵌套的。设计者在构建完整的Web页面时可以不断地在HTMl元素内部嵌入其他HTML元素。在构建页面的过程中,设计者大多会不可避免地不断重复使用HTML定义的有限元素集合中的元素。这些元素用于表示页面上不同类型的内容。监管最新的HTML5标准允许设计者直接在页面中创建新元素,但是设计者们还是会倾向于使用标准元素。
一个大型的页面可能会处于各种不同的原因使用<div>(最通用的分块形式)或<span>(最通用的标记连续文本的方式)这样的通用标签。那么如果所有元素都使用了相同的<div>标签,如何使用CSS来合理地设置各元素的样式呢?又该如何使用Javascript来设置用户与各元素不同交互方式呢? ——答案就是,为每个元素指定一个class.这样,HTML编写者就可以为各元素提供一个特定的标记,之后就可以通过该标记来访问特定的元素了。要使用class,有两种常见的方法。
- 第一种方法是,在设计时为所有的HTML元素都指定一个唯一的class.
这样,对应的CSS和Javascript就可以通过.city和.temperature这样的选择器来引用特定的元素了。如果想要更细粒度一点,可以使用h5.city和p.temperature。最简单形式的CSS选择器只需要一个标签的名称,后面加上以句点作为前缀的class名称即可。这两者都不是必须的。<div class="weather"> <h5 class="city">Provo<h5/> <p class="temperature">61°F</p> </div>
- 有时候在class为weather的<div>内,设计者认为它们使用<h5>和<p>的目的都是唯一的,因此他们选择只为外层元素指定class的值
此时,要在CSS或Javascript中引用该<div>内部的<h5>和<p>,就需要使用更为复杂的模式了。我们使用空格来连接外层标签的class值与内层标签的名称:.weather h5 \ .weather p。<div class="weather"><h5>Provo<h5/><p>61°F</p></div>
3.读写数据库
import os,pprint,sqlite3
from collections import namedtuple
def open_database(path='bank.db'):
new = not os.path.exists(path)
db = sqlite3.connect(path)
if new:
c = db.cursor()