Request请求对象的里有data参数,它就是用在POST里的,我们要传送的数据就是这个参数data,data是一个字典,里面要匹配键值对。
POST请求:代码模板
导入request模块
import urllib.request
代码模板
# 首先对data进行转码,转化成str类型
data = urllib.parse.urlencode(data)
# post请求只支持byte类型,所以要进行再次编码
data = data.encode('utf-8')
# 对url和参数进行包装
new_url = urllib.request.Request(url,data)
response = urllib.request.urlopen(new_url)
# 读取响应结果
response = result.read()
# 对响应结果解码
print(response.decode("utf8"))
POST请求:注意事项
注意:headers的一些属性:
- Content-Length: 144: 是指发送的表单数据长度为144,也就是字符个数是144个。
- X-Requested-With: XMLHttpRequest :表示Ajax异步请求。
- Content-Type: application/x-www-form-urlencoded : 表示浏览器提交 Web 表单时使用,表单数据会按照 name1=value1&name2=value2 键值对形式进行编码。
注意:User-Agent
- 每家都有门,你以一个路人的身份直接闯进去显然不是很礼貌。同理,一些站点不喜欢被程序(非人为访问)访问,有可能会拒绝你的访问请求。
- 但是如果我们用一个合法的身份去请求别人网站,显然人家就是欢迎的,所以我们就应该给我们的这个代码加上一个身份,就是所谓的User-Agent头。
- 浏览器 就是互联网世界上公认被允许的身份,如果我们希望我们的爬虫程序更像一个真实用户,那我们第一步,就是需要伪装成一个被公认的浏览器。用不同的浏览器在发送请求的时候,会有不同的User-Agent头。 urllib2默认的User-Agent头为:Python-urllib/x.y(x和y是Python主版本和次版本号,例如 Python-urllib/2.7)
- 完整的headers
# 完整的headers
headers = {
"Accept" : "application/json, text/javascript, */*; q=0.01",
"X-Requested-With" : "XMLHttpRequest",
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
}
注意:CA认证
- 现在随处可见 https 开头的网站,urllib可以为 HTTPS 请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问,如:https://www.baidu.com/等...
- 如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。(据说 12306 网站证书是自己做的,没有通过CA认证)
- urllib在访问的时候则会报出SSLError:
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>
所以,如果以后遇到这种网站,我们需要单独处理SSL证书,让程序忽略SSL证书验证错误,即可正常访问。
1.使用ssl创建未经验证的上下文,在urlopen中传入上下文参数
import ssl
import urllib2
context = ssl._create_unverified_context()
print urllib2.urlopen("https://www.12306.cn/mormhweb/", context=context).read()
2. 全局取消证书验证
import ssl
import urllib2
ssl._create_default_https_context = ssl._create_unverified_context
print urllib2.urlopen("https://www.12306.cn/mormhweb/").read()
Post方式爬取AJAX加载的数据
有些网页内容使用AJAX加载,只要记得,AJAX一般返回的是JSON,直接对AJAX地址进行post或get,就返回JSON数据了。
我们这里以豆瓣电影为例。
导入request
import ssl
import urllib.request
from urllib import parse
User-Agent头,模拟浏览器
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
组装请求数据
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
formdata = {
"start": "0",
"limit": "20"
}
data = parse.urlencode(formdata).encode(encoding='UTF8')
获取返回结果
request = urllib.request.Request(url, data=data, headers=headers)
# 返回结果
response = urllib.request.urlopen(request).read()
# utf-8解码
s = response.decode('utf-8', 'ignore')
print("【返回结果】:%s" % s)
完整代码:Python2.7.13
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import ssl
import urllib
import urllib2
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
formdata = {
"start":"0",
"limit":"20"
}
data = urllib.urlencode(formdata)
# 全局取消证书验证
ssl._create_default_https_context = ssl._create_unverified_context
request = urllib2.Request(url, data = data, headers = headers)
print urllib2.urlopen(request).read()
完整代码:Python3.6.1
import ssl
import urllib.request
from urllib import parse
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
formdata = {
"start": "0",
"limit": "20"
}
data = parse.urlencode(formdata).encode(encoding='UTF8')
# 全局取消证书验证
ssl._create_default_https_context = ssl._create_unverified_context
request = urllib.request.Request(url, data=data, headers=headers)
# 返回结果
response = urllib.request.urlopen(request).read()
# utf-8解码
s = response.decode('utf-8', 'ignore')
print("【返回结果】:%s" % s)
问题:为什么有时候POST也能在URL内看到数据?
- GET方式是直接以链接形式访问,链接中包含了所有的参数,服务器端用Request.QueryString获取变量的值。如果包含了密码的话是一种不安全的选择,不过你可以直观地看到自己提交了什么内容。
- POST则不会在网址上显示所有的参数,服务器端用Request.Form获取提交的数据,在Form提交的时候。但是HTML代码里如果不指定 method 属性,则默认为GET请求,Form中提交的数据将会附加在url之后,以?分开与url分开。
- 表单数据可以作为 URL 字段(method="get")或者 HTTP POST (method="post")的方式来发送。比如在下面的HTML代码中,表单数据将因为 (method="get") 而附加到 URL 上: