urllib的使用
一、request模块
http://httpbin.org 是github的http测试的接口。httpbin.org 这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等,且支持 GET、POST 等多种方法,对 web 开发和测试很有帮助。
导入模块:
1、import urllib
使用:urllib.request.
但这样会报错: AttributeError: module 'urllib' has no attribute 'request'
原因:在python3中request被作为一个模块,而不是方法。
解决方法:将request作为一个模块,如import urllib.request。
2、from urllib import request
requset.
1、urlopen()方法:是一个简单发送网络请求的方法。它接收一个字符串格式的 url ,它会向传入的 url发送网络请求,然后返回结果。
参数:
(1)url='' #字符串格式
例:
import urllib
response =urllib.request.urlopen(url='http://httpbin.org/get')
(2)data:是可选的,传入它则会发起POST请求,否则默认会发送get请求。data参数是字节 类型、或者类文件对象或可迭代对象。
import urllib import request
response = request.urlopen(url='http://httpbin.org/post',
data=b'username=wsq&password=123')
用data就是post请求,字节类型,用b''来转换成字节,且data中的数据会作为表单中的数据。
(3)timeout:设置超时时间,以秒为单位。如果请求超过设置时间,则抛出异常;若没有指定 则用系统默认设置。timeout参数只对 http、https以及ftp连接起作用。
报错会出现:urllib.error.URLError:
from urllib
response =urllib.request.urlopen(url='http://www.baidu.com',
timeout=0.1)
2、Request类:
解释:利用urlopen()可以发起最基本的请求,但这几个参数不足以构件一个完整的请求,可以利用 Request对象来构建更加完整的请求。
(1) 请求头添加:
from urllib import request
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0"
} #注意:一定是字典形式。
req = request.Request(url='http://www.baidu.com',headers = headers)
reponse = request.urlopen(req)
Referer:这个涉及防盗链技术,假如爬取一个图片出现403,在请求头里添加上它,大多数都 可以解决。
(2) 操作Cookie。(但不会用它操作,日后常用request)
(3) 设置代理:自己写个代理库。(间接请求,保护自己的IP地址)
(4) 验证:
3、Response对象:
urllib库中的类或者方法,在发送网络请求后,都会返回一个urllib.response的对象(例如: http.client.HTTPResponse object at ......)
它包含了请求回来的数据结果。它包含一些属性和方法,供我们处理返回的结果。
(1)、read():获取响应返回的数据,只能用一次。和文件句柄一样,只能运行一次。#返回的是字节码,decode() 解码成字符串。
(2)、readline():读取一行。没必要。
while True:
data = response.readline()
if data:
print(data)
(3)、info():获取响应头信息。 print(response.info())
(4)、geturl():获取访问的url。 print(response.geturl())
(5)、getcode() :返回状态码。 print(response.getcode())
二、parse模块
parse模块是一个工具模块,提供了需要对url处理的方法,用于解析url。
注意: url中只能包含ascii字符,在实际操作过程中,get请求通过url传递的参数中会有大量特殊字符 (非ascii字符),例如汉字,那么就需要进行url编码。(一个中文用UTF-8有3个字节。)
导包:from urllib import parse(import urllib不行问题同上)
方法:
1、parse.quote():编码
例: url = 'http://httpbin.org/get?username={}'
result = url.format(parse.quote('思齊')) #format方法别忘了
print(result)
结果为: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A
2、parse.unquote():反编码,看看具体参数是什么。
例1:
print(parse.unquote(result))
结果为: http://httpbin.org/get?username=思齊
3、parse.urlencode():在发送请求时,往往会需要传递很多的参数,如果用字符串拼接会很麻 烦,该方法就是用来拼接url参数的。
例1: args = {'username':'思齊','password':'小淘'}
res = parse.urlencode(args) #注意字典形式
print(res)
结果为: username=%E6%80%9D%E9%BD%8A&pd=123
例2:
args = {'username':'思齊','pd':'123'}
result = 'http://httpbin.org/get?{}'.format(parse.urlencode(args))
print(res)
结果为: http://httpbin.org/get?username=%E6%80%9D%E9%BD%8A&pd=123
注:url中规定多个参数 & 连接。
4、parse.parse_qs(): 和parse.urlencode()是相反的,将它转会字典。
例:print(parse.parse_qs(res))
结果为:{'username': ['思齊'], 'pd': ['123']}
{'http://httpbin.org/get?username': ['思齊'], 'pd': ['123']}
错误信息:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) #当出现这种错误时就是参数用的不是ascii码。
三、error模块
error模块主要负责异常处理,如果请求出现错误,我们可以用error模块进行处理,该模块主要包含
URLError和HTTPError
导包:from urllib import error
1.URLError:是error模块的基类,由request模块产生的的异常都可以用这个类来处理。
2.HTTPError:是的子类,主要包含三个属性:code:请求的状态码、reason:错误的原因、headers: 响应的报头。
例:
try:
request.urlopen('https://www.jianshu.com')#不是合法的用户会被 ban。
except error.HTTPError as e:
print(e.code)
print(e.reason)
print(e.headers)
四、robotparse模块
robotparse模块主要负责处理爬虫协议文件,robots.txt的文件。
导包:from urllib import robotparse
https://www.amazon.cn/robots.txt #亚马逊中国的爬虫协议,如图1
urllib3的使用
介绍:是一个基于python3的功能强大,友好的http客户端。
保证线程安全(不需考虑锁的问题),连接池保持(而不向之前的一样连一下关一下),支持重复请求、重定位,保证代码百分百被使用。
导包:import urllib3
(1)构造请求(request):
1.实例化一个PoolManager对象构造请求,这个实例对象处理了连接池和线程安全的所有细节,所以我们不用自行处 理。
例: http = urllib3.PoolManager()
在这里我出现了一个错误,如下:
AttributeError: module 'urllib3的使用' has no attribute 'PoolManager',我出现 这个原因是py文件所在的文件夹命名为urllib3。
2.用request()方法发送请求,可以用request()方法发送任意请求,GET POST....
第一个参数是何种类型的请求;第二个参数是请求的网站。
例1:发送get请求
response = http.request('GET','http://httpbin.org/get ',b'User- Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64rv:73.0) Gecko/20100101 Firefox/73.0')
此处传的二进制数据报错
例2:发送POST请求
response = http.request('POST','http://httpbin.org/post',
fields={'hello':'world'})
3.请求传入数据(data):
Headers:加入请求头
在request方法中添加字典格式的headers参数来指定请求头。
例:http = urllib3.PoolManager()
response = http.request('POST','http://httpbin.org/get ',
headers={'key':'value'})Query parameters(字符串参数):
*get,head,delete请求,可通过提供字典类型的参数fields来添加查询参数。(复习一 下:在urllib中我们通过parse.quote()编码这里只需提供fields参数即可)
例:http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/get ',
fields={'key':'value'})
*对于post,put请求,如果需要查询参数,需要通过url编码将参数编码正确格式再拼接到url中。
例: 如图1、2、3
import urllib3
import urllib.parse import urlencode
import json
http = urllib3.PoolManager()
args = {'username':'思齊','password':'小淘'}
方法一:
result = urlencode(args)
url = 'http://httpbin.org/post?' + result #字符串拼接
方法二:
url1 = 'http://httpbin.org/post?{}'
url1 = url.format(parse.urlencode(args))
response = http.request('POST',url)
print(json.loads(response.data.decode('utf-8')))
*form data(表单数据):
对于post,put,需要提供字典类型的参数fields来传递form表单数据。
response = http.request('post','http://httpbin.org/get ',
fields={'key':'value'})
*json数据
当我们需要发送json数据时,我们需要在request方法中传入编码后的二进制数据类型的body参数,并 指定Content-Type的请求头。
*文件上传(通常不用这个上传)
对于文件上传,我们可以模仿浏览器表单的方式
对于二进制数据上传,我们用指定body的方式,并设置Content-Type的请求头。
*注意:get,head,delete请求中提供fields参数会自动拼接到url中,而对post,put请求中你提供的 fields参数会填写到form表单中,若你想拼接到url中只能主动的使用字符串拼接的方法。
(2)http响应对象提供 status、data、headers等属性
例1:
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/get')
print(type(response))#返回的是
也就是http响应对象
print(response.data) #返回的是二进制数据
print(response.headers)#返回的是
字典形式,因此可以通过键名看键值
print(response.status)
(3)返回的是 json格式数据 可以通过json模块,loads为字典数据类型。
例:
import urllib3
import json
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/ip')
print(json.load(response.data.decode('utf-8')))
// response.data.decode('utf-8') 解码成字符串。
(4)返回的数据都是字节类型,对于大量的数据我们通过stream(流)来处理更好,也可以当作一个文件对象来处理。
例1:流
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024',
preload_content = False)
for i in response.stream(32): #一点点读对内存好,下图片就可以用这种方法
print(i)
例2:文件对象
import urllib3
http = urllib3.PoolManager()
response = http.request('get','http://httpbin.org/bytes/1024', preload_content = False)
for line in response: #比如说大文件可能5G大小,不能一次性回来,一批一批的回来
print(line)
(5)代理
例1:import urllib3
proxy = urllib3.ProxyManager('http://ip:端口号')
//用这个ip来帮助你来向某网站发送请求,保护了你自己的ip地址不被暴露。
response = proxy.request('get','http://httpbin.org/ip')
//http://httpbin.org/ip 查看请求的ip地址
print(response.data)
//遇到如下错误urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='115.210.79.22', port=8118): Max retries exceeded with url: http://httpbin.org/ip (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('