爬虫面试题
scrapy框架的工作流程?
1,你了解的反爬机制,如何处理?
通过headers反爬虫
ip的访问频率
动态加载数据,通过ajax请求数据,或者通过js代码生成数据
部分数据加密处理
解决方法:
对于基本网页的抓取可以自定义headers,添加headers的数据
使用多个代理ip进行抓取或者设置抓取的频率降低一些,
动态网页的可以使用selenium + phantomjs 进行抓取
对部分数据进行加密的,可以使用selenium进行截图,使用python自带的pytesseract库进行识别,但是比较慢最直接的方法是找到加密的方法进行逆向推理。
2,scrapy的基本架构
Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.
Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
3,scrapy的去重原理
1.找到Request类:需要将dont_filter设置为False开启去重,默认是True,没有开启去重;
2.对于每一个url的请求,调度器都会根据请求得相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中的指纹信息进行比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中。如果set()集合中没有存在这个加密后的数据,就将这个Request对象放入队列中,等待被调度。
4,scrapy中间件有哪几种类,你用过哪些?
下载中间件,爬虫中间件
5,scrapy中间件在哪起的作用
爬虫中间件:爬虫发起请求request的时候调用,列如更换修改代理ip,修改UA,
下载器中间件:浏览器返回响应response的时候调用,无效的数据,特殊情况进行重试
6,为什么会用到代理?
如果你一直用同一个代理IP爬取这个网页,很有可能IP会被禁止访问网页,所以,基本上做爬虫的都躲不过去IP的问题。
7,代理怎么使用?
1,可以使用urllib2中的ProxyHandler来设置代理ip
1 import urllib2 2 3 # 构建了两个代理Handler,一个有代理IP,一个没有代理IP 4 httpproxy_handler = urllib2.ProxyHandler({"http" : "124.88.67.81:80"}) 5 nullproxy_handler = urllib2.ProxyHandler({}) 6 #定义一个代理开关 7 proxySwitch = True 8 # 通过 urllib2.build_opener()方法使用这些代理Handler对象,创建自定义opener对象 9 # 根据代理开关是否打开,使用不同的代理模式 10 if proxySwitch: 11 opener = urllib2.build_opener(httpproxy_handler) 12 else: 13 opener = urllib2.build_opener(nullproxy_handler) 14 15 request = urllib2.Request("http://www.baidu.com/") 16 17 # 使用opener.open()方法发送请求才使用自定义的代理,而urlopen()则不使用自定义代理。 18 response = opener.open(request) 19 20 # 就是将opener应用到全局,之后所有的,不管是opener.open()还是urlopen() 发送请求,都将使用自定义代理。 21 # urllib2.install_opener(opener) 22 # response = urlopen(request) 23 24 print response.read()
2,使用requets代理
1 import requests 2 3 # 根据协议类型,选择不同的代理 4 proxies = { 5 "http": "http://12.34.56.79:9527", 6 "https": "http://12.34.56.79:9527", 7 } 8 9 response = requests.get("http://www.baidu.com", proxies = proxies) 10 print response.text
8,代理失效了怎么处理?
1 1、将代理IP及其协议载入ProxyHandler赋给一个opener_support变量;2、将opener_support载入build_opener方法,创建opener;3、安装opener。具体代码如下:from urllib import requestdef ProxySpider(url, proxy_ip, header):opener_support = request.ProxyHandler({'http': proxy_ip}) opener = request.build_opener(opener_support) request.install_opener(opener) req = request.Request(url, headers=header)rsp = request.urlopen(req).read()return rsp
9,爬取过程中,登录验证码如何处理?
抓取验证码图,对接打码平台进行处理返回
10,爬取速度过快,出现的验证码如何处理?
抓取验证码图,对接打码平台进行处理返回
11,如何用机器识别验证码?
对接打码平台
12,cookie如何处理?
requests.session
13,如何处理网站加密传参的情况?
简单加密可以使用selenium,或者执行js,存储cookie,手动修改cookie的值
也可以下载它们相关的APP
14,分布式的原理?
捅过重写scheduler和spider类,实现了调度、spider启动和redis的交互。实现新的dupefilter和queue类,达到了判重和调度容器和redis的交互,因为每个主机上的爬虫进程都访问同一个redis数据库,所以调度和判重都统一进行统一管理,达到了分布式爬虫的目的。
15,分布式如何判断爬虫已经停止了?
1 spider.getStatus();//获取爬虫状态 2 spider.getStatus().equals(Spider.Status.Init);//运行中
16,爬取下来的数据如何选择什么存储方式会更好
针对数据而定。
18,动态加载的数据如何提取?
动态网页的可以使用selenium + phantomjs 进行抓取
19,json数据如何提取?
json.loads, json.dumps
20,Python里面深拷贝,浅拷贝的区别?
浅拷贝不管几层只会拷贝第一层
拷贝就是在内存中重新开辟一块空间,不管数据结构多么复杂,只要遇到可能发生改变的数据类型,就重新开辟一块内存空间把内容复制下来,直到最后一层,不再有复杂的数据类型,就保持其原引用。这样,不管数据结构多么的复杂,数据之间的修改都不会相互影响
21,是否了解线程的同步和异步?
线程同步是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率低
线程异步:访问资源时在空闲等待时同时访问其他资源,实现多线程机制
22,链表和顺序表存储时各自有什么特点?
顺序表的优点是可以随机访问数据元素;
缺点是大小固定,不利于增删结点。
链表的优点是采用指针方式增减结点,非常方便(只需要改变指针指向,不移动结点);
缺点是不能进行随机访问,另外,每个结点上增加指针域,造成额外存储空间增大。
23,使用redis搭建分布式系统时如何处理网络延迟和网络异常?
由于网络异常的存在,分布式系统中请求结果存在“三态”的概念,即三种状态:“成功”、“失败”、“超时(未知)”
当出现“超时”时可以通过发起读取数据的操作以验证 RPC 是否成功(例如银行系统的做法)
另一种简单的做法是,设计分布式协议时将执行步骤设计为可重试的,即具有所谓的“幂等性”
24,数据仓库是什么?
数据仓库是一个面向主题的、集成的、稳定的、反映历史变化的、随着时间的流逝发生变化的数据集合。它主要支持管理人员的决策分析。
数据仓库收集了企业相关内部和外部各个业务系统数据源、归档文件等一系列历史数据,最后转化成企业需要的战略决策信息。
- 特点:
面向主题:根据业务的不同而进行的内容划分;
集成特性:因为不同的业务源数据具有不同的数据特点,当业务源数据进入到数据仓库时,需要采用统一的编码格式进行数据加载,从而保证数据仓库中数据的唯一性;
非易失性:数据仓库通过保存数据不同历史的各种状态,并不对数据进行任何更新操作。
历史特性:数据保留时间戳字段,记录每个数据在不同时间内的各种状态。
25,假设有一个爬虫程序,从网络上的获取的频率快,本地写入数据的频率慢,使用什么数据结构比较好?
26,你是否了解谷歌的无头浏览器?
无头浏览器即headless browser,是一种没有界面的浏览器。既然是浏览器那么浏览器该有的东西它都应该有,只是看不到界面而已。
Python中selenium模块中的PhantomJS即为无界面浏览器(无头浏览器):是基于QtWebkit的无头浏览器,
27,你是否了解mysql数据库的几种引擎?
- InnoDB:
InnoDB是一个健壮的事务型存储引擎,这种存储引擎已经被很多互联网公司使用,为用户操作非常大的数据存储提供了一个强大的解决方案。
在以下场合下,使用InnoDB是最理想的选择:
1.更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。
2.事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎。
3.自动灾难恢复。与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。
4.外键约束。MySQL支持外键的存储引擎只有InnoDB。
5.支持自动增加列AUTO_INCREMENT属性。
一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择。
- MEMORY:
使用MySQL Memory存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质是系统内存。
虽然在内存中存储表数据确实会提供很高的性能,但当mysqld守护进程崩溃时,所有的Memory数据都会丢失。
获得速度的同时也带来了一些缺陷。
一般在以下几种情况下使用Memory存储引擎:
1.目标数据较小,而且被非常频繁地访问。在内存中存放数据,所以会造成内存的使用,可以通过参数max_heap_table_size控制Memory表的大小,设置此参数,就可以限制Memory表的最大大小。
2.如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中。
3.存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。
28,redis数据库有哪几种数据结构?
5种数据结构
string
使用string时,redis**大多数情况下**并不会理解或者解析其含义,无论使用json、xml还是纯文本在redis看来都是一样的,只是一个字符串,只能进行strlen、append等对字符串通用的操作,无法针对其内容进一步操作。其基本操作命令有set、get、strlen、getrange、append:
1
2
3
4
5
|
SET key value GET key STRLEN key GETRANGE key start end APPEND key value |
在大多数情况之外,就是string中存储的为纯数字的情况,redis可以将字符串当做数字进行进一步操作,这些操作包括decr、decrby、incr、incrby和incrbyfloat。
hash
使用hash时,在我看来,就是value本身就是一组key-value对,不过redis将这里的key称为field(但是hkeys命令为什么不叫hfields命令呢哈哈),也就是value是一组field-value对。其基本操作命令有hset、hget、hmset、hmget、hgetall、hkeys和hdel:
1
2
3
4
5
6
7
|
HSET key field value HGET key field HMSET key field value [field value ...] HMGET key field [field ...] HGETALL key HKEYS key HDEL key field [field ...] |
list
使用list时,value就是一个string数组,操作这组string时,可以像对待栈一样使用pop和push操作,但是这个栈两端都能进行操作;也可以像对待数组一样使用一个index参数来操作。list的操作命令略杂,主要分为两类:L开头的和R开头的,L代表LEFT或者LIST,进行一些从列表左端进行的操作,或者一些与端无关的操作;R代表RIGHT,进行一些从列表右端进行的操作。
set
set用于存储一组不重复的值,也可以进行一些集合的操作,就像数学上的集合,它是无序的。基本操作有sadd和sismember:
1
2
|
SADD key member [member ...] SISMEMBER key member |
集合操作有:求交sinter、求并sunion和求差sdiff:
1
2
3
|
SINTER key [key ...] SUNION key [key ...] SDIFF key [key ...] |
sorted set
sorted set类似set,但是sorted set里每个元素都有一个score,这个score可用于排序和排名。基本操作有zadd、zcount、zrank:
1
2
3
|
ZADD key score member [score member ...] ZCOUNT key min max ZRANK key member |
29,对 __name__=='main'的理解
__name__是当前模块名,当模块被直接运行时模块名为_main_,也就是当前的模块,当模块被导入时,模块名就不是__main__,即代码将不会执行。
30,python是如何进行内存管理的?
a、对象的引用计数机制
python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。
b、垃圾回收
1>当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
2>当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象 的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
c、内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
1>Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理 对小块内存的申请和释放。
2>Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用 系统的malloc。
3>对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
31,__new)_和__init__的区别
__new__:它是创建对象时调用,会返回当前对象的一个实例,可以用_new_来实现单例
__init__:它是创建对象后调用,对当前对象的一些实例初始化,无返回值
32,常用的网络爬取方法
-
正则表达式
-
Beautiful Soup
-
Lxml
33,urllib 和urllib2的区别?
urllib 和urllib2都是接受URL请求的相关模块,但是urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。urllib不可以伪装你的User-Agent字符串。
urllib提供urlencode()方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
34,列举爬虫用到的网络数据包,解析包?
-
网络数据包 urllib、urllib2、requests
-
解析包 re、xpath、beautiful soup、lxml
35,手写一个单列模式?
1 lass Singleton(object): 2 _instance = None 3 def __new__(cls, *args, **kw): 4 if not cls._instance: 5 cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) 6 return cls._instance 7 class MyClass(Singleton): 8 a = 1 9 one = MyClass() 10 two = MyClass() 11 id(one) = id(two) 12 >>> True
36,常用的网络爬取方法?
urllib2 , Beautiful Soup 正则 xpath
37,代码实现删除list里面的重复元素
set
38,手写代码二分查找
39,python2和python3的区别
40,python的装饰器 ,手写
41,python常用的内置库,
42,如何做增量式爬取?
去爬帖子列表页, 每次都把当前页的 url 和数据库中的对比,如果没有重复的说明,这一夜都是新的 URL,然后下一页,直到出现部分重复或完全重复的页面
43,简述beautifulsoup模块的作用及基本使用?
BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后遍可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单。
44,seleniun模块的作用及基本使用?
操作浏览器
45,scrapy如何实现大文件的下载?
当使用requests的get下载大文件/数据时,建议使用使用stream模式。
当把get函数的stream参数设置成False时,它会立即开始下载文件并放到内存中,如果文件过大,有可能导致内存不足。
当把get函数的stream参数设置成True时,它不会立即开始下载,当你使用iter_content或iter_lines遍历内容或访问内容属性时才开始下载。需要注意一点:文件没有下载之前,它也需要保持连接。
iter_content:一块一块的遍历要下载的内容
iter_lines:一行一行的遍历要下载的内容
使用上面两个函数下载大文件可以防止占用过多的内存,因为每次只下载小部分数据。
示例代码:
1 r = requests.get(url_file, stream=True) 2 f = open("file_path", "wb") 3 # chunk是指定每次写入的大小,每次只写了512byte 4 for chunk in r.iter_content(chunk_size=512): 5 if chunk: 6 f.write(chunk)
46,scrapy如何实现限速?
在settings里面,
DOWNLOAD_DELAY = 0.25 # 250 ms of delay
47,scrapy如何实现暂停爬虫程序?
实现暂停与重启记录状态
方法一:
1、首先cd进入到scrapy项目里(当然你也可以通过编写脚本Python文件直接在pycharm中运行)
2、在scrapy项目里创建保存记录信息的文件夹
3、执行命令:
scrapy crawl 爬虫名称 -s JOBDIR=保存记录信息的路径
如:scrapy crawl cnblogs -s JOBDIR=zant/001
执行命令会启动指定爬虫,并且记录状态到指定目录
爬虫已经启动,我们可以按键盘上的ctrl+c停止爬虫,停止后我们看一下记录文件夹,会多出3个文件,其中的requests.queue文件夹里的p0文件就是URL记录文件,这个文件存在就说明还有未完成的URL,当所有URL完成后会自动删除此文件
当我们重新执行命令:scrapy crawl cnblogs -s JOBDIR=zant/001 时爬虫会根据p0文件从停止的地方开始继续爬取。
方法二:
在settings.py文件里加入下面的代码:
JOBDIR='sharejs.com'
使用命令scrapy crawl somespider,就会自动生成一个sharejs.com的目录,然后将工作列表放到这个文件夹里
48,scrapy如何进行自定制指令?
单爬虫运行
代码:
1 import sys 2 from scrapy.cmdline import execute 3 4 if __name__ == '__main__': 5 execute(["scrapy","crawl","chouti","--nolog"])
同时运行多个爬虫
步骤如下:
- 在spiders同级创建任意目录,如:commands
- 在其中创建 crawlall.py 文件 (此处文件名就是自定义的命令)
- 在settings.py 中添加配置 COMMANDS_MODULE = '项目名称.目录名称'
- 在项目目录执行命令:scrapy crawlall
代码:
1 from scrapy.commands import ScrapyCommand 2 from scrapy.utils.project import get_project_settings 3 4 class Command(ScrapyCommand): 5 6 requires_project = True 7 8 def syntax(self): 9 return '[options]' 10 11 def short_desc(self): 12 return 'Runs all of the spiders' 13 14 def run(self, args, opts): 15 spider_list = self.crawler_process.spiders.list() 16 for name in spider_list: 17 self.crawler_process.crawl(name, **opts.__dict__) 18 self.crawler_process.start() 19 20 crawlall.py
49,scrapy如何实现记录爬虫的深度?
通过scrapy.CrawlSpider
50,scrapy中的pipelines工作原理?
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item。
每个Item Pipeline都是实现了简单方法的Python类,比如决定此Item是丢弃而存储。以下是item pipeline的一些典型应用:
- 验证爬取的数据(检查item包含某些字段,比如说name字段)
- 查重(并丢弃)
- 将爬取结果保存到文件或者数据库中
51,简述scrapy爬虫中间件和下载中间件的作用?
52,scrapy-redis组件的作用?
- scheduler - 调度器
- dupefilter - URL去重规则(被调度器使用)
- pipeline - 数据持久化
53,scrapy-redis组件中如何实现任务的去重?
- dupefilter - URL去重规则(被调度器使用)
54,scrapy-redis的调度器如何实现任务的深度优先和广度优先?
55,手写正则匹配邮箱,手机号,一段html内容
56,robots协议是什么?
Robots协议(也称为爬虫协议、机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。
57,常见的http状态码?
1 一些常见的状态码为: 2 200 - 服务器成功返回网页 3 404 - 请求的网页不存在 4 503 - 服务不可用 5 详细分解: 6 1xx(临时响应) 7 表示临时响应并需要请求者继续执行操作的状态代码。 8 9 代码 说明 10 100 (继续) 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。 11 101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。 12 13 2xx (成功) 14 表示成功处理了请求的状态代码。 15 16 代码 说明 17 200 (成功) 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。 18 201 (已创建) 请求成功并且服务器创建了新的资源。 19 202 (已接受) 服务器已接受请求,但尚未处理。 20 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 21 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。 22 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。 23 206 (部分内容) 服务器成功处理了部分 GET 请求。 24 3xx (重定向) 25 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。 26 27 代码 说明 28 300 (多种选择) 针对请求,服务器可执行多种操作。服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 29 301 (永久移动) 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 30 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 31 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。 32 304 (未修改) 自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。 33 305 (使用代理) 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理。 34 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 35 4xx(请求错误) 36 这些状态代码表示请求可能出错,妨碍了服务器的处理。 37 38 代码 说明 39 400 (错误请求) 服务器不理解请求的语法。 40 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 41 403 (禁止) 服务器拒绝请求。 42 404 (未找到) 服务器找不到请求的网页。 43 405 (方法禁用) 禁用请求中指定的方法。 44 406 (不接受) 无法使用请求的内容特性响应请求的网页。 45 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。 46 408 (请求超时) 服务器等候请求时发生超时。 47 409 (冲突) 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。 48 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。 49 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 50 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 51 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 52 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 53 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。 54 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。 55 417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求. 56 5xx(服务器错误) 57 这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。 58 59 代码 说明 60 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 61 501 (尚未实施) 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。 62 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 63 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。 64 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 65 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。 66 HttpWatch状态码Result is 67 200 - 服务器成功返回网页,客户端请求已成功。 68 302 - 对象临时移动。服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 69 304 - 属于重定向。自上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。 70 401 - 未授权。请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 71 404 - 未找到。服务器找不到请求的网页。 72 2xx - 成功。表示服务器成功地接受了客户端请求。 73 3xx - 重定向。表示要完成请求,需要进一步操作。客户端浏览器必须采取更多操作来实现请求。例如,浏览器可能不得不请求服务器上的不同的页面,或通过代理服务器重复该请求。 74 4xx - 请求错误。这些状态代码表示请求可能出错,妨碍了服务器的处理。 75 5xx - 服务器错误。表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
58,http的请求和响应都包含哪些内容?
1 每个HTTP请求和响应都会带有相应的头部信息。默认情况下,在发送XHR请求的同时,还会发送下列头部信息: 2 3 Accept:浏览器能够处理的内容类型 4 Accept-Charset:浏览器能够显示的字符集 5 Accept-Encoding:浏览器能够处理的压缩编码 6 Accept-Language:浏览器当前设置的语言 7 Connection:浏览器与服务器之间连接的类型 8 Cookie:当前页面设置的任何Cookie 9 Host:发出请求的页面所在的域 10 Referer:发出请求的页面的URL 11 User-Agent:浏览器的用户代理字符串 12 例如:chrome下的请求头信息: 13 14 : 15 16 虽然不同浏览器实际发送的头部信息会有所不同,但以上列出的基本上是浏览器都会发送的,用setRequestHeader()方法也可以设置请求头信息,该函数接受两个参数:头部字段的名称和头部字段的值。要成功发送请求头部信息,需在调用open方法之后且调用send方法之前调用。 17 18 19 20 HTTP响应头部信息: 21 22 Date:表示消息发送的时间,时间的描述格式由rfc822定义 23 server:服务器名字。 24 Connection:浏览器与服务器之间连接的类型 25 content-type:表示后面的文档属于什么MIME类型 26 Cache-Control:控制HTTP缓存 27 以上是基本常见的信息 28 29 30 31 以上Expires 头部字段提供一个日期和时间,响应在该日期和时间后被认为失效