1.2 请求库 -- urllib库的使用
1.urllib库介绍: (Python3)
1 # urllib是python内置的HTTP请求库, 不需要额外安装即可使用, 它包含四个模块, 分别如下: 2 3 (1).request: request是最基本的HTTP请求模块, 可以用来模拟发送请求. 就像在浏览器中输入网址后按下回车是一样一样滴, 只需要个库方法传入URL以及额外的参数, 就可以模拟实现这个过程了. 4 5 (2).error: 异常处理模块, 如果出现请求错误, 我们可以捕捉这些异常, 然后进行重试或其他操作以保证程序不会意外终止. 6 7 (3).parse: 一个工具模块, 提供了许多URL处理方法, 比如拆分, 解析, 合并等. 8 9 (4).robotparse: 主要是用来识别网站的robots.txt文件, 然后判断哪些网站可以爬, 哪些网站不能爬, 其实这并不重要, 因为robots.txt只针对通用爬虫, 我们爬取数据一般会忽略该协议.
2.urllib发送请求与响应
urlopen是urllib.request提供的向服务器发送请求的的方法,同时它还带有处理授权验证(authenticaton)、重定向(redirection)、浏览器Cookies以及其他内容. 其语法与具体示例如下:
urllib.request.urlopen(url, data=None, [timeout,]*, cafile=None, cadefault=False, context=None)
(1).使用urlopen发送get请求
1 # 导入urllib库下的request模块 2 import urllib.request 3 4 # 使用urlopen向百度网页发送请求, response可以调用read方法, 读取内部的内容 5 response = urllib.request.urlopen('https://www.baidu.com') 6 7 # read方法获取的是二进制数据, 用utf-8进行解码就可以正常显示了 8 print(response.read().decode('utf-8'))
(2).使用urlopen发送post请求
1 # 在利用urlopen发送post请求前需要预先定义data数据作为方法的参数传递 2 import urllib.parse # parse定义data 3 import urllib.request 4 5 # urlencode可以吧字典转化为字符串 6 # 传入urlopen中的data需要是字节流, 需要使用bytes进行转换, 编码格式为utf-8 7 data = bytes(urllib.parse.urlencode({'word':'hello'}), encoding='utf8') 8 response = urllib.request.urlopen('http://httpbin.org/post', data=data) # 将data传入方法中 9 print(response.read())# 输出响应结果
(3).自定制Request对象
1 # 为什么要定制Request对象 2 上面的demo中我们通过URLopen发送了简单的请求,但传递的几个简单参数还不能构建一个完整的请求,由于一些服务器要求请求中需要携带headers中的一部分内容才能请求成功,没有这些表要的请求头很有可能会被识别为非法请求.所有需要定制Request对象. 3 4 # 定制Request对象与发送请求的步骤 5 -从urllib中导入request 6 -实例化一个Request对象,给该对象传入需要的参数 7 -利用urlopen方法将上面实例化定制后的request对象作为参数传入,向服务器发送请求 8 9 # Request类参数: 10 Request(url, data=None, headers={},origin_req_host=None,unverifiable=False, method=None) 11 - url:要请求的url 12 - data:发送post请求要向服务器提交的数据,可以使用urllib.parse.urlencode()编码,再bytes转为字节流类型 13 - headers是请求头信息,是一个字典,可以直接构造完成,也可以使用add_header方法动态添加 14 - origin_req_host:指的是请求方的host名称或者IP地址. 15 - unverifiable:表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True` 16 - method:是一个字符串,用来指示请求使用的方法,比如GET、POST和PUT等。
1 # 导入request模块用于发送请求, parse模块用于处理data数据 2 from urllib import request, parse 3 4 # 定义要访问的url 5 url ='http://httpbin.org/post' 6 7 # 定义响应头, 其中User-Agent表示了客户单的信息 8 headers ={ 9 'User-Agent':'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 10 'Host':'httpbin.org' 11 } 12 13 # 构建需要提交到服务器的数据 14 dict ={ 15 'name':'Germey' 16 } 17 18 # 处理data数据, 先将dic用parse.urlencode()转化为字符串 19 # 将字符串形式的dic通过bytes转化为字节流 20 data = bytes(parse.urlencode(dict), encoding='utf8') 21 22 # 实例化request对象, 传入url, data及headers参数, 由于提交数据data, 所以method为post请求 23 req = request.Request(url=url, data=data, headers=headers, method='POST') 24 25 # 使用urlopen向服务器发送请求, 获取响应赋值给response 26 response = request.urlopen(req) 27 28 # 输出响应结果 29 print(response.read().decode('utf-8'))
(4).响应对象
1 1.响应对象response的类型是<class'http.client.HTTPResponse'>,就是一个HTTPResponse类型的对象 2 3 2.响应对象常用方法: 4 read():返回网页内容 5 getheader(name):获取指定的响应头信息 6 getheader():获取所有响应头信息 7 8 3.响应对象包含的属性如下: 9 status:返回结果的状态码 10 reason:返回响应的异常信息
3.urllib高级用法 — Handler(处理器)
1 # Handler介绍: 2 通过上面的对request的封装后,已经构造了相对完善的request了,但还不够完善.一些网站的访问需要用户携带cookie,一些网站对ip的访问频率会有限制,当我们的请求量较大时,很有可能就被封ip了.所以我们还有对request进行进一步的处理. 3 Handler是一个强大的工具,可以理解为各种处理器,Handler有处理Cookies的,有处理ip代理的,还可处理登陆验证. 4 应用Handler不需知道一个BaseHandler类,它是所有其他Handler的父类,其内部封装了最基本的方法共子类调用. 5 现在要使用高级用法,就要引入opener. opener提供了open方法来请求服务器获取数据.
1 # opener的具体构建步骤如下: 2 0.构建一个对象,这个对象是构建处理器是需要传入的参数,不同的处理器有所不同,不如代理处理器的构建就不需要这一步. 3 1.实例化一个处理器,如Cookies处理器,代理处理器,验证处理器 4 2.利用build_opener方法构建opener
(1).验证
1 from urllib.request importHTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler, build_opener 2 from urllib.error importURLError 3 username ='username' 4 password ='password' 5 url ='http://localhost:5000/'# 自己搭建的服务器, 用于测试 6 7 # 1.示例化一个HTTPPasswordMgrWithDefaultRealm对象, 该对象将作为验证处理器实例化的参数传入 8 p =HTTPPasswordMgrWithDefaultRealm() 9 10 # 使用p的add_password方法将用户名密码添加进p对象 11 p.add_password(None, url, username, password) 12 13 # 2.实例化验证处理器对象, 并将p对象作为参数传进来 14 auth_handler =HTTPBasicAuthHandler(p) 15 16 # 3.利用build_opener方法构建一个opener, 接下来就可以利用opener来请求服务器了 17 opener = build_opener(auth_handler) 18 try: 19 result = opener.open(url) 20 html = result.read().decode('utf-8') 21 print(html) 22 exceptURLErroras e:# 处理异常 23 print(e.reason)
(2).代理
1 from urllib.error importURLError 2 from urllib.request importProxyHandler, build_opener 3 4 # 1.构建代理处理器, 注意:代理处理器的构建不需要像认证处理器那样先实例化一个对象作为参数 5 proxy_handler =ProxyHandler({ 6 'http':'http://127.0.0.1:9743', 7 'https':'https://127.0.0.1:9743' 8 }) 9 10 # 2.构建opener 11 opener = build_opener(proxy_handler) 12 13 # 向服务器发起请求 14 try: 15 response = opener.open('https://www.baidu.com') 16 print(response.read().decode('utf-8')) 17 exceptURLErroras e: 18 print(e.reason)
(3).Cookies
1 import http.cookiejar, urllib.request 2 3 # 1.实例化一个cookie对象, 该对象将作为参数传入处理器中 4 cookie = http.cookiejar.CookieJar() 5 6 # 2.构建一个cookie处理器, 将cookie对象出入 7 handler = urllib.request.HTTPCookieProcessor(cookie) 8 9 # 请求服务器获取数据 10 opener = urllib.request.build_opener(handler) 11 response = opener.open('http://www.baidu.com') 12 13 # 遍历cookie对象, 查看请求时携带的cookie都有哪些内容, 下面代码不是请求需要的代码, 是为了给大家看看cookie是个什么鬼 14 for item in cookie: 15 print(item.name+"="+item.value)
4.处理异常
1 # error简介 2 urllib的error模块定义了有request模块产生的异常,其中包含了URLError和HTTPError,其实HTTPError是URLError的子类 3 4 1.URLError 5 URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,有request,模块产生的异常都可以通过捕捉这个类来处理. 6 from urllib import request, error 7 try: 8 # 下面网址是我博客网址改动的, 根本不存在这个页面, 所以请求会抛出异常 9 response = request.urlopen('https://www.cnblogs.com/Jermy/p/1082330800000000.html') 10 except error.URLErroras e: 11 print(e.reason) 12 13 2.HTTPError 14 HTTPError是URLError的子类,专门用来处理HTTP请求错误,比如认证请求失败等。它有如下3个属性。 15 - code:返回HTTP状态码,比如404表示网页不存在,500表示服务器内部错误等。 16 - reason:同父类一样,用于返回错误的原因。 17 - headers:返回请求头。 18 from urllib import request, error 19 try: 20 # 下面网址是我博客网址改动的, 根本不存在这个页面, 所以请求会抛出异常 21 response = request.urlopen('https://www.cnblogs.com/Jermy/p/1082330800000000.html') 22 except error.HTTPErroras e: 23 print(e.reason, e.code, e.headers)
1 小贴士:如果你足够细心会发下我上面使用的是同样的url,却使用了不同的异常捕捉,同样都能捕捉到NotFound这个异常.那到底什么时候用URLError,什么时候用HTTPError呢?迷茫...... 2 没关系的,因为HTTPError是URLError的子类,也就是HTTPError会继承URLError,所以URLError能捕捉的异常,HTTPError一样能步骤,所以任性一点直接用HTTPError好了,
而且它步骤到异常能够提供的信息更多,岂不是更好,然并卵.个人感觉用处不大,注意不是没用,我只是说用处不大而已.
5.解析链接(使用较少)
1 # 1.urlencode():使用较多,它在构造GET请求参数的时候非常有用 2 3 from urllib.parse import urlencode 4 5 # 构建请求参数 6 params={ 7 'wd':'爬虫' 8 } 9 base_url ='http://www.baidu.com?' 10 url = base_url + urlencode(params) 11 print(url)
12 # 输出结果为: 13 http://www.baidu.com?wd=%E7%88%AC%E8%99%AB
1 # 其他方法:(不常用可只做了解) 2 2. urlparse():该方法可以实现URL的识别和分段 3 3. urlunparse():有了urlparse(),相应地就有了它的对立方法urlunparse()。它接受的参数是一个可迭代对象,但是它的长度必须是6,否则会抛出参数数量不足或者过多的问题 4 4. urlsplit():该方法和urlparse()方法非常相似,不过它不再单独解析params这一部分,只返回5个结果 5 5. urlunsplit():与urlunparse()类似,它也是将链接各个部分组合成完整链接的方法,传入的参数也是一个可迭代对象,例如列表、元组等,唯一的区别是长度必须为5 6 6. urljoin():提供一个base_url(基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析base_url的scheme、netloc和path这3个内容并对新链接缺失的部分进行补充,最后返回结果 7 7. parse_qs():有一串GET请求参数,利用parse_qs()方法,就可以将它转回字典 8 8. parse_qsl():它用于将参数转化为元组组成的列表 9 9. quote():该方法可以将内容转化为URL编码的格式. URL中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为URL编码 10 10. unquote():有了quote()方法,当然还有unquote()方法,它可以进行URL解码
6.Robots协议
1 Robots协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(RobotsExclusionProtocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作robots.txt的文本文件,一般放在网站的根目录下。 2 当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取。如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。 3 小贴士:甭管他,爬你的就好,,,就怕你技术太菜,爬不到人家的数据..........
浙公网安备 33010602011771号