程序地带

爬虫-urllib模块的使用


urllib是Python中请求url连接的官方标准库,在Python3中将Python2中的urllib和urllib2整合成了urllib。urllib中一共有四个模块,分别如下:


request:主要负责构造和发起网络请求,定义了适用于在各种复杂情况下打开 URL (主要为 HTTP) 的函数和类
error:处理异常
parse:解析各种数据格式
robotparser:解析robot.txt文件
一、request模块
1.urlopen()方法:
在urlopen()方法中,直接写入要访问的url地址字符串,该方法就会主动的访问目标网址,然后返回访问结果,返回的访问结果是一个http.client.HTTPResponse对象,该对象的常见方法有:
read() :获取访问网页获取的数据,bytes类型
info():返回响应头信息
getcode():返回Http状态码。
geturl():返回请求的url
发送简单的GET请求
from urllib.request import urlopen
#向指定的url发送请求,并返回服务器响应的类文件对象
resp = urlopen("https://www.baidu.com")
print(resp.read().decode())
发送简单的POST请求(data参数)
from urllib.reuqest import urlopen
from urllib.parse import urlencode
#将字典类型的数据转换成表单类型的数据格式,如"world=hello"
data = urlencode({"word":"hello"}).encode()
response = request.urlopen("http://httpbin.org/post", data=data)
print(response.read().decode())

默认的访问方式是GET,当在urlopen()方法中传入data参数时,则会发起POST请求。注意:传递的data数据需要为bytes格式


2.Request
如果需要执行更复杂的操作,比如增加HTTP报头,必须创建一个 Request 实例来作为urlopen()的参数;而需要访问的url地址则作为 Request 实例的参数。
为了使爬虫程序更像一个真实用户,那我们第一步就是需要伪装成一个被公认的浏览器,在发送请求的时候带上User-Agent头
from urllib.request import Request,urlopen
url = "https://www.baidu.com/"
ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
#url连同headers一起构造request请求,这个请求附带IE 9.0浏览器的User-Agent
request = Request(url,headers=ua_header)
#向服务器发送请求
resp = urlopen(request)
print(resp.read().decode)
3.ProxyHandler处理器(代理IP)
使用爬虫来爬取数据的时候,如果过于频繁的访问,而且网站还设有限制的话,很有可能会禁封我们的ip地址,这个时候就需要设置代理,来隐藏我们的真实IP。
代理IP的原理:以本机先访问代理IP,再通过代理IP地址访问服务器,这样服务器接受到的访问IP就是代理IP地址。
from urllib.request import build_opener,urlopen,install_opener,Request,ProxyHandler
# 构建了两个代理Handler,一个有代理IP,一个没有代理IP
proxy_handler = ProxyHandler({"http": "218.18.232.26:80", "https": "218.18.232.26:80"})
nullproxy_handler = ProxyHandler({})
proxySwitch = True #定义一个代理开关
# 通过build_opener()方法使用这些代理Handler对象,创建自定义opener对象
# 根据代理开关是否打开,使用不同的代理模式
if proxySwitch:
opener = build_opener(proxy_handler)
else:
opener = build_opener(nullproxy_handler)
request = Request("http://www.baidu.com/")
# 1. 如果这么写,只有使用opener.open()方法发送请求才使用自定义的代理,而urlopen()则不使用自定义代理。
resp = opener.open(request)
# 2. 如果这么写,就是将opener应用到全局,之后所有的,不管是opener.open()还是urlopen() 发送请求,都将使用自定义代理。
# install_opener(opener)
# resp = urlopen(request)
print (resp.read().decode())

如果代理需要授权验证,简单的方式是只需要在ProxyHandler传入的参数字典中,将值改为"用户名:密码@ip:端口号"这种形式,比如{"http":"myname:[email protected]:80"},如果采用复杂的方式,就需要创建一个密码管理对象,下面会有介绍。


4.HTTPPasswordMgrWithDefaultRealm()
利用这个类创建一个密码管理对象,用来保存 HTTP 请求相关的用户名和密码,主要应用两个场景:
验证代理授权的用户名和密码 (ProxyBasicAuthHandler())
验证Web客户端的的用户名和密码 (HTTPBasicAuthHandler())
5.ProxyBasicAuthHandler(代理授权验证)
在使用私密代理时,需要通过授权验证身份
from urllib.request import HTTPPasswordMgrWithDefaultRealm,ProxyBasicAuthHandler,build_opener,Request
# 私密代理授权的账户
user = "mr_mao_hacker"
# 私密代理授权的密码
passwd = "sffqry9r"
# 私密代理 IP
proxyserver = "61.158.163.130:16816"
# 1. 构建一个密码管理对象,用来保存需要处理的用户名和密码
passwdmgr = HTTPPasswordMgrWithDefaultRealm()
# 2. 添加账户信息,第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None,后面三个参数分别是代理服务器、用户名、密码
passwdmgr.add_password(None, proxyserver, user, passwd)
# 3. 构建一个代理基础用户名/密码验证的ProxyBasicAuthHandler处理器对象,参数是创建的密码管理对象
# 注意,这里不再使用普通ProxyHandler类了
proxyauth_handler = ProxyBasicAuthHandler(passwdmgr)
# 4. 通过 build_opener()方法使用这些代理Handler对象,创建自定义opener对象,参数包括构建的 proxy_handler 和 proxyauth_handler
opener = build_opener(proxyauth_handler)
request = Request("https://www.baidu.com/")
resp = opener.open(request)
print (resp.read().decode())

注:通常用户名和密码不直接写在程序中,而是存放在环境变量,或者单独写入一个模块,然后从模块导入


6.HTTPBasicAuthHandler(WEB客户端授权验证)
有些Web服务器(包括HTTP/FTP等)访问时,需要进行用户身份验证,爬虫直接访问会报HTTP 401 错误,表示访问身份未经授权
如果我们有客户端的用户名和密码,只需要将上述代理授权验证代码中的ProxyBasicAuthHandler改成HTTPBasicAuthHandler即可
7.Cookies
Cookies在爬虫方面最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续。
由于urllib并没有很好的处理cookie的对象,所以在这里我们需要用到一个别的库,即http库,并使用里面的cookiejar来进行cookie的管理,该模块主要的对象有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-perl标准的 Set-Cookie3 文件格式兼容的FileCookieJar实例。


大多数情况下,我们只需要用到CookieJar(),如果需要和本地文件进行交互,就要用MozillaCookieJar()和LWPCookieJar(),下面就介绍几种案例:
获取cookie,并保存到CookieJar()中
from http.cookiejar import CookieJar
from urllib.request import Request,build_opener,HTTPCookieProcessor
# 构建一个CookieJar对象实例来保存cookie
cookiejar = cookielib.CookieJar()
# 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
handler=HTTPCookieProcessor(cookiejar)
opener = build_opener(handler)
# 以get方法访问页面,访问之后会自动保存cookie到cookiejar中
resp = opener.open("http://www.baidu.com")
# 可以按标准格式将保存的Cookie打印出来
cookieStr = ""
for item in cookiejar:
cookieStr = cookieStr + item.name + "=" + item.value + ";"
# 舍去最后一位的分号
print cookieStr[:-1]
访问网站获得cookie,并将cookie保存在本地文件中
from http.cookiejar import MozillaCookieJar
from urllib.request import Request,build_opener,HTTPCookieProcessor
# 保存cookie的本地磁盘文件名
filename = "cookie.txt"
#声明一个MozillaCookieJar(有save实现)对象实例来保存cookie,之后写入文件
cookiejar = MozillaCookieJar(filename)
# 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
handler = HTTPCookieProcessor(cookiejar)
opener = build_opener(handler)
response = opener.open("https://www.baidu.com/")
# 保存cookie到本地文件
cookiejar.save()
从文件中获取cookie
from http.cookiejar import MozillaCookieJar
from urllib.request import Request,build_opener,HTTPCookieProcessor
#创建MozillaCookieJar(有load实现)实例对象
cookiejar = MozillaCookieJar()
#从文件中读取cookie内容到对象
cookiejar.load("cookie.txt")
# 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
handler = HTTPCookieProcessor(cookiejar)
opener = build_opener(handler)
response = opener.open("https://www.baidu.com/")
8.处理HTTPS请求SSL证书验证
最简单的方法就是通过添加忽略ssl证书验证关闭证书验证,由于urllib并没有很好的处理ssl的对象,所以在这里我们需要用到一个别的库,即ssl库,如下:
import ssl
from urllib.request import urlopen,Request
# 表示忽略未经核实的SSL证书认证
context = ssl._create_unverified_context()
url = "https://www.12306.cn/mormhweb/"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
request = Request(url,headers=headers)
# 在urlopen()方法里 指明添加 context 参数
resp = urlopen(request, context=context)
print(resp.read().decode())
二、error模块
在urllib中主要设置了两个异常,一个是URLError,一个是HTTPError,HTTPError是URLError的子类。
1.URLError
URLError产生的原因主要有:
没有网络连接
服务器连接失败
找不到指定的服务器
下面访问一个不存在的域名:
from urllib.error import URLError
from urllib.request import Request,urlopen
request = Request("http://www.fafafasfdaffaf.com/")
try:
resp = urlopen(request)
except URLError as e:
print(e)
2.HTTPError
HTTPError包含了三个属性:
code:请求的状态码
reason:错误的原因
headers:响应的报头
from urllib.error import HTTPError
from urllib.request import Request,urlopen
requset = Request("http://www.baidu.com/lfafdaflafapae.html")
try:
resp = urlopen(requset)
except HTTPError as e:
print(e)
print(e.code)
print(e.reason)
print(e.headers)
三、parse模块

data参数需要用urllib.parse模块对其进行数据格式处理。


urllib.parse.quote(url):(URL编码处理)主要对URL中的非ASCII码编码处理
urllib.parse.unquote(url):(URL解码处理)URL上的特殊字符还原
urllib.parse.urlencode(data):对请求数据data进行格式转换

 


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Elite-Wang/p/14278731.html

随机推荐

js随机序列号20位_js实现随机8位验证码

开发思路:1.画出放置验证码的模块、一个写有“看不清…”的小块,以及输入验证码的文本框2.获取各个模块3.封装一个函数Yan_ma(),设置验证码为8位&#x...

weixin_39574050 阅读(744)

brew gd php_mac php没有GD库怎么办

macphp没有GD库怎么办?php扩展安装(此方法可以解决macosX之后php没有GD库问题步骤总结下载对应版本的源码tar-zxvf下载包名1>cd下载包名2>cdex...

weixin_39561673 阅读(718)

brew gd php_Homebrew安装PHP(new!)

由于Homebrew仓库的更新,将homebrew/homebrew-php合并到homebrew/core中,同时也去掉了php各种扩展包.甚至php安装包的名称也做了统一修改以php7.1为例,以...

weixin_39771969 阅读(144)

哈尔尺度函数_3.3 哈尔小波空间W0

在3.2节我们学习了关于(3.8)定义的Vj的性质。特别的,我们可以乘以系数从一个Vj空间变换到另一个。我们这节学习V0和V1的关系。将f1(t)∈V1投影至V0我们考虑一个属于V1的函...

weixin_39653761 阅读(511)

C++如何将赋一个对象引用

Objectb;Objecta=b;//调用了拷贝构造函数Objectb;Object&a=b;//赋引用Object*a=b;//赋指针...

韩运畅 阅读(344)