urllib 01

关于urllib库的使用request 发送请求urlopen()request类高级用法

关于urllib库的使用

urllib库是python内置的HTTP请求库,也就是说我们是不需要进行安装的。 其中urllib包括以下四个模块 1. request:用以模拟发送请求,就像我们浏览器的输入框,其中可以加入一些额外参数用以模拟浏览器 2.error 3.parse 4.robotparser

request 发送请求

urlopen()

urllib.request()可以实现最基本的HTTP访问。
下面以一个实例爬取python官网进行展示

import urllib.request
response = urllib.request.urlopen('http://www.python.org')
print(response.read().decode('utf-8'))

可以看到python程序已经成功获取了网页源代码,但是发现在获取的response中的类型需要通过 response.read().decode('utf-8') 才能进行展示,检查一下response的数据类型为

type(response)

http.client.HTTPResponse

发现response的数据类型为http.client.HTTPResponse 该类型的对象主要有read() readinto() getheader(name) getheaders() fileno() 等方法 以及msg/version/status/reason/debuglecel/closed等属性

如 通过response.read()方法可以获取读取结果,通过response.status属性可以获取response的状态

response.status

200

目前status属性为200,即是联通状态 可以对其他方式进行调用测试

print(response.getheaders())

[('Connection', 'close'), ('Content-Length', '50897'), ('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur, 1.1 varnish, 1.1 varnish'), ('Accept-Ranges', 'bytes'), ('Date', 'Fri, 05 Mar 2021 11:22:01 GMT'), ('Age', '1919'), ('X-Served-By', 'cache-bwi5125-BWI, cache-hnd18721-HND'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '1, 3182'), ('X-Timer', 'S1614943322.979393,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]

print(response.getheader('Content-length'))

50897

我觉得我有必要区别以下getheader()和getheaders(): 所以很明显的是,getheaders()方法用于输出全部的响应头的信息,而getheader(name) 则对应的输出响应值

urlopen()还有许多的参数,首先看一下urlopen的API

urllib.request.urlopen(
url,
data=None,
timeout=,
*,
cafile=None,
capath=None,
cadefault=False,
context=None,
)

下面分别从不同参数理解整个函数

  • data

下面通过一个实例来介绍data的用法 这里urlopen()方法中,data的类型必须是byte类型,所以输入的字典{'word':'hello'},必须通过bytes()方法转换成byte类型,而bytes()方法只接受string类型,通过urllib.parse.urlencode()方法将字典转换成string,再转换成byte类型 这里我用的是jupyter lab,所以在后面response.read().decode('utf-8')让换行符消失

import urllib.parse
import urllib.request

data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read().decode('utf-8'))

{
"args": {},
"data": "",
"files": {},
"form": {
"word": "hello"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "10",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.7",
"X-Amzn-Trace-Id": "Root=1-60423d57-04ac587026fe33de2ccee34f"
},
"json": null,
"origin": "183.246.30.52",
"url": "http://httpbin.org/post"
}

form中,出现了输入的字典,则表示url的请求方式为post方式,这里简单介绍一下post方式和get方式的差异:

  1. 在安全性方面

    • get方式会让信息暴露在url中,可能导致密码泄露

    • post方式以表单的形式上传,能更好地保护信息安全

  2. 在传输数据量方面

    • get请求提交最多只有1024个字节

    • post请求无限制

  • timeout

timeout参数用于设置限定时间,即在限定的时间内如果没有获得服务器响应即报错。 通过下面的实例进行演示

import socket
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)
except urllib.error.URLError as e:

print(response.read().decode('utf-8'))

if isinstance(e.reason,socket.timeout):
    print('TIME OUT')
    

TIME OUT

由于时间超时,输出的错误类型是URLerror是属于urllib.error类型,所以导入相关库进行抓取错误。 timeout 类型错误是属于超市错误属于socket类型的错误

request类

介绍以下request的API内容

urllib.request.Request(
url,
data=None,
headers={},
origin_req_host=None,
unverifiable=False,
method=None,
)

urllib.request.Request( url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None, )

  1. 其中url是必选参数,其他都是可选参数

  2. data必须传bytes类型

  3. headers传入的内容是字典,作为请求头,可通过修改User-Agent伪装浏览器

  4. origin_req_host是指请求方的host地址或IP地址

  5. unverifiable表示的是这个请求是否是无法验证的??

  6. method传入的书请求方法,有get和post两种

以下通过一个实例来展示request类

from urllib import request, parse
url = 'http://httpbin.org/post'

构造请求头

headers = {
'User-Agent':'Mozilla/4.0(compatible; MSIE 5.5; Windows NT)',
'Host':'httpbin.org'
}

构造输入的表单数据

dic ={
'name':'Atu'
}

构造data数据

data = bytes(parse.urlencode(dic),encoding='utf-8')

构造了request类,即是一个伪装后的url

req = request.Request(
url=url,
data=None,
headers=headers,
origin_req_host=None,
unverifiable=False,
method='POST'
)
response = request.urlopen(req)
print(response.read().decode('utf-8'))

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "0",
"Host": "httpbin.org",
"User-Agent": "Mozilla/4.0(compatible; MSIE 5.5; Windows NT)",
"X-Amzn-Trace-Id": "Root=1-60430595-3161f57a0ee7913f60b742a4"
},
"json": null,
"origin": "223.104.247.132",
"url": "http://httpbin.org/post"
}

高级用法

对于更加高级的如cookie处理,代理设置等,我们可以选择强大的handler工具。 首先介绍urllib.request模块里面的BaseHandler父类,各个子类都继承了BaseHandler的属性:

  • HTTPDefaultErrorHandler: 用于处理HTTP相应错误,抛出的HTTPError错误

  • HTTPRedirectHandler:处于处理重定向[mark,重定向是指什么]

  • HTTPCookieProcessor:用于处理Cookies 还有其他handler类可以参考官方文档

另一个比较重要的类是OpenerDirector,我们称之为Opener,前面使用的urlopen()方法实际上就是一个urllib配置好的opener,为了实现更加高级的方法,这里使用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) # auth_handler是由HTTPBasicAtuthHandler实例化的Handler对象,其输入额参数为 HTTPPasswordMgrWithDefaultRealm对象
opener = build_opener(auth_handler)

try:
result = opener.open(url) #使用open打开的对象就是需要的结果
html = result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)

[WinError 10061] 由于目标计算机积极拒绝,无法连接。

  • 代理 做爬虫时间,大多数时候为了隐藏自身的真实ip都会选择代理,以以下实例进行展示: proxyHandler是用来做代理类,其参数是字典

from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener

proxy_handler = ProxyHandler({
'http':'http://127.0.0.1:9743',
'http':'http://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)








  • Cookie 下面通过实例介绍,保存cookie的Handler
  1. 声明CookieJar对象,把CookieJar对象进行实例化

  2. 使用HTTPCookieProcessor构建handler,其输入的参数为CookieJar

  3. 利用build_opener构建出Opener

import http.cookiejar,urllib.request

cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')

for item in cookie:
print(item.name+"="+item.value)

BAIDUID=9871F8DE5C415A182773408756D8CCB7:FG=1
BIDUPSID=9871F8DE5C415A1867D1295E303CB06F
H_PS_PSSID=33517_33637_33261_33273_31660_33594_33605_33590_26350_22158
PSTM=1615017612
BDSVRTM=0
BD_HOME=1

考虑将Cookie内容本地保存,可以使用MozillaCookieJar方法. 保存文件的时候应当保存cookie文件,cookie文件的格式是[http.cookiejar.MozillaCookieJar],而response的格式是[http.client.HTTPResponse],

filename='cookie.txt'
cookie = http.cookiejar.MozillaCookieJar(filename=filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True,ignore_expires=True)

也可以采用LWPCookieJar的格式保存,即声明: cookie = http.cookiejar.LWPCookieJar(),生成了文件格式有所不同

在看一下怎么读取文件中的Cookie

cookie = http.cookiejar.MozillaCookieJar()
cookie.load(filename="cookie.txt",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的request用法到这里介绍为止,其他内容可以参考官网文档,然后后面继续是urllib的其他问题

希望能跟你沟通学习,能够一直成长,加油!

你可能感兴趣的:(urllib 01)