首先,了解一下 urllib库,它是 Python内置的HTP请求库,也就是说不需要额外安装即可使用。
它包含如下4个模块。
urllib.request 模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理授权验证,重定向,浏览器Cookies以及其他内容
import urllib.request
import urllib.parse
import urllib.error
import socket
response = urllib.request.urlopen("http://www.ifeng.com/")
print(response.read().decode("utf-8"))
#用type()方法输出响应的类型
print(type(reponse))
print(response.status)
print(response.getheaders())
print(response.getheader("Server"))
可以发现是一个HTTPResponse类型的对象,主要包含read(),readinto(),getheader(name),getheaders(),fileno()等方法,以及msg,version,status,reason,debuglevel.closed等属性
urlopen函数的API
urllib. request. urlopen(url, data=None, [timeout, ]* cafile=None, capath=None, cadefault=False, context=None)
可以发现除第一个参数可以传递url之外,我们还可以传递其他内容,比如data(附件数据)timeout(超时时间)等
data参数是可选的如果要添加该参数,需要使用byte()方法将参数转化为字节流编码格式的内容,即bytes类型。
另外,如果使用这个参数,则它的请求方式就不再是Get方式,而是post方式
data = bytes(urllib.parse.urlencode({'account':"15124120232"}),encoding="utf8")
response = urllib.request.urlopen("http://httpbin.org/post",data = data)
print(response.status)
print(response.read().decode("utf-8"))
timeout 参数用于设置超时时间,单位为秒,意思就是如果请求超出设置的这个时间,还没有的得到响应,就会抛出异常。如果不指定这个参数,就会使用全局默认时间。它支持HTTP,HTTPS,FTP请求
try:
response = urllib.request.urlopen("http://httpbin.org/get",timeout=0.11)
except urllib.error.URLError as e:
if isinstance(e.reason,socket.timeout):
print("TIME OUT")
除了data和timeout参数之外,还有context参数,它必须是ssl.SSLContent类型,用来指定SSL设置,此外,cafile和capath这两个参数分别指定CA证书和它的路径,这个请求在HTTPS链接时会有用
利用urlopen()方法可以实现最基本的请求发起,但这几个简单的参数并不足及构建一个完整的请求。如果请求中加入Headers等信息,就可以利用会更加强大的Request类来构建
request = urllib.request.Request("http://www.ifeng.com/")
response = urllib.request.urlopen(request)
print(response.read().decode("utf-8"))
class urllib request Request(url, data=None, headers=0), origin req host=None, unverifiable=False, method=None)
第一个参数ur1用于请求URL,这是必传参数,其他都是可选参数。
第二个参数data如果要传,必须传 bytes(字节流)类型的。如果它是字典,可以先用urllib. parse模块里的 urlencode()编码。
第三个参数 headers是一个字典,它就是请求头,我们可以在构造请求时通过 headers参数直接构造,也可以通过调用请求实例的 add header()方法添加。
添加请求头最常用的用法就是通过修改User- Agent来伪装浏览器,默认的User- Agent是Python-urllib,我们可以通过修改它来伪装浏览器。比如要伪装火狐浏览器,你可以把它设置为
Mozilla/5.0(X11; U; Linux 1686)Gecko/20071127 Firefox/2.0.0.11
第四个参数 origin req host指的是请求方的host名称或者IP地址。
第五个参数 unverifiable表示这个请求是否是无法验证的,默认是 False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable的值就是 True c
第六个参数 method是一个字符串,用来指示请求使用的方法,比如GET、POST和PUT等。
url = "http://210.38.250.43/login!doLogin.action"
headers = {
'User-Agent': "Mozilla/5.0(X11; U; Linux 1686)Gecko/20071127 Firefox/2.0.0.11",
'Host': "210.38.250.43"
}
dict = {
'account': '123',
'pwd': '123456'
}
data = bytes(urllib.parse.urlencode(dict),encoding='utf8')
req = urllib.request.Request(url=url,data=data,headers=headers,method="POST")
response = urllib.request.urlopen(req)
print(response.read().decode("utf-8"))
可以把它理解为各种处理器,有专门处理登录验证的,有处理Cookies的,有处理代理设置的。利用它们,我们几乎可以做到HTTP请求中所有的事情。
接下来,就有各种 Handler子类继承这个 BaseHandler类,举例如下。
from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
proxy_handler = ProxyHandler({
'http': "http://127.0.0.1:9743",
'https': "https://127.0.0.1:9743"
})
opener = build_opener(proxy_handler)
try:
response = opener.open("https://www.baidu.com")
print(response.read().decode("utf-8"))
except URLError as e:
print(e.reason)
import http.cookiejar,urllib.request
filename = "cookies.txt"
cookie = http.cookiejar.MozillaCookieJar()
cookie.load(filename,ignore_discard=True,ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com")
print(response.read().decode("utf-8"))
urllib的error模块定义了由request 模块产生的异常。如果出现了问题,request模块便会抛出error模块中定义的异常
URLError类来自 urllib库的eror模块,它继承自OSError类,是 error异常模块的基类,由 request模块生的异常都可以通过捕获这个类来处理。
它具有一个属性reason,即返回错误的原因
try:
response = urllib.request.urlopen("http://fengzhao.com/index.html")
except urllib.error.URLError as e:
print(e.reason)
它是 URLError的子类,专门用来处理HTP请求错误,比如认证请求失败等。它有如下3个属性
try:
response = urllib.request.urlopen("http://fengzhao.com/index.html")
except urllib.error.HTTPError as e:
print(e.reason,e.code,e.headers,sep="\n")