HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
以下是 HTTP 请求/响应的步骤:
(1)客户端连接Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接.
(2)发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、首部行、空行和实体体4部分组成。
(3)服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源副本写到TCP套接字,由客户端读取。一个响应由状态行、首部行、空行和实体体4部分组成。
(4)释放TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
(5)客户端浏览器解析服务器返回的HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
2. GET方法和POST方法的区别GET和POST本质上就是TCP连接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
(1)使用时最直观的区别
最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。
(2)为什么get比post更快
a. post请求包含更多的请求头
因为post需要在请求的body部分包含数据,所以会多了几个数据描述部分的首部字段(如:content-type),这其实是微乎其微的。
b. 最重要的一条,post在真正接收数据之前会先将请求头发送给服务器进行确认,然后才真正发送数据
在这里插入图片描述
3. 面试一般是怎么回答GET和POST的区别的参考资料:
《计算机网络自顶向下方法》
二、分别通过GET、POST方法获取页面内容 1. python3 requests模块学习requests库是一个常用的用于http请求的模块,它使用python语言编写,基于urllib,可以方便的对网页进行爬取,相较于urllib更加简洁高效,是学习python爬虫的较好的http请求模块。
(1)发送简单的请求
import requests
r = requests.get('https://github.com/Ranxf') # 最基本的不带参数的get请求
r1 = requests.get(url='http://dict.baidu.com/s', params={'wd': 'python'}) # 带参数的get请求
使用该方式使用以下方法
requests.get(‘https://github.com/timeline.json’) # GET请求 requests.post(“http://httpbin.org/post”) # POST请求 requests.put(“http://httpbin.org/put”) # PUT请求 requests.delete(“http://httpbin.org/delete”) # DELETE请求 requests.head(“http://httpbin.org/get”) # HEAD请求 requests.options(“http://httpbin.org/get” ) # OPTIONS请求
(2)为url传递参数
import requests
url_params={'key':'value'} #字典传递参数,如果值为None的键不会被添加到url中
res=requests.get("http://www.xazlsec.com",params=url_params)
print(res.url)
>>>https://www.xazlsec.com/?key=value
(3)响应的内容
print(res.encoding) #获取当前的编码 print(res.text) #以encoding解析返回内容。字符串方式的响应体,会自动根据响应头部的字符编码进行解码。 print(res.content) #以字节形式(二进制)返回。字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩。 print(res.headers) #以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None print(res.status_code) #响应状态码
(4)自定义请求头和cookie信息
url="http://www.xazlsec.com"
header = {'user-agent': 'my-app/0.0.1'}
cookie = {'key':'value'}
res=requests.get(url,headers=header,cookies=cookie)
url="http://www.xazlsec.com"
data = {'some': 'data'}
headers = {'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
res=requests.post(url,data=data,headers=headers)
print(res.text)
(5)响应
r.headers #返回字典类型,头信息 r.requests.headers #返回发送到服务器的头信息 r.cookies #返回cookie r.history #返回重定向信息,当然可以在请求是加上allow_redirects = false 阻止重定向
(6)设置超时
r = requests.get('url',timeout=1) #设置秒数超时,仅对于连接有效
(7)会话对象,能够跨请求保持某些参数
s = requests.Session()
s.auth = ('auth','passwd')
s.headers = {'key':'value'}
r = s.get('url')
r1 = s.get('url1')
(8)设置代理
proxies = {'http':'ip1','https':'ip2' }
requests.get('url',proxies=proxies)
汇总:
# HTTP请求类型
# get类型
r = requests.get('https://github.com/timeline.json')
# post类型
r = requests.post("http://m.ctrip.com/post")
# put类型
r = requests.put("http://m.ctrip.com/put")
# delete类型
r = requests.delete("http://m.ctrip.com/delete")
# head类型
r = requests.head("http://m.ctrip.com/head")
# options类型
r = requests.options("http://m.ctrip.com/get")
# 获取响应内容
print(r.content) #以字节的方式去显示,中文显示为字符
print(r.text) #以文本的方式去显示
#URL传递参数
payload = {'keyword': '香港', 'salecityid': '2'}
r = requests.get("http://m.ctrip.com/webapp/tourvisa/visa_list", params=payload)
print(r.url) #示例为http://m.ctrip.com/webapp/tourvisa/visa_list?salecityid=2&keyword=香港
#获取/修改网页编码
r = requests.get('https://github.com/timeline.json')
print (r.encoding)
#json处理
r = requests.get('https://github.com/timeline.json')
print(r.json()) # 需要先import json
# 定制请求头
url = 'http://m.ctrip.com'
headers = {'User-Agent' : 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19'}
r = requests.post(url, headers=headers)
print (r.request.headers)
#复杂post请求
url = 'http://m.ctrip.com'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload)) #如果传递的payload是string而不是dict,需要先调用dumps方法格式化一下
# post多部分编码文件
url = 'http://m.ctrip.com'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
# 响应状态码
r = requests.get('http://m.ctrip.com')
print(r.status_code)
# 响应头
r = requests.get('http://m.ctrip.com')
print (r.headers)
print (r.headers['Content-Type'])
print (r.headers.get('content-type')) #访问响应头部分内容的两种方式
# cookies
url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies['example_cookie_name'] #读取cookies
url = 'http://m.ctrip.com/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies) #发送cookies
#设置超时时间
r = requests.get('http://m.ctrip.com', timeout=0.001)
#设置访问代理
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.100:4444",
}
r = requests.get('http://m.ctrip.com', proxies=proxies)
#如果代理需要用户名和密码,则需要这样:
proxies = {
"http": "http://user:pass@10.10.1.10:3128/",
}
参考资料:
[https://www.cnblogs.com/ranxf/p/7808537.html]:
2. 获取www.xazlsec.com网页内容(1)GET方法
import requests
url="http://www.xazlsec.com"
headers = {'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
res=requests.get(url,headers=headers)
print(res.text)
结果:
(2)POST方法
import requests
url="http://www.xazlsec.com"
data = {'some': 'data'}
headers = {'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
res=requests.post(url,data=data,headers=headers)
print(res.text)
结果:
使用正则将页面中的域名、邮箱等关键信息匹配出来,并进行输出
1. python 正则表达式学习()和[]有本质的区别
()内的内容表示的是一个子表达式,()本身不匹配任何东西,也不限制匹配任何东西,只是把括号内的内容作为同一个表达式来处理,例如(ab){1,3},就表示ab一起连续出现最少1次,最多3次。如果没有括号的话,ab{1,3},就表示a,后面紧跟的b出现最少1次,最多3次。另外,括号在匹配模式中也很重要。这个就不延伸了,LZ有兴趣可以自己查查
[]表示匹配的字符在[]中,并且只能出现一次,并且特殊字符写在[]会被当成普通字符来匹配。例如[(a)],会匹配(、a、)、这三个字符。
所以() [] 无论是作用还是表示的含义,都有天壤之别,没什么联系
以http://home.baidu.com/contact.html为例,提取百度邮箱和联系电话
import requests
import re
mail_pattern=r"S.+:+[w]+@[w.]+" #匹配规则
#m=r'S.+:+[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}.[com,cn,net]{1,3}' 效果同上
phone_pattern=r"S.+:+[d]+-[d]+-[d]+"
url="http://home.baidu.com/contact.html"
res=requests.get(url)
text=res.text #得到页面源代码,注意这里不能用content,会匹配不出来
# 使用正则匹配文档中存在的email地址
email=re.findall(mail_pattern,text)
phone=re.findall(phone_pattern,text)
email=set(email)
phone=set(phone)
print(email)
print(phone)
获取结果如下:



