Python3爬虫学习——urlib库笔记

Python3爬虫学习——urllib库

前言

本笔记仅个人认知和见解,水平有限,还请见谅。

内容大多来自Python文档和学习材料,作相应的扩充或压缩后的笔记。

没有很多实例,大多是理论知识


文章目录

  • Python3爬虫学习——urllib库
    • 前言
    • urllib库概述
    • 1.用request发送请求
      • urlopen
      • Request
      • urlopen与Request的关系与小结
      • Handler与OpenerDirector
        • Handler
        • OpenerDirector
        • 关系
        • HTTPPasswordMgr 对象与HTTPPasswordMgrWithDefaultRealm 对象
        • ProxyHandler 对象
        • Cookie处理
          • CookieJar对象
          • HTTPCookieProcessor 对象
          • MozillaCookieJar对象
          • LWPCookieJar对象
          • MozillaCookieJar对象与LWPCookieJar对象的共同方法
    • 2.在error模块处理错误
      • URLError
      • HTTPError
    • 3.利用parse解析URL
      • urlparse方法和urlunparse方法
        • urlparse方法
        • urlunparse方法
      • urlsplit方法和urlunsplit方法
      • urljoin方法
        • urlencode方法和parse_qs\parse_qsl方法
        • urlencode方法
        • parse_qs方法
        • parse_qsl方法
      • quote方法和unquote方法
        • quote方法
        • unquote方法
    • 4.分析robotparser模块
      • robotparser类的方法
    • 总结
    • 存疑

urllib库概述

urllib库是python内置库,利用它就可以实现HTTP请求发送,而不需要关心HTTP链接是如何实现的,我们只需要给定指定的URL、请求头和请求体等信息即可。

urllib库包含四个模块:

  • request:基本的HTTP请求模块,可以模拟浏览器发送请求。

  • error:异常处理模块,可以被我们用于捕获异常。

  • parse:工具模块,提供了众多URL处理方法。

  • robotparser:用于识别网站的robots.txt文件,并判断哪些网站可以爬,哪些网站不能爬。

1.用request发送请求

request库不仅可以模拟浏览器的请求发起过程,同时还具有处理授权验证(Authentication)、重定向(Redirection)、浏览器Cookie等功能。

urlopen

首先是urlopen方法的API:urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)

首先是基础用法:response = urllib.request.urlopen('https://www.python.org')

其中urlopen只由第一个参数URL,即网址,这是唯一必须指定的内容,是请求的目标站点。urlopen返回一个HTTPResponse类型的对象,储存在response里。这个用法完成了对Python官网的GET请求。

urlopen的其他参数:

  • data参数:传递该参数则表示进行POST请求,传递的内容是POST请求中的表单信息。在传递前要用bytes方法将参数转化为字节流编码格式的内容(bytes类型)。传递字典类型的数据时,应先用urllib.parse.urlencode方法进行编码。

  • timeout参数:用于设置超时时间,单位为秒。如果超过设置的时间,则发生异常。如果不指定则实用全局默认时间。超时的异常是urllib.error.URLError,其错误原因是超时,查看异常的属性reason,得到socket.timeout,意思是超时异常。

  • context参数:指定SSL的设置,参数必须是ssl.SSLContext类型。

  • cafile参数和capath参数:用于指定CA证书和其路径,用于HTTPS链接请求。

  • cadefault参数:已经弃用,可以不管,默认值为False。

Request

Request类的构造方法:class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

参数说明:

  • url:唯一必须参数,指定请求URL。

  • data:同urlopen,传输bytes类型的数据。

  • headers:headers是个字典,即请求头。既可以直接在写Request类时写这个选项的内容,也可以通过调用实例的方法add_header方法添加。通常User-Agent来伪装浏览器(默认的User-Agent为Python-urllib)。

  • origin_req_host:请求方(己方)的host名或IP地址。

  • unverifiable:表示请求是否是无法验证的。True表示确实无法验证。

  • method:请求使用的方法,类型是一个字符串,比如GET、POST。

学习小笔记:

其实这里我是完全不理解unverifiable这个参数到底是什么意思,到底是无法验证是True还是可以验证是True。所以在网上搜的时候,我发现大家的说法和书上都是一样的,“指请求无法验证,默认为 False。用户并没有足够的权限来选择接收这个请求结果,例如请求一个 HTML 文档中的图片,但没有自动抓取图像的权限,这时 unverifiable 为 True。”我觉得很离谱,原来大家都喜欢抄书,后来去python的documentation看到了原文,原来书上的东西很多都是文档里翻译来的,这句话疑似是机翻的,有点奇奇怪怪的,但是话倒是说的比较明白,“所谓无法验证的请求,是指用户没有机会对请求的 URL 做验证。”结合图片那个例子,大概就是True无法验证。

urlopen与Request的关系与小结

urllib是urllib.request的一个方法,用于获得网站响应,响应是HTTPResponse类型的对象;Request是一个类,用于构建简单的Request对象,即请求内容。Request对象可以作为参数传入urlopen方法,如此可以使用比较完整的请求获得网站响应。

对于urlopen和Request的data参数,都需要byte类型数据(字节流编码格式),于是需要byte()方法将参数转为字节流编码格式,如果是字典类型,需要先用urllib.parse.urlencode方法将字典转为字符串。

Request类的headers参数,是字典类型的数据,既可以在构建Request类时候就指定,也可以使用add_header()方法添加。

Python3爬虫学习——urlib库笔记_第1张图片

Handler与OpenerDirector

Handler

Handler可以当作Request的升级版,可以管理网站验证,代理,Cookie等Request类难以管理的请求。Handler类有一个大爹:BaseHandler类,是所有Handler类的父类。其子类有如下几类比较常用:[(源自Python文档)](urllib.request — 用于打开 URL 的可扩展库 — Python 3.9.14 文档)

  • HTTPDefaultErrorHandler:为 HTTP 错误响应定义的默认 handler,所有出错响应都会转为 HTTPError 异常。

  • HTTPRedirectHandler:一个用于处理重定向的类。

  • HTTPCookieProcessor(cookiejar=None):一个用于处理 HTTP Cookies 的类。

  • ProxyHandler(proxies=None):用于设置代理,默认代理为空。

  • HTTPPasswordMgr:维护 (realm, uri) -> (user, password) 映射数据库。即用于管理密码,维护用户名密码对照表。

  • HTTPPasswordMgrWithDefaultRealm:维护 (realm, uri) -> (user, password) 映射数据库。realm 为 None 视作全匹配,若没有其他合适的安全区域就会检索它。

  • HTTPPasswordMgrWithPriorAuth:HTTPPasswordMgrWithDefaultRealm 的一个变体,也带有 uri -> is_authenticated 映射数据库。可被 BasicAuth 处理函数用于确定立即发送身份认证凭据的时机,而不是先等待 401 响应。

  • HTTPBasicAuthHandler(password_mgr=None):处理远程主机的身份认证。 password_mgr 应与 HTTPPasswordMgr 兼容;如果给出错误的身份认证方式, HTTPBasicAuthHandler 将会触发 ValueError 。

OpenerDirector

OpenerDirector对象封装了请求方法,比如urlopen就是比较简单的请求方法。构建更高级的请求,需要用到更底层的实例完成,即OpenerDirector。OpenerDicrector有以下常用方法:[(源自Python文档)](urllib.request — 用于打开 URL 的可扩展库 — Python 3.9.14 文档)

  • OpenerDirector.add_handler(handler):handler 应为 BaseHandler 的实例。将检索以下类型的方法,并将其添加到对应的处理链中(注意 HTTP 错误是特殊情况)。代表协议,如http,为实际HTTP代码。

    • _open() — 表明该 handler 知道如何打开 protocol 协议的URL

    • http_error_() — 表明该 handler 知道如何处理代码为 type 的 HTTP 错误。

    • _error() — 表明该 handler 知道如何处理来自协议为 protocol (非http)的错误。

    • _request() — 表明该 handler 知道如何预处理协议为 protocol 的请求。

    • _response() — 表明该 handler 知道如何后处理协议为 protocol 的响应。

  • *OpenerDirector*.open(url, data=None[, timeout]):用于打开URL,其返回值和错误类型与urlopen()方法相同。超时选项仅适用于HTTP,HTTPS和FTP。

还有构建OpenerDirector的方法:

urllib.request.build_opener([handler, ...]):返回一个 OpenerDirector 实例,以给定顺序把处理函数串联起来。处理函数可以是 BaseHandler 的实例,也可以是 BaseHandler 的子类(这时构造函数必须允许不带任何参数的调用)。

关系

使用build_opener方法构建OpenerDirector实例,然后利用OpenerDirector实例的方法open()打开URL,得到网站响应。
Python3爬虫学习——urlib库笔记_第2张图片

HTTPPasswordMgr 对象与HTTPPasswordMgrWithDefaultRealm 对象

HTTPPasswordMgr 对象与HTTPPasswordMgrWithDefaultRealm 对象都有以下方法:

  • HTTPPasswordMgr.add_password(realm, uri, user, passwd)
    uri 可以是单个 URI,也可以是 URI 列表。realm、user 和 passwd 必须是字符串。这使得在为 realm 和超级 URI 进行身份认证时,(user, passwd) 可用作认证令牌。

  • HTTPPasswordMgr.find_user_password(realm, authuri)
    为给定 realm 和 URI 获取用户名和密码。如果没有匹配的用户名和密码,本方法将会返回 (None, None) 。对于 HTTPPasswordMgrWithDefaultRealm 对象,如果给定 realm 没有匹配的用户名和密码,将realm设为None。

这两个对象主要用于解决请求网站时,网站开启了基本身份认证(HTTP Basic Access Authentication)。可以在实例化对象时就给定(realm, uri, user, passwd)的内容。

ProxyHandler 对象

ProxyHandler({'协议类型':'代理链接','协议类型':'代理链接',...})即可构建一个ProxyHandler实例。然后用上图的方法可以发送请求。

Cookie处理
CookieJar对象

CookieJar对象包含在http.cookiejar内,需要先import。创建实例的方法:cookie = http.cookiejar.CookirJar()。这样创建出来的是一个空Cookie,可以用于Handler构建并用于请求网站,以此获得Cookie。

HTTPCookieProcessor 对象

用于构建handler,用法:handler = urllib.request.HTTPCookieProcessor(CookieJar)

MozillaCookieJar对象

MozillaCookieJar对象是CookieJar的子类,用于处理与Cookie和文件相关的事件如读取和保存。对于的文件格式是Mozilla型浏览器Cookie格式(cookies.txt文件格式)。用法:

  • 创建/打开:cookie = http.cookiejar.MozillaCookieJar(filename)
LWPCookieJar对象

与MozillaCookieJar对象类似,LWPCookieJar对象用于处理LWP(libwww-perl)格式(Set-Cookie3文件格式)的Cookie的读取和保存。

  • 创建/打开: cookie = http.cookiejar.LWPCookieJar(filename)
MozillaCookieJar对象与LWPCookieJar对象的共同方法

加载:cookie.load(filename=None, ignore_discard=False, ignore_expires=False)ignore_discard: 若为True,即使设定了丢弃 cookie 仍然保存它们,意思是保存会话Cookie。 ignore_expires: 若为True,即使 cookie 已超期仍然保存它们。旧的 cookie 将被保留,除非是被新加载的 cookie 所覆盖。

保存:cookie.save(filename=None, ignore_discard=False, ignore_expires=False)ignore_discard: 若为True,即使设定了丢弃 cookie 仍然保存它们,意思是保存会话Cookie。 ignore_expires: 若为True,即使 cookie 已超期仍然保存它们。文件如果已存在则会被覆盖,这将清除其所包含的全部 cookie。 已保存的 cookie 可以使用 load() 或 revert() 方法来恢复。

其他方法见Python文档

2.在error模块处理错误

URLError

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

用法:exception urllib.error.URLError as objectname

其属性只有一个:reason,即返回错误的原因(如Not Found)。

HTTPError

HTTPError是URLError的子类之一,专门处理HTTP请求错误(如认证请求等特殊HTTP错误)。

用法:exception urllib.error.HTTPError as objectname

属性:

  • code:返回HTTP状态码,如404等,

  • reason:返回错误原因(如Not Found)。

  • headers:返回请求头

需要注意,reason的返回值有可能不是字符串类,有可能是一个对象,如超时错误的返回值

try:
    response = urllib.request.urlopen('https://emorepitg.top', timeout=0.01)
except urllib.error.URLError as e:
    print(type(e.reason))
    if isinstance(e.reason,socket.timeout):
        print('TIME OUT')
        
<class 'socket.timeout'>
TIME OUT

如上,超时错误的reason属性是一个socket.timeout类,可以用isinstance方法检查来判单是否是超时错误。也可以直接打印reason属性,因为这个类的附带值是一个字符串,其值总是 “timed out”。

3.利用parse解析URL

urllib内的parse模块提供了若干解析URL的方法,它支持的URL协议有:file, ftp, gopher, hdl, http, https, imap, mailto, mms, news, nntp, prospero, rsync, rtsp, rtspu, sftp, shttp, sip, sips, snews, svn, svn+ssh, telnet, wais, ws, wss.

urlparse方法和urlunparse方法

urlparse方法

该方法对URL解析,然后输出解析结果的类型(urllib.parse.ParseResult)以及结果本身(字符串)。

用法:urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

传入字符型URL,在URL没有指定协议的时候用scheme指定协议(如果URL没有协议的时候用scheme指定协议,则解析后的netloc会被放在path内,是个很奇怪的问题,由于没有实战,并不知道其作用,留疑)。

print(urllib.parse.urlparse('https://docs.python.org/zh-cn/3.9/library/urllib.parse.html?highlight=urllib%20parse#module-urllib.parse'))
ParseResult(scheme='https', netloc='docs.python.org', path='/zh-cn/3.9/library/urllib.parse.html', params='', query='highlight=urllib%20parse', fragment='module-urllib.parse')
print(urllib.parse.urlparse('docs.python.org/zh-cn/3.9/library/urllib.parse.html?highlight=urllib%20parse#module-urllib.parse',scheme='https'))
ParseResult(scheme='https', netloc='', path='docs.python.org/zh-cn/3.9/library/urllib.parse.html', params='', query='highlight=urllib%20parse', fragment='module-urllib.parse')

解析出的结果是ParseResult类型对象,包含六个部分:

scheme 0 URL协议 scheme 参数
netloc 1 网络位置部分 空字符串
path 2 分层路径 空字符串
params 3 No longer used always an empty string
query 4 查询组件 空字符串
fragment 5 片段识别 空字符串
urlunparse方法

urlparse的对立方法,将上述六个参数构造成URL。参数可以是列表类型,也可以是元组等,但必须是长度为6的可迭代对象,其返回值是一个字符串。

用法:urllib.parse.urlunparse(parts)

urlsplit方法和urlunsplit方法

与urlparse方法和urlunparse方法类似,urlsplit方法可以解析URL,但是这一方法不再单独解析params这一个部分,而是合并到path中去。其返回值是一个urllib.parse.SplitResult类。同样地,urlunsplit只需要五个参数即可。

urljoin方法

通过合并一个 “基准 URL” (base) 和另一个 URL (url) 来构造一个完整 (“absolute”) URL。

用法:urllib.parse.urljoin(base, url, allow_fragments=True)

>>> urllib.parse.urljoin('https://www.emorepitg.top/index.html','?category=2')
'https://www.emorepitg.top/index.html?category=2'
>>> urllib.parse.urljoin('https://www.emorepitg.top/index.html','https://www.csdn.net/index.php?category=2')
'https://www.csdn.net/index.php?category=2'

“基准URL”提供scheme、netloc和path三个参数(即https://emorepitg.top/index.html),如果“另一个URL“不存在这三项,就用”基准URL“去补,如果”另一个URL“存在这三个参数,”基准URL”的内容就不起作用

urlencode方法和parse_qs\parse_qsl方法
urlencode方法

将字典类型转化为URL适用的字符串类型,即将字典转为key=value 对,并用是&连接的字符串。

用法:urllib.parse.urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus)

当使用二元组序列作为 query 参数时,每个元组的第一个元素为键而第二个元素为值。 值元素本身也可以为一个序列,在那种情况下,如果可选的形参 doseq 的值为 True,则每个键的值序列元素生成单个 key=value 对(以 ‘&’ 分隔)。 被编码的字符串中的参数顺序将与序列中的形参元素顺序相匹配。

safe, encoding 和 errors 形参会被传递给 quote_via (encoding 和 errors 形参仅在查询元素为 str 时会被传递)。

parse_qs方法

将链接中用&连接的key=value对转化为字典类型,但是需要注意的是,字典的值是一个列表。

>>> urllib.parse.parse_qs('name=Emore&age=20')
{'name': ['Emore'], 'age': ['20']}
>>> type(urllib.parse.parse_qs('name=Emore&age=20')['name'])
list
parse_qsl方法

同上parse_qs方法。将链接中用&连接的key=value对转化为元组类型的列表。

>>> urllib.parse.parse_qsl('name=Emore&age=20')
[('name', 'Emore'), ('age', '20')]

quote方法和unquote方法

quote方法

quote方法将URL中的中文转化为URL编码的格式。

>>> urllib.parse.quote('甲寅')
'%E7%94%B2%E5%AF%85'
unquote方法

quote方法的对立方法,将URL编码格式转化为中文(解码)

4.分析robotparser模块

urllib.robotparser是robots.txt语法分析模块。Robots协议(也称为爬虫协议、机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。

robotparser类的方法

urllib.robotparser.RobotFileParser(url='')
这个类提供了一些可以读取、解析和回答关于 url 上的 robots.txt 文件的问题的方法。

set_url(url)
设置指向 robots.txt 文件的 URL。RobotFileParser对象创建时没有给url时调用来设置url。

read()
读取 robots.txt URL 并将其输入解析器。需要注意,如果获得了RobotFileParser对象但是没有调用过read方法,则别的所有解析方法返回值都是False,所以一定要记得调用。

parse(lines)
解析行参数。

can_fetch(useragent, url)
判断useragent是否可以抓取url,返回True或False。

mtime()
返回最近一次获取 robots.txt 文件的时间。 这适用于需要定期检查 robots.txt 文件更新情况的长时间运行的网页爬虫。

modified()
将最近一次获取 robots.txt 文件的时间设置为当前时间。

总结

至此,urllib库的四个模块大致学习完毕,其中有一些小地方需要注意的。

  • urllib.request模块中,data参数需要用byte类型

  • urllib.request.Request模块中,headers参数是字典类型

  • 搞清楚request和urlopen的关系,Handler与OpenerDirector的关系

  • urlparse方法在URL没有带scheme时,将scheme以参数导入,netloc会跑到path内

  • urlunparse方法必须是六个参数的可迭代对象

  • urlunsplit方法必须是五个参数的可迭代对象

  • parse_qs解析出的字典的值是一个列表

  • quote方法和unquote方法对字符串和URL编码处理

  • robotparser对象处理前需要用read方法

存疑

如果URL没有协议的时候用scheme指定协议,则解析后的netloc会被放在path内,是个很奇怪的问题,由于没有实战,并不知道其作用。

print(urllib.parse.urlparse('https://docs.python.org/zh-cn/3.9/library/urllib.parse.html?highlight=urllib%20parse#module-urllib.parse'))
ParseResult(scheme='https', netloc='docs.python.org', path='/zh-cn/3.9/library/urllib.parse.html', params='', query='highlight=urllib%20parse', fragment='module-urllib.parse')
print(urllib.parse.urlparse('docs.python.org/zh-cn/3.9/library/urllib.parse.html?highlight=urllib%20parse#module-urllib.parse',scheme='https'))
ParseResult(scheme='https', netloc='', path='docs.python.org/zh-cn/3.9/library/urllib.parse.html', params='', query='highlight=urllib%20parse', fragment='module-urllib.parse')

你可能感兴趣的:(Python3爬虫笔记,Python学习笔记,爬虫,学习,python)