使用urllib

它是 Python内置的HTTP请求库,也就是说不需要额外安装即可使用。

包含以下4个模块:

名字 说明
request 它是最基本的 HTTP请求模块,可以用来模拟发送请求。就像在浏览器里输入网址然后回车一样,只需要给库方法传入URL以及额外的参数,就可以模拟实现这个过程了。
error 异常处理模块,如果出现请求错误,我们可以捕获这些异常,然后进行重试或其他操作以保证程序不会意外终止。
parse 一个工具模块,提供了许多URL处理方法,比如拆分、解析、合并等。
robotparser 主要是用来识别网站的 robots.txt文件,然后判断哪些网站可以爬,哪些网站不可以爬,它其实用得比较少。

重点讲解下前3个模块。

发送请求

使用urllib 的request模块,我们可以方便地实现请求的发送并得到响应。

1.urlopen()

urllib.request模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理授权验证(authenticaton)、重定向( redirection)、浏览器Cookies以及其他内容。

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

查看返回的类型

import urllib.request
response=urllib.request.urlopen('https://www.python.org')
print(type(response))

发现是HTTPResponse类型

  • 该对象包含了以下方法:

    • read():返回网页的内容。
    • readinto()
    • getheader(name)
    • getheaders()
    • fileno()
  • 以及以下属性:

    • msg
    • version
    • status:请求页面的状态码。
    • reason
    • debuglevel
    • closed

得到这个对象之后,我们把它赋值为response变量,然后就可以调用这些方法和属性,得到返回结果的一系列信息了。

urlopen API:

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

data参数

data参数是可选的。如果要添加该参数,并且如果它是字节流编码格式的内容,即 bytes类型,则需要通过bytes()方法转化。另外,如果传递了这个参数,则它的请求方式就不再是GET方式,而是POST方式。

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())

这里我们传递了一个参数 word,值是 hello。它需要被转码成 bytes(字节流)类型。其中转字节流采用了bytes()方法,该方法的第一个参数需要是str(字符串)类型,需要用urllib.parse模块里的urlencode()方法来将参数字典转化为字符串;第二个参数指定编码格式,这里指定为utf8。

timeout参数

timeout参数用于设置超时时间,单位为秒,意思就是如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常。如果不指定该参数,就会使用全局默认时间。它支持 HTTP、HTTPS、FTP请求。

import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())

这里我们设置超时时间是1秒。程序1秒过后,服务器依然没有响应,于是抛出了URLError 异常该异常属于urllib.error模块,错误原因是超时。

因此,可以通过设置这个超时时间来控制一个网页如果长时间未响应,就跳过它的抓取。这可以利用try except语句来实现,相关代码如下:

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:if isinstance(e.reason,socket.timeout):print( 'TIME OUT')

这里我们请求了http:/httpbin.org/get测试链接,设置超时时间是0.1秒,然后捕获了URLError异常,接着判断异常是socket.timeout类型(意思就是超时异常),从而得出它确实是因为超时而报错,打印输出了 TIME OUT。

其他参数

除了data参数和timeout参数外,还有context参数,它必须是ssl.SsLContext类型,用来指定SSL设置。

此外,cafile和 capath这两个参数分别指定CA证书和它的路径,这个在请求HTTPS链接时会有用。

cadefault参数现在已经弃用了,其默认值为False。

2.Request

我们知道利用urlopen()方法可以实现最基本请求的发起,但这几个简单的参数并不足以构建一个完整的请求。如果请求中需要加入Headers等信息,就可以利用更强大的Request类来构建。

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

下面我们看一下Request可以通过怎样的参数来构造,它的构造方法如下:

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None,unverifiable=False,method=None)
  • 第一个参数url用于请求URL,这是必传参数,其他都是可选参数。

  • 第二个参数 data如果要传,必须传 bytes(字节流)类型的。如果它是字典,可以先用urllib.parse模块里的urlencode()编码。

  • 第三个参数 headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加。添加请求头最常用的用法就是通过修改 User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,我们可以通过修改它来伪装浏览器。比如要伪装火狐浏览器,你可以把它设置为:

    Mozilla/5.0 (X11; U;Linux i686)Gecko/20071127 Firefox/2.0.0.11
    
  • 第四个参数origin_req_host指的是请求方的host名称或者IP地址。

  • 第五个参数unverifiable表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个 HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True。

  • 第六个参数method是一个字符串,用来指示请求使用的方法,比如 GET、POST和 PUT等。

下面我们传入多个参数构建请求来看一下:

from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {'User-Agent':'Mozilla/4.o (compatible;MSIE 5.5; windows NT)' ,'Host':'httpbin.org'
}
dict = {'name':'Germey'
}data = bytes(parse.urlencode(dict),encoding='utf8')
req = request.Request(url=url, data=data,headers=headers,method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

headers也可以用add_header()方法来添加:

req = request.Request(url=url, data=data,method='POST')
req.add_header( 'User-Agent', 'Mozilla/4.o (compatible; MSIE 5.5; Windows NT)')

3.高级用法

在上面的过程中,我们虽然可以构造请求,但是对于一些更高级的操作(比如 Cookies处理、代理设置等),就需要更强大的工具 Handler 登场了。简而言之,我们可以把它理解为各种处理器,有专门处理登录验证的,有处理Cookies的,有处理代理设置的。利用它们,我们几乎可以做到 HTTP请求中所有的事情。

首先,介绍一下urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,例如 default_open()、 protocol_request()等。有各种 Handler子类继承这个BaseHandler类,举例如下。

说明
HTTPDefaultErrorHandler 用于处理HTTP响应错误,错误都会抛出 HTTPError类型的异常。
HTTPRedirectHandler 用于处理重定向。
HTTPCookieProcessor 用于处理Cookies。
ProxyHandler 用于设置代理,默认代理为空。
HTTPPasswordMgr 用于管理密码,它维护了用户名和密码的表。
HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。

另一个比较重要的类就是OpenerDirector,我们可以称为Opener。Opener可以使用open()方法,返回的类型和urlopen()如出一辙。它就是利用Handler来构建Opener。下面用几个实例来看看它们的用法。

  • 验证

    有些网站在打开时就会弹出提示框,直接提示你输入用户名和密码,验证成功后才能查看页面。

    借助HTTPBasicAuthHandler就可以完成

    from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
    from urllib.error import URLErrorusername = '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)html = result.read().decode('utf-8')print(html)
    except URLError as e:print(e.reason)
    

    这里首先实例化HTTPBasicAuthHandler对象,其参数是HTTPPasswordMgrWithDefaultRealm对象,它利用add_password()添加进去用户名和密码,这样就建立了一个处理验证的 Handler。

    接下来,利用这个Handler并使用build_opener()方法构建一个Opener,这个Opener在发送请求时就相当于已经验证成功了。

    接下来,利用Opener的open()方法打开链接,就可以完成验证了。这里获取到的结果就是验证后的页面源码内容。

  • 代理

    在做爬虫的时候,免不了要使用代理,如果要添加代理,可以这样做:

    from urllib.error import URLError
    from urllib.request import ProxyHandler,build_openerproxy_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)
    

    这里我们在本地搭建了一个代理,它运行在9743端口上。

    这里使用了ProxyHandler,其参数是一个字典,键名是协议类型(比如HTTP或者HTTPS等).键值是代理链接,可以添加多个代理。

    然后,利用这个Handler 及 build opener()方法构造一个Opener,之后发送请求即可。

  • Cookies

    Cookies的处理就需要相关的Handler 了。我们先用实例来看看怎样将网站的Cookies获取下来,相关代码如下:

    import http.cookiejar,urllib.requestcookie = http.cookiejar.CookieJar()
    handler = urllib.request.HTTPCookieProcessor(cookie)
    opener = urllib.request.build_opener(handler)
    response = opener.open( ' http://wwwl.baidu.com')for item in cookie:print(item.name+"="+item.value)
    

    首先,我们必须声明一个CookieJar对象。接下来,就需要利用HTTPCookieProcessor来构建一个Handler,最后利用build_opener()方法构建出Opener,执行open()函数即可。运行结果如下:

    我们还可以输出为文件格式:

    import http.cookiejar,urllib.requestfilename = "cookies.txt"
    cookie = http.cookiejar.MozillaCookieJar(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)
    

    这时CookieJar就需要换成MozillaCookieJar,它在生成文件时会用到,是CookieJar的子类,可以用来处理Cookies 和文件相关的事件,比如读取和保存Cookies,可以将Cookies保存成Mozilla型浏览器的 Cookies格式。运行之后,可以发现生成了一个cookies.txt文件.其内容如下:

    另外,LWPCookieJar同样可以读取和保存Cookies,但是保存的格式和MozillaCookieJar不一样,它会保存成libwww-perl(LWP)格式的Cookies文件。要保存成LWP格式的Cookies文件,可以在声明时就改为:

    cookie = http.cookiejar.LWPCookieJar(filename)
    

    可以发现他们之间的差别有点大。

    下面我们以LWPCookieJar格式来看看如何使用cookie文件

    import http.cookiejar,urllib.request
    cookie = http.cookiejar.LWPCookieJar()
    cookie.load('cookies.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'))
    

    可以看到,这里调用load()方法来读取本地的Cookies文件,获取到了Cookies的内容。不过前提是我们首先生成了LWPCookieJar格式的Cookies,并保存成文件,然后读取 Cookies之后使用同样的方法构建Handler和 Opener即可完成操作。

    运行结果正常的话,会输出百度网页的源代码。

    通过上面的方法,我们可以实现绝大多数请求功能的设置了。

处理异常

urllib的error模块定义了由request模块产生的异常。如果出现了问题,request模块便会抛出error模块中定义的异常。

1.URLError

URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,由request模块生的异常都可以通过捕获这个类来处理。

它具有一个属性reason,即返回错误的原因。

from urllib import request,error
try:response=request.urlopen('https://cuiqingcai.com/index.htm')
except error.URLError as e:print(e.reason)

程序没有直接报错,而是输出了如上内容,这样通过如上操作,我们就可以避免程序异常终止,同时异常得到了有效处理。

2.HTTPError

它是URLError的子类,专门用来处理IITTP请求错误,比如认证请求失败等。它有如下3个属性。

名字 说明
code 返回HTTP状态码,比如404表示网页不存在,500表示服务器内部错误等。
reason 同父类一样,用于返回错误的原因。
headers 返回请求头。
from urllib import request,error
try:response=request.urlopen('https://cuiqingcai.com/index.htm')
except error.HTTPError as e:print(e.reason,e.code,e.headers,sep='\n')

依然是同样的网址,这里捕获了HTTPError异常,输出了reason、code和 headers属性。

因为URLError是 HTTPError的父类,所以可以先选择捕获子类的错误,再去捕获父类的错误

有时候,reason属性返回的不一定是字符串,也可能是一个对象。

import socket
import urllib.request
import urllib.errortry:response=urllib.request.urlopen('https://www.baidu.com',timeout=0.01)
except urllib.error.URLError as e:print(type(e.reason))if isinstance(e.reason,socket.timeout):print('TIME OUT')

可以发现,reason属性的结果是socket.timeout类。所以,这里我们可以用isinstance()方法来判断它的类型,作出更详细的异常判断。

解析链接

urllib 库里还提供了 parse 模块,它定义了处理 URL 的标准接口,例如实现 URL 各部分的抽取、合并以及链接转换。它支持如下协议的 URL 处理:file、ftp、gopher、hdl、http、https、imap、mailto、mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、sip、sips、snews、svn、svn+ssh、telnet 和 wais。

1.urlparse()

该方法可以实现 URL 的识别和分段

from urllib.parse import urlparseresult = urlparse('https://www.baidu.com/index.html;user?id=5#comment')
print(type(result))
print(result)

这里我们利用urlparse()方法进行了一个URL 的解析。首先,输出了解析结果的类型,然后将结果也输出出来。

可以看到,返回结果是一个ParseResult类型的对象,它包含6个部分,分别是scheme,netloc,path,params,query和 fragment。一般的URL标准格式如下:

scheme://netloc/path;params?query#fragment
名字 说明 输出
scheme

《Python 3网络爬虫开发实战 》崔庆才著 第二章笔记相关推荐

  1. Python之父推荐!《Python 3网络爬虫开发实战》第二版!文末送签名版!

    很多读者会让我写爬虫方面的书籍,我也一直没写,没写的原因主要有两个,第一个就是在爬虫方面我其实不是很擅长,第二个原因就是因为在爬虫领域庆才已经做的足够好了,我写不一定能写出庆才这水平的,所以也就一直没 ...

  2. 《Python 3网络爬虫开发实战 》崔庆才著 第三章笔记

    使用urllib 它是 Python内置的HTTP请求库,也就是说不需要额外安装即可使用. 包含以下4个模块: 名字 说明 request 它是最基本的 HTTP请求模块,可以用来模拟发送请求.就像在 ...

  3. 《Python 3网络爬虫开发实战 》崔庆才著 第一章笔记

    一.请求库的安装 requests的安装 由于 requests 属于第三方库 ,也就是 python 默认不会自带这个库,所以需要我们手动安装. pip install requests selen ...

  4. Python 3网络爬虫开发实战

    分析Robots协议 书中以简书为例,对robots.txt文件分析. robots.txt 简书robots.txt文件内容如下: # See http://www.robotstxt.org/wc ...

  5. 计算机书籍- 网络爬虫开发实战

    书名: Python 3网络爬虫开发实战 作者:崔庆才 出版社:人民邮电出版社 出版时间:2018年04月 鼠标

  6. 双十二爬虫顶流崔庆才老师来图灵直播啦!快来围观啊!!!

    <Python 3网络爬虫开发实战(第2版)>上市一周便登上了京东新书销量榜第一位,延续第一版的好内容.好口碑,成为近期火爆技术圈的新书.12.12 晚 20:00 我们邀请崔庆才老师来图 ...

  7. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(3):抓取猫眼电影榜单TOP100电影,并存入Excel表格

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,如果你也要这套视频教程的话,关注我公众号[小众技术],关注后回复[PYTHON],无套路免费送你一个学习大 ...

  8. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(5):将爬虫爬取到的数据存储到TXT,Word,Excel,Json等文件中

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,此套教程共5章,加起来共有34节课,内容非常详细丰富!如果你也要这套视频教程的话,关注我公众号[小众技术] ...

  9. python3网络爬虫开发实战pdf 崔庆才 百度网盘分享

    python3网络爬虫开发实战pdf 崔庆才 百度网盘分享 介绍了如何利用Python 3开发网络爬虫,环境配置和基础知识,然后讨论了urllib.requests.正则表达式.Beautiful S ...

最新文章

  1. PythonR爬取分析赶集网北京二手房数据(附详细代码)
  2. BERT+CRF的损失函数的研究
  3. IOS常用正则表达式
  4. 我的2015学习总结及2016的技术规划(2016.02)
  5. python编程标准_Python常见编程规范总结
  6. Matlab 2022a 安装教程(手把手式教程 超简单)
  7. python 位置参数、默认参数、可变参数位置关系_python的位置参数、默认参数、关键字参数、可变参数区别...
  8. 由浅入深|让你彻底理解Python中的yield
  9. 智能门禁(6)---调用face++实现人脸检测
  10. 学习笔记:自己编译安装OpenCV+测试opencv安装是否成功
  11. 高通刷机工具使用介绍
  12. PMSM FOC控制 Matlab/Simulink仿真之Clark变换
  13. 一款优秀的开源SQL检查审核神器!再也不用担心写SQL出问题了
  14. HIVE函数集合(全)
  15. Ceres Solver从零开始手把手教学使用
  16. android_usb_msd,MSD6A828安卓智能电视主板
  17. android 权限管理 主动防御,基于SEAndroid的敏感数据主被动防御机制分析与设计
  18. 关于雷达隐身的一些事
  19. 多线程的经典案例(卖票)
  20. cloudcanal集群资源充足,任务却提示“集群机器内存不足,无法分配任务”

热门文章

  1. 图的介绍和邻接矩阵、邻接表的创建(以有向图为例)
  2. 域名被用来干嘛的?你知道吗?
  3. 一台手机如何在微信语音/视频通话时把声音录下来
  4. 堆排序——LeetCode451. Sort Characters By Frequency
  5. pipeline 语法练习
  6. PAT乙级095 解码PAT准考证
  7. 【Straw-Uniapp-uView】基于 Uniapp + uView 搭建项目基础模板
  8. VR混战已开始,看各大虚拟现实如何争春?
  9. Linux压缩pdf
  10. matlab 读二值图片,二值图像