get请求和post请求的区别、使用Request模块进行get请求和post请求、上传图片的post请求、爬虫登陆Cookies、使用Session登录、爬虫下载文件的几种方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgcr654321/article/details/82831629

get请求和post请求的区别:

超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。HTTP 的工作方式是客户机与服务器之间的请求-应答协议。web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。

URL全称是资源描述符,一个URL地址用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。

我们最常用的是GET和POST请求。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。即GET是向服务器发索取数据的一种请求,而POST是向服务器提交数据的一种请求 。

GET请求:

使用GET方法时,查询字符串(键值对)被附加在URL地址后面一起发送到服务器。

如:

/test/demo_form.jsp?name1=value1&name2=value2 #后面name1及之后内容是查询字符串

POST请求:

使用POST方法时,查询字符串在POST信息中单独存在,和HTTP请求一起发送到服务器。

如:

POST/test/demo_form.jsp HTTP/1.1

Host:w3schools.com

name1=value1&name2=value2 # 这是查询字符串

GET和POST的区别:

 

GET

POST

点击返回/刷新按钮

没有影响

数据会重新发送(浏览器将会提示用户“数据被从新提交”)

添加书签

可以

不可以

缓存

可以

不可以

编码类型(Encoding type)

application/x-www-form-urlencoded

application/x-www-form-urlencoded or multipart/form-data. 请为二进制数据使用multipart编码

历史记录

没有

长度限制

没有

数据类型限制

只允许ASCII字符类型

没有限制。允许二进制数据

安全性

查询字符串会显示在地址栏的URL中,不安全,请不要使用GET请求提交敏感数据

因为数据不会显示在地址栏中,也不会缓存下来或保存在浏览记录中,所以看POST求情比GET请求安全,但也不是最安全的方式。如需要传送敏感数据,请使用加密方式传输

可见性

查询字符串显示在地址栏的URL中,可见

查询字符串不会显示在地址栏中,不可见

上面这些并不是HTTP的GET和POST两者请求的本质区别,这些区别是建立在HTML标准对于HTTP协议的用法的约定之上的。

注意:

GET和POST与数据如何传递没有关系:

GET和POST是由HTTP协议定义的。在HTTP协议中,使用哪个Method与应用层的数据如何传输是没有相互关系的。HTTP没有要求,如果Method是POST数据就要放在BODY中。也没有要求,如果Method是GET,数据(参数)就一定要放在URL中而不能放在BODY中。实际上这种做法只是HTML标准对HTTP协议的用法的约定。现代的Web Server都是支持GET中包含BODY这样的请求,虽然这种请求不可能从浏览器发出。

HTTP协议对GET和POST都没有对长度的限制:

HTTP协议明确地指出HTTP头和Body都没有长度的要求。对于URL长度上的限制,有两方面的原因:

某些浏览器的限制;

服务器的限制:多数服务器出于安全、稳定方面的考虑,会给URL长度加限制,但是这个限制是针对所有HTTP请求的,与GET、POST没有关系。

安全不安全和GET、POST没有关系:

这个不用多解释,无论GET还是POST都有办法抓包破解信息。

使用Request模块进行get请求和post请求:

Python 的自带模块 urllib, 可以用来提交get请求,下载网页内容。但我们平常使用的网页更多的是使用get请求和post请求,对于这两种请求,我们就要使用requests模块来处理了。

get和post的应用场景:

post请求:账号登录;搜索内容;上传图片;上传文件;往服务器传数据等。

get请求:正常打开网页,往服务器传数据。

使用requests模块进行get请求:

如我们想模拟一下百度的搜索。首先观察一下,比如我们在百度搜索框中写上 “莫烦python”, 我们发现它弹出了一串这么长的网址:https://www.baidu.com/s?wd=%E8%8E%AB%E7%83%A6python&ie=UTF-8

我们可以发现,把com后面改成/s?wd=莫烦python,搜索结果仍然相同。

因此, “/s?wd=莫烦python” 这就是我们进行个性化搜索需要的关键信息。

我们把网址分成两个部分,前面固定不变的部分是“http://www.baidu.com/s?”,后面变化的部分定义成参数param。通过对参数赋不同的值,然后把参数传入,形成新的个性化搜索网址,然后把网址传入 然后传入 requests.get() 功能,我们就可以实现个性化搜索。webbrowser模块用来打开一个你的默认浏览器, 观看你是否在百度的搜索页面。

import requests
import webbrowser

# webbrowser模块是为了让你看到这个请求过程和结果

param = {"wd": "莫烦Python"}
# 个性化搜索所需信息
r = requests.get('http://www.baidu.com/s', params=param)
# 组合形成个性化搜索的网址,并传入requests.get()方法中
print(r)
# r接收到的requests.get()返回值200表示正常打开网页
print(r.url)
# 打印出我们get的网页地址
webbrowser.open(r.url)
# 浏览器打开这个地址

运行结果如下:

<Response [200]>
http://www.baidu.com/s?wd=%E8%8E%AB%E7%83%A6Python

Process finished with exit code 0

使用requests模块进行post请求:

在这个网页http://pythonscraping.com/pages/files/form.html中,我们可以提交姓名,然后网页会返回一个包含你提交内容的信息,如:

注意这里只是一个展示,实际上大多数情况下,你post过去的信息是交给服务器内部处理的,不是用来显示在网址上的。

观察网页的源代码:

<h2>Tell me your name!</h2>
<form method="post" action="processing.php">
First name: <input type="text" name="firstname"><br>
Last name: <input type="text" name="lastname"><br>
<input type="submit" value="Submit" id="submit">
</form>

然后发现我们填入姓名的地方原来是在一个 <form> 里面。这个 <form> 里面有几个<input>  tag, 我们可以看到有两个 <input> 里面的值 name="firstname" 和 name="lastname",这两个就是我们要 post 提交上去的信息。

我们填好姓名, 选择 Network, 勾选 Preserve log, 再点击 “submit”, 我们可以观察到我们提交的post请求。

该.php文件中内容如下:

General

Request URL:http://pythonscraping.com/pages/files/processing.php
Request Method:POST
Status Code:200 OK
Remote Address:198.27.68.184:80
Referrer Policy:no-referrer-when-downgrade
Response Headers

Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8
Date:Mon, 24 Sep 2018 07:40:03 GMT
Keep-Alive:timeout=5, max=100
Server:Apache
Transfer-Encoding:chunked
Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.9
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:26
Content-Type:application/x-www-form-urlencoded
Host:pythonscraping.com
Origin:http://pythonscraping.com
Referer:http://pythonscraping.com/pages/files/form.html
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Form Data

firstname:111
lastname:222

这些数据中包含了:

Request URL (post请求要用的 URL);

Request Method (post);

Form Data (post 去的信息),可以观察到我们提交的111和222信息也在里面。

现在我们用Python 来模拟这一次提交post请求登录Cookies。

我们把 'firstname' 和 'lastname'信息组织成一个 python 字典,然后把这个字典传入 requests.post()。

注意,:

这里的 post 里面的 url, 不是我们填表时的 url (http://pythonscraping.com/pages/files/form.html), 而是要把 Form 信息提交去的那个网页, 也就是上图中查看到的 Request URL (http://pythonscraping.com/files/processing.php)。

import requests

data = {'firstname': '莫烦', 'lastname': '周'}
r = requests.post('http://pythonscraping.com/pages/files/processing.php', data=data)
# 要post过去的data是上面定义的字典
print(r.text)

运行结果如下:

Hello there, 莫烦 周!

上传图片的post请求:

传照片也是 post请求的一种。

http://pythonscraping.com/files/form2.html我们使用这个网页来上传照片。

网页源代码如下:


<h2>Upload a file!</h2>
<form action="../pages/files/processing2.php" method="post" enctype="multipart/form-data">
  Submit a jpg, png, or gif: <input type="file" name="uploadFile"><br>
  <input type="submit" value="Upload File">
</form>

我们可以发现有 <input> 对象里是一个叫 uploadFile 的名字. 我们将这个名字记作为key放入 python 的字典中。接着在字典中, 使用 open打开一个图片文件, 当做要上传的文件。把这个字典放入你的 post里面的 files 参数,就能上传你的图片了, 网页会返回一个页面, 将你的图片名显示在上面。

如:

import requests

file = {'uploadFile': open('./1.png', 'rb')}
r = requests.post('http://pythonscraping.com/pages/files/processing2.php', files=file)
print(r.text)

运行结果如下:

uploads/1.png
The file 1.png has been uploaded.

爬虫登陆Cookies:

我们使用这个网页来模拟登陆:http://pythonscraping.com/pages/cookies/login.html

先手动试一下:

登陆后转到下面这个网页:

登陆账号时,浏览器做了以下工作:

使用 post 方法登录了上面画红线的url;

post 的时使用了Form data中的用户名和密码;

生成了一些 cookies。

什么是cookies:

cookies就是用来保存你登陆这个网站的登陆信息,当我访问这个网站中的不同页面时,保存的cookies将被调用,服务器将知道我之前是否登录,以哪个账号登录的,从而给我相应的权限。

cookies的传递:

用 requests.post + payload 的用户信息发给网页, 返回的 r 里面会有生成的 cookies 信息. 接着我请求去登录后的页面时, 使用 request.get, 并将之前的 cookies 传入到 get 请求. 这样就能已登录的名义访问 get 的页面。

如:

import requests

payload = {'username': 'morvan', 'password': 'password'}
r = requests.post('http://pythonscraping.com/pages/cookies/welcome.php', data=payload)
print(r.cookies.get_dict())
r = requests.get('http://pythonscraping.com/pages/cookies/welcome.php', cookies=r.cookies)
print(r.text)

运行结果如下:

{'loggedin': '1', 'username': 'morvan'}

<h2>Welcome to the Website!</h2>
You have logged in successfully! <br><a href="profile.php">Check out your profile!</a>

Process finished with exit code 0

使用Session登录:

每次像上面这样传递cookies很麻烦,requests中提供了一个很方便的功能就是Session,它可以自动帮我们传递这些cookies信息。创建完一个 session 过后, 我们直接只用 session 来 post 和 get。而且这次 get 的时候, 我们并没有传入 cookies. 但是实际上 session 内部就已经有了之前的 cookies 了。

如:

import requests

session = requests.Session()
payload = {'username': 'morvan', 'password': 'password'}
r = requests.post('http://pythonscraping.com/pages/cookies/welcome.php', data=payload)
print(r.cookies.get_dict())
r = requests.get('http://pythonscraping.com/pages/cookies/welcome.php')
print(r.text)

运行结果如下:

{'loggedin': '1', 'username': 'morvan'}

<h2>Welcome to the Website!</h2>
Whoops! You logged in wrong. Try again with any username, and the password "password"<br><a href="login.html">Log in here</a>

Process finished with exit code 0

爬虫下载文件的几种方式:

我们以这个链接为例:https://morvanzhou.github.io/learning-steps/

打开该链接,鼠标移动到图片上,右键审查元素,如下图:

我们发现这张图片被存放在/static/img/description/learning_step_flowchart.png" 这个网页, 注意这个地址开头是 /, 并不是完整的网址, 它是在 “https://morvanzhou.github.io/” 下面的网址。我们还要将其补全, 才能在网址栏中找到这个图片地址。补全后为:

https://morvanzhou.github.io/static/img/description/learning_step_flowchart.png

然后我们把这个图片下载下来。

import os
from urllib.request import urlretrieve
import requests

os.makedirs('./img/', exist_ok=True)
# 创建一个空文件夹用于存放图片
IMAGE_URL = "https://morvanzhou.github.io/static/img/description/learning_step_flowchart.png"
urlretrieve(IMAGE_URL, './img/image1.png')
# 用urlretrieve下载链接的内容,并放置和命名。
# 或者也可以用get方式下载文件
r = requests.get(IMAGE_URL)
with open('./img/image2.png', 'wb')as f:
	f.write(r.content)
# 打开文件并写入方式
# 上面两种是把文件完整地下载到内存后再写入本地磁盘,如果
# 文件很大,下面一种方式支持边下载边写入磁盘
r2 = requests.get(IMAGE_URL, stream=True)
with open('./img/image3.png', 'wb')as f:
	for chunk in r.iter_content(chunk_size=32):
		f.write(chunk)
# 每下载满32B就写入文件

运行截图如下,三种方式均下载了文件。

练习:下载国家地理杂志美图

用于爬取的页面:http://www.ngchina.com.cn/animals/

随便查看了几张图的审查元素,发现它们都存在于img_list 的这种 <ul> 中。

我们只要找到带有 img_list 的这种 <ul>, 然后在 <ul> 里面找 <img>。然后提取 <img> 的 src 属性, 里面的就是图片的网址。然后把它们下载下来即可。

from bs4 import BeautifulSoup
import requests

URL = "http://www.ngchina.com.cn/animals/"
html = requests.get(URL).text
# 获取网页全部代码
soup = BeautifulSoup(html, 'lxml')
# 使用BeautifulSoup分析代码,分解代码为各个部分
img_ul = soup.find_all('ul', {"class": "img_list"})
# 寻找代码中所有ul中class为img_list的部分
for ul in img_ul:
	imgs = ul.find_all('img')
	# 每一个ul中的所有img对象赋给imgs
	for img in imgs:
		url = img['src']
		# 每个img对象中的每一个img的链接提取出来
		r = requests.get(url, stream=True)
		# 下载该链接对应的图片
		image_name = url.split('/')[-1]
		# 用链接/的最后一部分给图片命名
		with open('./img/%s' % image_name, 'wb')as f:
			for chunk in r.iter_content(chunk_size=128):
				f.write(chunk)
			# 每下载128B就存入文件中
		print('Saved %s' % image_name)
	# 报告下载完成的图片名

运行截图如下,可以看到所有这种命名格式链接的图片都被下载下来了。

猜你喜欢

转载自blog.csdn.net/zgcr654321/article/details/82831629