文件应该都不陌生,比如办公软件word、excel、txt等文件,很多人几乎是天天会接触到各种各样的文件。Python内置了读写文件的函数,用法和C是兼容的。需要注意的是,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象,然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
文件对象的操作方法
file 对象使用 open 函数来创建, file 对象常用的函数有close()、next()、tell()等等。
读文件
要以读文件的模式打开一个文件对象,使用Python内置的open()函数。open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。比如open(file, mode=‘r’)。当然,如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在。
正常情况下,文件打开后,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示。最后一步是调用close()方法关闭文件。
但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法。
写文件
写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’。
需要注意的是,以’w’模式写入文件时,如果文件已存在,会直接覆盖(相当于删掉后新写入一个文件)。如果我们希望追加到文件末尾怎么办?可以传入’a’以追加(append)模式写入。
你会发现,无论’r’、‘w’、'a’都是开始所描述open()方法中的第二参数模式的一种。mode参数默认为文本模式,如果要以二进制模式打开,加上 b。
学习对excel及csv文件进行操作
不论对于哪种格式的文件,读写的基本方法是一致的,但是需要注意的一点是对于同一个文件,以不同的格式打开,相应能够进行的读写操作是不一样的。
(1)对excel文件进行操作。使用xlrd读取文件,使用xlwt生成Excel文件(可以控制Excel中单元格的格式)。但是用xlrd读取excel是不能对其进行操作的;而xlwt生成excel文件是不能在已有的excel文件基础上进行修改的,如需要修改文件就要使用xluntils模块。pyExcelerator模块与xlwt类似,也可以用来生成excel文件。
(2)对csv文件进行操作。csv是逗号分隔值文件格式,一般用WORDPAD或记事本(NOTE),EXCEL打开。csv(逗号分隔值)是一种用来存储数据的纯文本文件,通常都是用于存放电子表格或数据的一种文件格式。
os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
序号 | 方法及描述 |
---|---|
1 | os.access(path, mode)检验权限模式 |
2 | os.chdir(path)改变当前工作目录 |
3 | os.chflags(path, flags)设置路径的标记为数字标记。 |
4 | os.chmod(path, mode)更改权限 |
5 | os.chown(path, uid, gid)更改文件所有者 |
6 | os.chroot(path)改变当前进程的根目录 |
7 | os.close(fd)关闭文件描述符 fd |
8 | os.closerange(fd_low, fd_high)关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 |
9 | os.dup(fd)复制文件描述符 fd |
10 | os.dup2(fd, fd2)将一个文件描述符 fd 复制到另一个 fd2 |
11 | os.fchdir(fd)通过文件描述符改变当前工作目录 |
12 | os.fchmod(fd, mode)改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。 |
13 | os.fchown(fd, uid, gid)修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。 |
14 | os.fdatasync(fd)强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。 |
15 | os.fdopen(fd[, mode[, bufsize]])通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 |
16 | os.fpathconf(fd, name)返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。 |
17 | os.fstat(fd)返回文件描述符fd的状态,像stat()。 |
18 | os.fstatvfs(fd)返回包含文件描述符fd的文件的文件系统的信息,像 statvfs() |
19 | os.fsync(fd)强制将文件描述符为fd的文件写入硬盘。 |
20 | os.ftruncate(fd, length)裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。 |
21 | os.getcwd()返回当前工作目录 |
22 | os.getcwdu()返回一个当前工作目录的Unicode对象 |
23 | os.isatty(fd)如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。 |
24 | os.lchflags(path, flags)设置路径的标记为数字标记,类似 chflags(),但是没有软链接 |
25 | os.lchmod(path, mode)修改连接文件权限 |
26 | os.lchown(path, uid, gid)更改文件所有者,类似 chown,但是不追踪链接。 |
27 | os.link(src, dst)创建硬链接,名为参数 dst,指向参数 src |
28 | os.listdir(path)返回path指定的文件夹包含的文件或文件夹的名字的列表。 |
29 | os.lseek(fd, pos, how)设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 |
30 | os.lstat(path)像stat(),但是没有软链接 |
31 | os.major(device)从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。 |
32 | os.makedev(major, minor)以major和minor设备号组成一个原始设备号 |
33 | os.makedirs(path[, mode])递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。 |
34 | os.minor(device)从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。 |
35 | os.mkdir(path[, mode])以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。 |
36 | os.mkfifo(path[, mode])创建命名管道,mode 为数字,默认为 0666 (八进制) |
37 | os.mknod(filename[, mode=0600, device])创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。 |
38 | os.open(file, flags[, mode])打开一个文件,并且设置需要的打开选项,mode参数是可选的 |
39 | os.openpty()打开一个新的伪终端对。返回 pty 和 tty的文件描述符。 |
40 | os.pathconf(path, name)返回相关文件的系统配置信息。 |
41 | os.pipe()创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 |
42 | os.popen(command[, mode[, bufsize]])从一个 command 打开一个管道 |
43 | os.read(fd, n)从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。 |
44 | os.readlink(path)返回软链接所指向的文件 |
45 | os.remove(path)删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。 |
46 | os.removedirs(path)递归删除目录。 |
47 | os.rename(src, dst)重命名文件或目录,从 src 到 dst |
48 | os.renames(old, new)递归地对目录进行更名,也可以对文件进行更名。 |
49 | os.rmdir(path)删除path指定的空目录,如果目录非空,则抛出一个OSError异常。 |
50 | os.stat(path)获取path指定的路径的信息,功能等同于C API中的stat()系统调用。 |
51 | os.stat_float_times([newvalue])决定stat_result是否以float对象显示时间戳 |
52 | os.statvfs(path)获取指定路径的文件系统统计信息 |
53 | os.symlink(src, dst)创建一个软链接 |
54 | os.tcgetpgrp(fd)返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 |
55 | os.tcsetpgrp(fd, pg)设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。 |
56 | os.tempnam([dir[, prefix]])Python3 中已删除。返回唯一的路径名用于创建临时文件。 |
57 | os.tmpfile()Python3 中已删除。返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。 |
58 | os.tmpnam()Python3 中已删除。为创建一个临时文件返回一个唯一的路径 |
59 | os.ttyname(fd)返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。 |
60 | os.unlink(path)删除文件路径 |
61 | os.utime(path, times)返回指定的path文件的访问和修改的时间。 |
63 | os.write(fd, str)写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 |
64 | os.path 模块获取文件的属性信息。 |
datetime是Python处理日期和时间的标准库,这个模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。
类名 | 功能说明 |
---|---|
date | 日期对象,常用的属性有year, month, day |
time | 时间对象 |
datetime | 日期时间对象,常用的属性有hour, minute, second, microsecond |
timedelta | 时间间隔,即两个时间点之间的长度 |
tzinfo | 时区信息对象 |
每种类都有各自固定的数据结构以及方法属性。下面依次做些简单介绍。
d1 = date(2011,06,03)#date对象
方法 | 属性 |
---|---|
date.max、date.min | date对象所能表示的最大、最小日期 |
date.resolution | date对象表示日期的最小单位。这里是天。 |
date.today() | 返回一个表示当前本地日期的date对象 |
date.fromtimestamp(timestamp) | 根据给定的时间戮,返回一个date对象 |
d1.year、date.month、date.day | 年、月、日 |
d1.replace(year, month, day) | 生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变) |
d1.timetuple() | 返回日期对应的time.struct_time对象 |
d1.weekday() | 返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推 |
d1.isoweekday() | 返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推 |
d1.isocalendar() | 返回格式如(year,month,day)的元组 |
d1.isoformat() | 返回格式如’YYYY-MM-DD’的字符串 |
d1.strftime(fmt) | 和time模块format相同 |
from datetime import *
now = date(2016, 10, 26)
tomorrow = now.replace(day = 27)
print 'now:', now, ', tomorrow:', tomorrow
print 'timetuple():', now.timetuple()
print 'weekday():', now.weekday()
print 'isoweekday():', now.isoweekday()
print 'isocalendar():', now.isocalendar()
print 'isoformat():', now.isoformat()
print 'strftime():', now.strftime("%Y-%m-%d")
#Output========================
# now: 2016-10-26 , tomorrow: 2016-10-27
# timetuple(): time.struct_time(tm_year=2016, tm_mon=10, tm_mday=26, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=300, tm_isdst=-1)
# weekday(): 2
# isoweekday(): 3
# isocalendar(): (2016, 43, 3)
# isoformat(): 2016-10-26
# strftime(): 2016-10-26
方法 | 属性 |
---|---|
time.min、time.max | time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999) |
time.resolution | 时间的最小单位,这里是1微秒 |
t1.hour、t1.minute、t1.second、t1.microsecond | 时、分、秒、微秒 |
t1.tzinfo | 时区信息 |
t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ) | 创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性(原有对象仍保持不变) |
t1.isoformat() | 返回型如"HH:MM:SS"格式的字符串表示 |
t1.strftime(fmt) | 同time模块中的format |
from datetime import *
tm = time(23, 46, 10)
print 'tm:', tm
print 'hour: %d, minute: %d, second: %d, microsecond: %d' % (tm.hour, tm.minute, tm.second, tm.microsecond)
tm1 = tm.replace(hour=20)
print 'tm1:', tm1
print 'isoformat():', tm.isoformat()
print 'strftime()', tm.strftime("%X")
#Output==============================================
# tm: 23:46:10
# hour: 23, minute: 46, second: 10, microsecond: 0
# tm1: 20:46:10
# isoformat(): 23:46:10
# strftime() 23:46:10
方法 | 属性 |
---|---|
datetime.today() | 返回一个表示当前本地时间的datetime对象 |
datetime.now([tz]) | 返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间 |
datetime.fromtimestamp(timestamp[, tz]) | 根据时间戮创建一个datetime对象,参数tz指定时区信息 |
datetime.utcfromtimestamp(timestamp) | 根据时间戮创建一个datetime对象 |
datetime.combine(date, time) | 根据date和time,创建一个datetime对象 |
datetime.strptime(date_string, format) | 将格式字符串转换为datetime对象 |
dt.year、month、day、hour、minute、second、microsecond、tzinfo | 同上 |
dt.date() | 获取date对象 |
dt.time() | 获取time对象 |
dt. replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]) | 同上 |
dt. timetuple ()、dt. utctimetuple ()、dt. toordinal ()、dt. weekday ()、dt. isocalendar ()、dt. isoformat ([ sep] ) 、dt. strftime (format) | 同上 |
dt. ctime () | 返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple())) |
from datetime import *
import time
print 'datetime.max:', datetime.max
print 'datetime.min:', datetime.min
print 'datetime.resolution:', datetime.resolution
print 'today():', datetime.today()
print 'now():', datetime.now()
print 'utcnow():', datetime.utcnow()
print 'fromtimestamp(tmstmp):', datetime.fromtimestamp(time.time())
print 'utcfromtimestamp(tmstmp):', datetime.utcfromtimestamp(time.time())
#output======================
# datetime.max: 9999-12-31 23:59:59.999999
# datetime.min: 0001-01-01 00:00:00
# datetime.resolution: 0:00:00.000001
# today(): 2016-10-26 23:12:51.307000
# now(): 2016-10-26 23:12:51.307000
# utcnow(): 2016-10-26 15:12:51.307000
# fromtimestamp(tmstmp): 2016-10-26 23:12:51.307000
# utcfromtimestamp(tmstmp): 2016-10-26 15:12:51.307000
#coding:utf-8
from datetime import *
dt = datetime.now()
#日期减一天
dt1 = dt + timedelta(days=-1)#昨天
dt2 = dt - timedelta(days=1)#昨天
dt3 = dt + timedelta(days=1)#明天
delta_obj = dt3-dt
print type(delta_obj),delta_obj# 1 day, 0:00:00
print delta_obj.days ,delta_obj.total_seconds()#1 86400.0
#! /usr/bin/python
# coding=utf-8
from datetime import datetime, tzinfo,timedelta
"""
tzinfo是关于时区信息的类
tzinfo是一个抽象类,所以不能直接被实例化
"""
class UTC(tzinfo):
"""UTC"""
def __init__(self,offset = 0):
self._offset = offset
def utcoffset(self, dt):
return timedelta(hours=self._offset)
def tzname(self, dt):
return "UTC +%s" % self._offset
def dst(self, dt):
return timedelta(hours=self._offset)
#北京时间
beijing = datetime(2011,11,11,0,0,0,tzinfo = UTC(8))
print "beijing time:",beijing
#曼谷时间
bangkok = datetime(2011,11,11,0,0,0,tzinfo = UTC(7))
print "bangkok time",bangkok
#北京时间转成曼谷时间
print "beijing-time to bangkok-time:",beijing.astimezone(UTC(7))
#计算时间差时也会考虑时区的问题
timespan = beijing - bangkok
print "时差:",timespan
#Output==================
# beijing time: 2011-11-11 00:00:00+08:00
# bangkok time 2011-11-11 00:00:00+07:00
# beijing-time to bangkok-time: 2011-11-10 23:00:00+07:00
# 时差: -1 day, 23:00:00
Python从设计之初就已经是一门面向对象的语言,面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如老师、学生、医生、汽车、猫、狗等等都是类的一种,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。下面列表的内容是面向对象语言中需要搞清楚的一些重要概念。
名称 | 概念 |
---|---|
类(Class) | 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 |
方法 | 类中定义的函数。 |
类变量 | 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。 |
数据成员 | 类变量或者实例变量用于处理类及其实例对象的相关的数据。 |
方法重写 | 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。 |
局部变量 | 定义在方法中的变量,只作用于当前实例的类。 |
实例变量 | 在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。 |
继承 | 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。 |
实例化 | 创建一个类的实例,类的具体对象。 |
对象 | 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。 |
实话说,小白学习正则表达式的时候有种撞墙的冲动^吐血!$ 需要强调的一点是正则表达式非常强大,学好了可以让你的编程事半功倍,尤其是程序的应用实践方面。不过正如很多明白人已经讲过的,要讲清楚正则的所有内容,可以写一本厚厚的书了;如果你经常遇到正则表达式的问题,你可能需要一本正则表达式的参考书。所以作为小白自学的基础介绍,这里将把重点放在对正则表达式概念的认知上,搞明白正则表达式是什么、主要用来做什么以及一些简单的示例就可以了。
如果用一句话描述对初学正则表达式的认识,那就是一套关于字符串的规范法则。有点类似交通法规,比如靠右行、红灯停绿灯行等诸如此类的明确要求与约定,用以保障交通通畅和车辆行驶安全。
关于正则表达式,个人认为还是廖雪峰老师讲解的清楚明了。
字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址,虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。
正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
所以我们判断一个字符串是否是合法的Email的方法是:
1.创建一个匹配Email的正则表达式;
2.用该正则表达式去匹配用户的输入来判断是否合法。
因为正则表达式也是用字符串表示的,所以,我们要首先了解如何用字符来描述字符。
在正则表达式中,如果直接给出字符,就是精确匹配。用\d可以匹配一个数字,\w可以匹配一个字母或数字,所以:
‘00\d’可以匹配’007’,但无法匹配’00A’;
‘\d\d\d’可以匹配’010’;
‘\w\w\d’可以匹配’py3’;
.可以匹配任意字符,所以:
‘py.‘可以匹配’pyc’、‘pyo’、‘py!‘等等。
要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符:
来看一个复杂的例子:\d{3}\s+\d{3,8}。
我们来从左到右解读一下:
1.\d{3}表示匹配3个数字,例如’010’;
2.\s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少有一个空格,例如匹配’ ‘,’ ‘等;
3.\d{3,8}表示3-8个数字,例如’1234567’。
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。
如果要匹配’010-12345’这样的号码呢?由于’-‘是特殊字符,在正则表达式中,要用’‘转义,所以,上面的正则是\d{3}-\d{3,8}。
但是,仍然无法匹配’010 - 12345’,因为带有空格。所以我们需要更复杂的匹配方式。
要做更精确地匹配,可以用[]表示范围,比如:
[0-9a-zA-Z_]可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如’a100’,‘0_Z’,‘Py3000’等等;
[a-zA-Z_][0-9a-zA-Z_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;
[a-zA-Z_][0-9a-zA-Z_]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B可以匹配A或B,所以(P|p)ython可以匹配’Python’或者’python’。
表示行的开头,\d表示必须以数字开头。
KaTeX parse error: Expected 'EOF', got '\d' at position 8: 表示行的结束,\̲d̲表示必须以数字结束。
你可能注意到了,py也可以匹配’python’,但是加上^py$就变成了整行匹配,就只能匹配’py’了。
re 模块使 Python 语言拥有全部的正则表达式功能。
-re.match函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
需要注意的是,re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而search匹配整个字符串,直到找到一个匹配。
参数 | 描述 |
---|---|
pattern | 正则中的模式字符串。 |
string | 替换的字符串,也可为一个函数。 |
flags | 要被查找替换的原始字符串。 |
count | 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。 |
#!/usr/bin/python3
import re
phone = "2004-959-559 # 这是一个电话号码"
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)
输出结果:
电话号码 : 2004-959-559
电话号码 : 2004959559
在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议是HTTP,所以:
(1)HTML是一种用来定义网页的文本,会HTML,就可以编写网页;
(2)HTTP是在网络上传输HTML的协议,用于浏览器和服务器的通信。
HTTP请求的流程:
步骤1:浏览器首先向服务器发送HTTP请求,请求包括:
方法:GET还是POST,GET仅请求资源,POST会附带用户数据;
路径:/full/url/path;
域名:由Host头指定:Host: www .sina .com .cn
以及其他相关的Header;
如果是POST,那么请求还包括一个Body,包含用户数据。
步骤2:服务器向浏览器返回HTTP响应,响应包括:
响应代码:200表示成功,3xx表示重定向,4xx表示客户端发送的请求有错误,5xx表示服务器端处理时发生了错误;
响应类型:由Content-Type指定;
以及其他相关的Header;
通常服务器的HTTP响应会携带内容,也就是有一个Body,包含响应的内容,网页的HTML源码就在Body中。
步骤3:如果浏览器还需要继续向服务器请求其他资源,比如图片,就再次发出HTTP请求,重复步骤1、2。
Web采用的HTTP协议采用了非常简单的请求-响应模式,从而大大简化了开发。当我们编写一个页面时,我们只需要在HTTP请求中把HTML发送出去,不需要考虑如何附带图片、视频等,浏览器如果需要请求图片和视频,它会发送另一个HTTP请求,因此,一个HTTP请求只处理一个资源。
HTTP协议同时具备极强的扩展性,虽然浏览器请求的是 http:/ /www. sina. com. cn/ 的首页,但是新浪在HTML中可以链入其他服务器的资源,比如, 从而将请求压力分散到各个服务器上,并且,一个站点可以链接到其他站点,无数个站点互相链接起来,就形成了World Wide Web,简称WWW。