urllib库的学习总结(python3网络爬虫开发实战项目)

urllib库是python内置的HTTP请求库,包含以下四个模块:

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

一、发送请求(request模块)

1)urlopen()(实现最基本的发送请求,官方参考文档:https://docs.python.org/3/library/urllib.request.html

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

它是一个HTTPResposne类型的对象,主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法,以及msg、version、status、reason、debugleve1、closed等属性。

urlopen()函数的API:

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

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

bytes()方法的第一个参数需要是str(字符串)类型,需要用urllib.parse模块里的urlencode()方法来将参数字典转化为字符串;第二个参数指定编码格式,这里指定为utf8。

2、timeout参数

用于设置超时时间,单位为秒。如果请求超出了设置的这个时间,还没有得到响应,就会抛出异常。

设置超时时间过后,服务器依然没有响应,于是抛出了URLError异常,该异常属于urllib.error模块,错误原因是超时。用try except语句实现抓取异常。

3、其他参数

context参数,它必须是ss1.SSLContext类型,用来指定SSL设置。
cafile和capath这两个参数分别指定CA证书和它的路径,这个在请求HTTPS链接时会有用。
cadefault 参数现在已经弃用了,其默认值为False。

2)Request(高级请求,如加入header等信息)

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

依然用urlopen()方法来发送这个请求,只不过这次该方法的参数不再是URL,而是一个Request类型的对象。通过构造这个数据结构,一方面我们可以将请求独立成一个对象,另一方面可更加丰富和灵活地配置参数。

Ruquest()函数的API:

class urllib.request. Request(url, data-None, headers={}, origin req host-None, unverifiable-False, method-None)

  • 参数url用于请求URL,这是必传参数,其他都是可选参数。
  • 参数data如果要传,必须传bytes(字节流)类型的。如果它是字典,可以先用ur1lib.parse模块里的urlencode()编码。
  • 参数headers是字典,就是请求头,=可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add header()方法添加。
  • 参数origin req host指的是请求方的host名称或者IP地址。
  • 参数unverifiable表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True。
  • 参数method是一个字符串,用来指示请求使用的方法,比如GET、POST和PUT等。

(3)高级用法

1、Handler处理器(Cookies处理,代理设置)

urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,例如default_open()、protocol_request()等。

各种Handler子类继承这个BaseHandler类,比如:

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

其他的Handler类,参考官方文档:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。

2、OpenerDirector(比Request模块更高级的功能)

OpenerDirector也称为Opener,之前用过urlopen()这个方法,实际上它就是urllib为我们提供的一个Opener。

Opener可以使用open()方法,返回的类型和urlopen()相同,利用Handler来构建Opener。

  • 验证

from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener 
from urllib. error import URLError username=' username' password=' password'
url=' http://localhost:5000/'
p=HTTPPas swordMgrwithDefaultRealm()
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在发送请求时就相当于已经验证成功了。

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

  • 代理

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

使用了ProxyHandler,参数是一个字典,键名是协议类型(比如HTTP或者HTTPS等),键值是代理链接,可以添加多个代理。
然后利用这个Handler及build_opener()方法构造一个Opener,之后发送请求即可。

  • Cookies

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)

首先必须声明一个CookieJar对,然后利用HTTPCookieProcessor来构建一个Handler,最后利用build_opener()方法构建出Opener,执行open()函数即可。

二、处理异常(error模块)

(1)URLError

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

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

如果打开一个不存在的网页会报错,但是捕获了这个异常之后,运行之后就会显示:Not Found,如果没有报错,程序就会正常运行,这样就避免了程序异常终止。

(2)HTTPError

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

code:返回HTTP状态码,比如404表示网页不存在,500表示服务器内部错误等。

reason:同父类一样用于返回错误的原因。

header:返回请求头。

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')
except error. URLError as e: 
    print(e. reason)
else: 
    print(' Request Successfully")

由于URLError是HTTPError的父类,所以可以先选择捕获子类的错误,再去捕获父类的错误,这样就可以做到先捕获HTTPError,获取它的错误状态码、原因、headers等信息。如果不是HTTPError异常,就会捕获URLError异常,输出错误原因。最后,用else来处理正常的逻辑。

三、解析链接(parse模块)

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

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

运行结果如下:
<class'urllib.parse.ParseResult'>
ParseResult(scheme='http',netloc='www.baidu.com',path='/index.html',params='user',query='id=5',fragment='comment')

利用urlparse()方法进行了一个URL的解析。先输出了解析结果的类型,然后将结果也输出出来。返回结果是一个ParseResult类型的对象,它包含6个部分,分别是scheme、netloc、path、params、query和fragment。

标准的URL链接格式:scheme://netloc/path;params?query#fragment

urlparse()的API用法:

urllib.parse.urlparse(urlstring,scheme='",allow_fragments=True)

  • urlstring:这是必填项,即待解析的URL。
  • scheme:它是默认的协议(比如http或https等)。假如这个链接没有带协议信息,会将这个作为默认的协议。
  • allowfragments:即是否忽略fragment。如果它被设置为False,fragment部分就会被忽略,它会被解析为path、parameters或者query的一部分,而fragment部分为空。

(2)urlunparse()

URL的构造urlunparse()接受的参数是一个可迭代对象,但是它的长度必须是6,否则会抛出参数数量不足或者过多的问题。

(3)urlsplit()

urlsplit()和urlparse()方法相似,只不过它不再单独解析params这一部分,只返回5个结果,params会合并到path中。

返回结果是SplitResult,也是一个元组类型,既可以用属性获取值,也可以用索引来获取。

(4)urlunsplit()

urlunsplit()也是将链接各个部分组合成完整链接的方法,传人的参数也是一个可迭代对象,例如列表、元组等,唯一的区别是长度必须为5。

(5)urljion()

urljoin()方法。我们可以提供一个base_url(基础链接)作为第一个参数,将新的链接作为第二个参数,该方法会分析base_ur1的scheme、netloc和path这3个内容并对新链接缺失的部分进行补充,最后返回结果。

from urllib.parse import urljoin 
print(urljoin('http://www.baidu.com',‘FAQ.html'))
print(urljoin('http://www.baidu.com',‘https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html?question=2'))
print(urljoin('http://www.baidu.com?wd=abc','https://cuiqingcai.com/index.php'))
print(urljoin('http://www.baidu.com','?category=2#comment'))
print(urljoin('www.baidu.com','?category=2#comment'))print(urljoin('www.baidu.com#comment','?category=2'))
运行结果如下:
http://www.baidu.com/FAQ.html
https://cuiqingcai.com/FAQ.htmlhttps://cuiqingcai.com/FAQ.html 
https://cuiqingcai.com/FAQ.html?question=2
https://cuiqingcai.com/index.php
http://www.baidu.com?category=2#comment
www.baidu.com?category=2#comment
www.baidu.com?category=2

base_ur1提供了三项内容scheme、netloc和path。如果这3项在新的链接里不存在,就予以补充;如果新的链接存在,就使用新的链接的部分。而base_ur1中的params、query 和fragment是不起作用的。

(6)urlencode()

urlencode()将字典序列化为GET请求

from urllib. parse import urlencode 
params={
' name':' germey',
' age':22
base url=' http://www. baidu. com?'
url=base_url+urlencode(params)
print(url)

运行结果如下:
http://ww.baidu.com?name=germey&age=22

参数就成功地由字典类型转化为GET请求参数了。

(7)parse_qs()

parse_qs()反序列化将它转化为字典。

(8)parse_qsl()

将参数转化为元组组成的列表。

(9)quote()

可以将内容转化为URL编码的格式。URL中带有中文参数时,有时可能会导致乱码的问题,此时用这个方法可以将中文字符转化为URL编码。

(10)unquote()

进行URL的解码。

三、分析Robots协议

robotparser模块可以实现对网站Robots协议的分析。

(1)Robots协议

Robots 协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。它通常是一个叫作robots.txt的文本文件,一般放在网站的根目录下。

当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取。如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。

User-agent:*
Disallow:/
Al1ow:/public/

User-agent 描述了搜索爬虫的名称,*代表该协议对任何爬取爬虫有效。

Allow一般和Disallow一起使用,一般不会单独使用,用来排除某些限制。/public/表示所有页面不允许抓取,但可以抓取public目录。

(2)爬虫名称

爬虫                                                                  名称                                                      名称网站
BaiduSpider                                                      百度                                                      www.baidu.com
Googlebot                                                         谷歌                                                      www.google.com
360Spider                                                          360搜索                                               www.so.com
YodaoBot                                                          有道                                                      www.youdao.com
ia_archiver                                                         Alexa                                                   www.alexa.cn
Scooter                                                              altavista                                               www.altavista.com

(3)robotparser

robotparser模块提供了一个类RobotFileParser来解析robots.txt,它可以根据某网站的robots.txt文件来判断一个爬取爬虫是否有权限来爬取这个网页。

RobotFileParser的声明:

urllib.robotparser.RobotFileParser(url=")

  • set_url():用来设置robots.txt文件的链接。如果在创建RobotFileParser对象时传入了链接,那么就不需要再使用这个方法设置了。
  • read():读取robots.txt文件并进行分析。注意,这个方法执行一个读取和分析操作,如果不调用这个方法,接下来的判断都会为False,所以一定记得调用这个方法。这个方法不会返回任何内容,但是执行了读取操作。
  • parse():用来解析robots.txt文件,传人的参数是robots.txt某些行的内容,它会按照robots.txt的语法规则来分析这些内容。
  • can_fetch():该方法传人两个参数,第一个是User-agent,第二个是要抓取的URL。返回的内容是该搜索引擎是否可以抓取这个URL,返回结果是True或False。
  • mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,你可能需要定期检查来抓取最新的robots.txt。
  • modified():它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析robots.txt的时间。

猜你喜欢

转载自blog.csdn.net/weixin_42351003/article/details/83010483