接着来学习urllib库的一些内容
一、urlopen
在urllib库中,所有和网络请求相关的方法,都被集中到urllib.request模块下面。
因此要首先通过from urllib import request导入,再通过request.xxx使用
from urllib import request
resp = request.urlopen('http://www.baidu.com/')
print(resp.read())
还可以通过request.urlopen??
来查看urlopen中的参数设置
创建一个表示远程url的类文件对象,然后像本地一样操作这个类文件来获取远程数据
(1) url:请求的url
(2) data:请求的data,如果设置了这个值,那么将变成post请求
(3) 返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象,
有read(size),readline,以及getcode等方法
read、readline、readlines用于读取源代码
getcode用于返回识别码
二、urlretrieve
这个函数可以方便的将网页上的一个文件保存到本地
from urllib import request
request.urlretrieve("http://www.baidu.com","baidu.html")
再通过os.listdir()
可以看到该目录下已经多出了一个baidu.html文件
除了这个之外,还可以将图片从网上下载下来
from urllib import request
request.urlretrieve('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1564992132272&di=b16f6f652de004abdb6a90f301209044&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201503%2F24%2F20150324201057_U3EWh.thumb.700_0.jpeg','bai.jpg')
同样通过listdir来查看
三、urlencode&parse_qs(编码与解码)
- urlencode(编码)
urlencode可以把字典数据转换成URL编码的数据
data = {'name':'爬虫基础','greet':'hello world','age':'100'}
qs = parse.urlencode(data)
print(qs)
#结果:name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100
由于urlopen不能识别汉字
若:
from urllib import request
resp = request.urlopen('https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=大白')
print(resp)
会出现UnicodeEncodeError
因此要对大白
进行编码,具体如下
from urllib import request
from urllib import parse
data = {'wd':'大白'}
qs = parse.urlencode(data)
print(qs)
#结果:wd=%E5%A4%A7%E7%99%BD
即编码为%E5%A4%A7%E7%99%BD
再通过字符串的拼接拼起来
resp = request.urlopen('https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&'+qs)
print(resp)
#结果:<http.client.HTTPResponse object at 0x00000164C6BB7198>
- parse_qs(解码)
可将编码后的url参数进行解码
from urllib import parse
qs = 'wd=%E5%A4%A7%E7%99%BD'
print(parse.parse_qs(qs))
#结果:{'wd': ['大白']}
四、urlparse&urlsplit(url解析)
当拿到一个url时,若要对url各个组成部分进行分割,可以选择urlparse或urlsplit进行分割
- urlparse
from urllib import parse
url = ' https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=wd=%E5%A4%A7%E7%99%BD'
result = parse.urlparse(url)
print(result)
#结果:ParseResult(scheme='', netloc='', path=' https://www.baidu.com/baidu', params='', query='tn=monline_3_dg&ie=utf-8&wd=wd=%E5%A4%A7%E7%99%BD', fragment='')
还可以通过关键字来访问特定部分
print(result.query)
#结果:tn=monline_3_dg&ie=utf-8&wd=wd=%E5%A4%A7%E7%99%BD
- urlsplit
from urllib import parse
url = ' https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=wd=%E5%A4%A7%E7%99%BD'
result = parse.urlsplit(url)
print(result)
#结果:SplitResult(scheme='', netloc='', path=' https://www.baidu.com/baidu', query='tn=monline_3_dg&ie=utf-8&wd=wd=%E5%A4%A7%E7%99%BD', fragment='')
通过两个result的对比,可以发现:
urlparse和urlsplit基本是一样的,唯一的区别在于urlparse有params属性,而urlsplit没有
五、Request类
如果想在请求的时候增加一些请求头,那么就必须使用request.Request类来实现
如,若要增加一个User-Agent:
from urllib import request
header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'}
rq = request.Request('http://www.baidu.com/',headers = header)
resp = urlopen(rq)
print(resp.read())
六、ProxyHandle处理器
解决封IP的问题
(1)不使用代理
from urllib import request
resp = request.urlopen('http://httpbin.org/ip')
print(resp.read())
#结果:b'{\n "origin": "113.57.75.184, 113.57.75.184"\n}\n'
(2)使用代理
from urllib import request
url = 'http://httpbin.org/ip'
#1.使用ProxyHandle创建一个handler
#后面要接端口号(PORT)
handler = request.ProxyHandler({'http':'118.25.104.254:1080'})
#2.用创建好的handle来构建一个opener
opener = request.build_opener(handler)
#3.使用opener来发送请求
resp = opener.open(url)
print(resp.read())
#结果:b'{\n "origin": "118.25.104.254, 118.25.104.254"\n}\n'
七、cookie
指某些网站为了分辨用户身份,进行session跟踪而储存在用户本地客户端上的数据。
cookie储存的数据量一般不超过4kb,因此只适用于存储一些小量的数据
格式:
Set-Cookie:NAME = VALUE; Expires/Max-age = DATE; Path = PATH;
Domain = DOMAIN_NAME; SECURE
名字 | 含义 |
---|---|
NAME | cookie的名字 |
VALUE | cookie的值 |
Expires | cookie的过期时间 |
Path | cookie作用的路径 |
Domain | cookie作用的域名 |
SECURE | 是否只在https协议下起作用 |
- http.cookiejar模块:
该模块主要的类有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。
这四个类的作用分别如下:
CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失
FileCookieJar(filename, delayload = None, policy = None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延时访问文件,即只有在需要时才读取文件或在文件中存储数据
MozillaCookieJar(filename, delayload = None, policy = None):从FileCookieJar派生而来,创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例
LWPCookieJar(filename, delayload = None, policy = None):从FileCookieJar派生而来,创建与libwww-per标准的Set-Cookie3文件格式兼容的FileCookieJar实例
- cookie的加载与保存
(1)保存
from urllib import request
from http.cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar('cookie.txt')
handler = request.HTTPCookieProcessor(cookiejar)
opener = request.build_opener(handler)
resp = opener.open('https://www.baidu.com/')
cookiejar.save(ignore_discard = True, ignore_expires = True)
(2)加载
from urllib import request
from http.cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar('cookie.txt')
cookiejar.load()
handler = request.HTTPCookieProcessor(cookiejar)
opener = request.build_opener(handler)
#resp = ...
for cookie in cookiejar:
print(cookie)
由于cookie在过了一段时间后会过期,因此在cookie.save
和cookie.load
中,有两个参数ignore_discard = True
、ignore_expires = True
需要注意下:
ignore_discard = True:即使cookies即将被丢弃也要保存下来
ignore_expires = True:如果cookies已经过期也将它保存并且文件已存在时将覆盖