Python内置HTTP请求库之urllib
其中包含的4个模块:
-request:最基本的HTTP请求模块,用来模拟发送请求
-error:异常处理,如果出现请求错误,可以捕获并进行相关处理
-parse:工具模块,有很多URL处理方法,拆分、解析、合并等
-robotparser:识别网站的robots.txt文件
常用请求方法之urlopen():
-具体形式:
urllib.request.urlopen(url,data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
**timeout参数为可选项**
1.url:待爬取的网页URL
2.data:POST提交的数据,添加此参数要用bytes()将参数值转换为字节流格式(bytes),添加data后,请求方法会改为POST,模拟为表单形式提交。
例:data=bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
1) .urlencode()方法将字典转换为字符串形式('word=hello')
2) encoding=' ' 设置编码格式
3.timeout:用于设置超时时间(秒),如果超出此时间无响应,则抛出异常(urllib.error中的超时异常,URLError),不指定时,使用全局默认时间。
4.context:ssl.SSLContext类型,用来指定SSL设置
5.cafile和capath:指定CA证书和它的路径
6.cadefault:已弃用,默认值为false
urllib.request.Request类:
-用于构建Request请求对象,可添加headers等信息,将对象传入urlopen()方法中,用于设置请求头等
-具体形式:urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)
-参数说明:
1.url:必选,其余可选
2.data:bytes类型,建立字典,使用urllib.parse.urlencode()编码
3.headers:字典型,也可用add_header()添加请求头,修改User-Agent伪装浏览器访问
4.origin_req_host:请求方的host名称或IP地址
5.unverifiable:表示请求是否无法验证,默认为false
6.method:字符串型,请求方式,GET、POST、PUT等
-添加headers的另一种方式:
req=urllib.request.Request(url,data,method='POST')
req.add_header('Uset-Agent','Mozilla/4.0(compatible;MSIE5.5;Windows NT)')
urllib.request.BaseHandler类:
-用于处理登录验证、Cookies、代理设置等的工具类
-相关部分子类:
1.HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常
2.HTTPRedirectHandler:处理重定向
3.HTTPCookieProcessor:处理Cookies
4.ProxyHandler:用于代理设置,默认代理为空
5.HTTPPasswordMgr:用于管理密码,维护了用户名和密码的表
6.HTTPBasicAuthHandler(基础授权处理器):用于管理认证,如果一个链接打开时需要认证,用它解决认证的问题
OpenerDirector类:
-简称为Opener,利用Handler来构建Opener对象,完成一些高级功能。
例:网页打开时,需要验证用户名、密码
from urllib.request import HTTPPasswordMgrWithDefaultRealm,
HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username='username'
password='password'
url='http://localhost:5000/'
p=HTTPPasswordMgrWithDefaultRealm() #创建此类对象,用于设置用户名和密码
p.add_password(None,url,username,password)
auth_handler=HTTPBasicAuthHandler(p)
opener=build_opener(auth_handler)
try:
result=opener.open(url) #open()方法相当于urlopen()
html=result.read().decode('utf-8') #获取验证后的网页源码并设置编码格式
print(html)
except URLError as e:
print(e.reason) #reason用于打印错误原因
例:代理的设置
from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
#创建一个代理处理器,可添加多个代理,字典型,键为协议,值为url
proxy_handler=ProxyHandler({'http':'http://127.0.0.1:9743',
'https':'https://127.0.0.1:9743'})
opener=build_open(proxy_handler) #用代理handler对象构建Opener
try:
r=opener.open('https://www.baidu.com')
print(r.read().decode('utf-8'))
except URLError as e:
print(e.reason)
例:Cookie的获取
import http.cookiejar,urllib.request
cookie=http.cookiejar.CookieJar()
handler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handler)
r=opener.open('http://www.baidu.com')
for item in cookie:
print(item.name+'='+item.value)
-Cookies可保存为文件形式:
1.Mozilla型浏览器的Cookies格式:http.cookie.MozillaCookieJar()
2.libwww-perl(LWP)格式的Cookies文件:http.cookiejar.LWPCookieJar()
urllib.error模块:
-异常处理
1.URLError:来自urllib库的error模块,继承自OSError类,由request模块产生的异常都可以捕获这个类来处理。
-属性:reason:返回错误产生的原因。
例:
from urllib import request,error
try:
r=request.urlopen('https://......')
except error.URLError as e:
print(e.reason)#避免异常终止,打印错误原因
2.HTTPError:URLError的子类,用来处理HTTP请求错误。
-属性:
1.code:返回HTTP状态码
2.reason:错误原因
3.headers:返回请求头
例:
try:
......
except error.HTTPError as e:
print(e.reason,e.code,e.headers,sep='\n')
-输出:
Not Found
404
headers信息.....
较好的异常处理写法:
from urllib import request,error
try:
r=request.urlopen('https://www.baidu.com')
except error.HTTPError as e:
print(e.reason,e.code,e.headers,sep=''\n)
except error.URLError as e:
print(e.reason)
else:
print('Request Successfully')
先捕获HTTPError异常,如果不是此异常,则捕获URLError,如果没有发现异常,用else来做正确的相关处理
-判断是否为超时异常的方法:
try:
...
except urllib.error.URLError as e:
if isinstance(e.reason,socket.timeout):
#isinstance(A,B)用于判断两个参数的类型是否相同,返回True或False
print('Time Out')
urllib.parse模块:
-解析链接
1.urlparse():URL的识别和分段,返回值为元组,可用索引或字段名取值,返回值为6个部分
1)scheme:协议
2)netloc:域名
3)path:访问路径
4)params:参数
5)query:查询条件(一般再GET类型的URL中)
6)fragment:锚点(定位页面内部的下拉位置)
-标准的链接格式:
scheme://netloc/path;params?query#fragment
-urlparse()的完整写法:
urllib.parse.urlparse(urlstring,scheme=' ',allow_fragments=True)
-参数:
1)urlstring:待解析的URL
2)scheme:备用的协议,若URL中无协议,使用此处指定的协议,若URL有协议,则此参数无效
3)allow_fragments:是否忽略fragment,设置为false时,url中的fragment部分会被解析为path、params、query的一部分,而fragment部分为空
-使用:
result=urlparse('http://www.baidu.com/index.html#comment')
print(result.scheme,result[0],result.netloc,result[1])
2.urlunparse():将urlparse方法解析的六个部分构造为一个标准的url 链接
例:
from urllib.parse import urlunparse
data=['http','www.baidu.com','index.html','user','a=6','comment']
#data列表的长度必须为6
#结果为:http://www.baidu.com/index.html;user?a=6#comment
3.urlsplit():与urlparse()类似,区别在于urlsplit()没有params部分,将其合并到path中显示
4.urlunsplit():与urlunparse()类似,区别在于传入5个部分的内容,无params部分
5.urljoin():两个参数,第一个为base_url(基础链接),第二个参数为另一个链接,会对base_url中的scheme,netloc,path3个部分进行分析,若第二个链接的这三个部分内容有缺失,用base_url中对应部分对其补充,若无缺失,则使用第二个链接。
6.urlencode():
-序列化方法
-作用:将字典类型序列化,也就是转换为字符串形式。(构造GET请求参数时)
例:
params={'name':'make','age':20}
url='http://www.baidu.com?'+urlencode(params)
#结果:http://www.baidu.com?name=make&age=20
7.parse_qs()
-反序列化方法
-可以将一串GET请求参数,转为字典
例:
query='name=germey&age=22'
print(parse_qs(query))
#结果:{'name':['germey'],'age':['22']}
8.parse_qsl()
-将参数转换为元组组成的列表
例:
query='name=germey&age=22'
print(parse_qsl(query))
#结果:[('name','germey'),('age','22')]
9.quote()
-编码
-将内容转换为URL编码格式
例:quote(keyword)
-结果:%E5%A3%B1....
10.unquote()
-解码
-于quote()方法相反,将URL编码结果还原
urllib.robotparser模块:
-robots.txt解析
-使用方法:使用该模块中的RobotFileParser类
urllib.robotparser.RobotFileParser(url='传入robots.txt的链接 ')
-常用方法:
1.set_url():设置robots.txt的链接
2.read():读取robots.txt文件并分析(读取后用’\n‘分割,就是每一行的内容)
3.parse():解析robots.txt文件,传入的参数是robots.txt某些行的内容
4.can_fatch():返回是否可抓取该URL,True或False
-参数:
1)User-Agent
2)待抓取的URL
5.mtime():返回上次抓取和分析robots.txt的时间,用于定期检查来抓取最新的robots.txt
6.modified():将当前时间设置为上次抓取和分析botots.txt的时间
from urllib.robotparser import RobotFileParser
rp=RobotFileParser('http://www.jianshu.com/robots.txt')
rp.read()
print(rp.can_fetch('*','http://www.baidu.com/p'))
#结果:True 表示该robots.txt中指出该URL可被任何爬虫爬取
例:parse()的使用
rp=RobotFileParser()
rp.parse(urlopen('http://www.baidu.com/robots.txt').read().decode('utf-8').split('\n'))
print(rp.can_fetch('*','http://www.baidu.com/p'))
#结果:True