当前位置:网站首页 > 技术博客 > 正文

urllib3



在Python2中,有urllib和urllib2两个库来实现请求的发送,而在Python3中,统一为了urllib,其官方文档链接为:https://docs.python.org/3/library/urllib.html。urllib是Python内置的HTTP请求库,它包含4个模块:

  • request:最基本的HTTP请求模块,可以用来模拟发送请求。
  • error:异常处理模块,如果出现请求错误,可以捕获异常,然后进行重试或其他操作。
  • parse:工具模块,提供了许多URL处理方法,如拆分、解析、合并等。
  • robotparser:主要用于识别网站的rebots.txt文件,然后判断哪些网站可以爬,哪些网站不可以爬。

urllib的request模块提供了最基本的构造HTTP请求的方法,使用它可以方便地实现请求的发送并得到响应,同时它还带有处理授权验证(authentication)、重定向(redirection)、浏览器Cookies以及其他内容。

1. urlopen( )

使用urlopen( )函数可以发送一个请求,urlopen( )函数的完整参数列表如下:

 

用法可参考官方文档https://docs.python.org/3/library/urllib.request.html。

1)使用urlopen( )方法爬取网页源代码,url参数用于指定要请求的URL路径(未指定data参数时,默认使用GET请求方法)

 

​ urlopen( )函数返回的是一个HTTPResponse对象,它包含了read( )、readinto( )、getheader(name)、getheaders( )、fileno( )等方法, 以及msg、version、status、reason、debuglevel、closed等属性。

 

2)data参数可以设置请求要传递的参数,使用时需要使用bytes( )方法将参数转化为字节流编码格式的内容,即bytes类型;并且如果 使用了data参数,则请求方法就不再是GET方法了,而是POST方法。

 

​ 这里传递了一个参数word,值是hello。它需要被转码成bytes(字节流)类型。其中转字节流采用了bytes( )方法,该方法的第一个参 数是字符串类型,需要用urllib.parse模块里的urlencode( )方法将参数转换为字符串,bytes( )方法第二个参数指定编码格式。执行后, 通过观察返回的响应头里的Content-Type字段的值可以知道使用的是POST请求方法。

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

 

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

 

5)除了url、data、timeout这些参数外,还有context参数,它必须是ssl.SSLContext类型,用来制定SSL设置。此外,cafile和capath这两 个参数分别指定CA证书的和它的路径,这个在请求HTTPS链接时会有用,cadefault参数已经启用了,其默认值为false。


2. Request

使用urlopen( )方法可以实现最基本请求的发起,但不足以构建一个完整的请求。如果请求中需要加Headers等信息,则需要使用Request类来构建。它的构造方法如下:

 

url是必选参数,其余都是可选参数。

  • url:请求的URL。。
  • data:请求的参数。必须传bytes(字节流)类型的,如果是字典,可以先用urllib.parse模块里的urlencode( )编码。
  • headers:请求头。它是一个字典类型的数据。可以在构造Request对象时通过headers参数直接构造,也可以由Request对象调用add_header( )方法添加。添加请求头最常用的就是通过修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,比如伪装火狐浏览器,可以将请求头中的User-Agent字段值设置为:

    ​ Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/ Firefox/95.0

    可以去某个浏览器发送请求然后查看请求中的User-Agent字段的值。

  • origin_req_host:请求方的host名称或者IP地址。
  • unverifiable:该请求是否是无法验证的,默认为False,意思是说用户没有足够权限来选择接收这个请求的结果。例如,请求一个HTML文档中的图片,但是没有自动抓取图像的权限,这时unverifiable的值就是True。
  • method:请求使用的方法,类型是一个字符串,比如GET、POST。

通过Request类,一方面我们可以将请求独立成一个对象,另一方面可以更加丰富和灵活地配置参数。

1)基本使用

 

​ 它依旧是使用urlopen( )方法发送请求,只不过这次该方法的参数不再是URL,而是一个Request类型的对象。

2)设置请求头、请求参数。

 


3. Handler、Opener

实现验证、代理设置、Cookies处理等功能需要使用Handler和Opener。可以将Handler理解为各种处理器,有专门处理登录验证的,有处理Cookie的,有处理代理设置的,利用它们,几乎可以做到HTTP请求中所有的事情。urllib.request模块里的BaseHandler类,是其他所有Handler的父类,提供了最基本的方法,例如default_open( )、protocol_request( )等。它的常用子类有:

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

更多的Handler类可参考官方文档:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。Handler需要和Opener(Opener对应的类为OpenerDirector)组合使用,通过Handler对象可以构建Opener对象,Opener对象可以调用open( )方法,open( )方法的返回类型和urlopen( )是一样的。

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

​ 请求这样带有验证的页面时,可以借助HTTPBasicAuthhandler完成,代码如下:

 

​ 该案例中,如果验证成功,则打印tomcat管理页的源代码。

2)实现代理。在做爬虫的时候,免不了要使用代理,如果要添加代理,可以使用ProxyHandler,其参数是一个字典,字典中键名协议类 型(比如HTTP或者HTTPS等),键值是代理连接,可以添加多个代理。

 

3)获取网站的Cookie。首先,必须声明一个CookieJar对象,然后利用HTTPCookieProcessor来构建一个Handler,最后利用 build_opener( )方法构建Opener,执行open( )方法即可。

 

4)获取网站的Cookie并保存为文件。

 

​ 这里将CookieJar换成了MozillaCookieJar,它在生成文件时会用到,是CookieJar的子类,可以用来处理Cookies和文件相关的事件, 比如读取和保存Cookies,本例中将Cookies保存成了Mozilla型浏览器的Cookies格式,运行之后当前目录下生成了一个cookies.txt文 件,内容如下:


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

 

​ 此时生成的Cookies文件中的格式如下:

5)生成Cookies文件后,后续过程中会读取Cookies文件并进行利用。以LWPCookieJar格式的Cookie文件为例

 

以上是urllib库中request模块的基本用法,想实现更多的功能,可以参考官方文档:https://docs.python.org/3/library/urllib.request.html


urllib库中的error模块定义了由request模块产生的异常,使用request模块发送请求时,如果出现错误,便会抛出error模块中定义的异常。

1. URLError

URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,request模块产生的异常都可以通过捕获这个类来处理。它有一个属性reason,表示错误的原因。

 

2. HTTPError

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

  • code:HTTP状态码。
  • reason:同父类一样,表示错误的原因。
  • headers:请求头

1)捕获异常,查看HTTPError的三个属性。

 


2)因为URLError类是HTTPError的父类,所以在捕获异常时应先选择捕获子类的异常,再去捕获父类的异常。写法如下:

 

​ 以上案例是一个较好的异常处理方法的格式。

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

 


​ 设置超时时间0.01秒来强制抛出timeout异常,从运行结果中可以看到,reason属性的类型是socket.timeout类,所以可以使用 isinstance( )方法来判断它的类型,作出更详细的有针对性的处理。


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

1. urlparse( )

urlparse( )方法可以实现URL的识别和分段。API用法如下:

 

其中,urlstring参数是必选项,其余都是可选的。

  • urlstring:待解析的URL。
  • scheme:默认的解析协议。如果待解析的URL中没有包含协议信息,会将scheme指定的协议作为默认的协议,只在URL中不包含scheme信息时才生效。
  • allow_fragments:是否允许解析fragment,默认值为True,如果为False,则fragment部分会被忽略,它会被解析为path、param或者query的一部分,而fragment部分为空。

urlparse( )方法的返回结果是一个ParseResult类型的对象,它包含6个部分,分别是scheme(协议)、netloc(域名)、path(访问路径)、params(参数)、query(查询条件,一般用作GET类型的URL)、fragment(锚点)。一般的URL都会由这6部分组成。

1)urlparse( )方法的基本使用,使用它解析一个URL。

 


2)如果指定了scheme参数,且URL中没有包含scheme参数时,则解析时使用scheme参数指定的协议。

 


​ 由于URL中没有包含scheme,而通过scheme参数指定了协议,所以从运行结果可以看出,解析时使用的是scheme指定的协议,但由 于URL中未指定scheme,所以解析的netloc为空。

3) 如果URL中包含了scheme,而同时又指定了scheme参数,则解析时默认使用URL中的scheme。

 


​ 从运行结果可以看出,解析时使用的是URL中的scheme。

4)如果allow_fragments值为False,则URL中包含的fragment将会被解析为path、params或者query的一部分。

 


​ 可以看出,fragment被解析为了query的一部分,而fragment为空。如果URL中不包含params和query:

 


​ 可以看出,当URL中不包含params和query时,fragment被解析为了path的一部分,而fragment为空。

5)urlparse( )的返回结果ParseResult实际上是一个元组,我们可以用索引顺序来获取,也可以用属性名获取。

 

2. urlunparse( )

与urlparse( )对立的方法是urlunparse( ),它用于构造一个URL,接收的参数是一个可迭代的对象(如列表、元组等),长度必须是6,否则会抛出参数数量不足或者过多的问题。

 

3. urlsplit( )

urlsplit( )方法与urlparse( )方法类似,只不过urlsplit( )方法不单独解析params部分,而是将其解析到path部分中。

 

它返回的是SplitResult类型的对象,其实是一个元组类型,所以既可以用属性获取值,也可以用索引来获取。

 

4. urlunsplit( )

与urlsplit( )对立的方法是urlunsplit( ),它用于构造一个URL,接收的参数是一个可迭代的对象(如列表、元组等),长度必须是5,否则会抛出参数数量不足或者过多的问题。

 

5. urljoin( )

除了使用urlunparse( )和urlunsplit( )方法可以构造URL,还可以通过urljoin( )方法构造URL。使用urljoin( )方法时,提供一个base_url(基础URL)作为第一个参数,将新的URL作为第二个参数,该方法会分析base_url中的scheme、netloc和path这3个内容并对新的URL缺失的部分进行补充,最后补充后的URL。

 


可以发现,base_url提供了三项内容scheme、netloc、path,如果这3项在新的URL中不存在,就予以补充;如果新的URL中已存在,不做替换。而base_url中的params、query、fragment是不起作用的。


6. urlencode( )

urlencode( )方法在构造请求参数时使用。

1)在GET请求方式中构造请求参数。

 

2)在POST请求方式中构造请求参数。

 

7. parse_qs( )

parse_qs( )方法可以将代表参数的字符串转回为字典。

 

8. parse_qsl( )

与parse_qs( )方法功能类似,将代表参数的字符串转换为元组组成的列表。

 

返回结果是一个列表,列表中每一个元素都是一个元组,元组的第一个内容是参数名,第二个内容是参数值。


9. quote( )

quote( )方法可以将内容转换为URL编码的格式。当URL中带有中文参数时,会导致乱码问题,此时可以用quote( )方法将其转换为URL编码。

 

10. unquote( )

unquote( )与quote( )方法对应,可以对URL编码的字符串进行解码。

 



利用urllib库中的robotparser模块,可以实现对网站Robots协议的分析。

1. Robots协议

Robots协议也称作爬虫协议、机器人协议,它的全名叫做网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些页面不可以抓取。它通常是一个名为robots.txt的文本文件,一般放在网站的根目录下。当搜索爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在robots.txt文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取;如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。

1)robots.txt文件样例1。所有爬虫都不可以爬取任何页面,但public目录可以爬取。

 
  • User-agent:描述了搜索爬虫的名称,*则表示该协议对所有爬虫有效。比如User-agent:Baiduspider表示对百度爬虫是有效的。如果有多条User-agent记录,就会有多个爬虫会受到爬取限制,但至少需要指定一条。
  • Disallow:指定不允许爬取的目录,/表示所有页面都不允许爬取。
  • Allow:一般和Disallow一起使用,不会单独使用,用来排除Disallow指定的规则,指定除了Disallow指定的页面外,哪些页面可以抓取。

2)robots.txt文件样例2。 禁止爬虫爬取任何目录。

 

3)robots.txt文件样例3。 允许爬虫爬取任何页面。

 

4)robots.txt文件样例。只允许名称为WebCrawler的爬虫爬取任何页面,不允许其他爬虫爬取任何页面。

 

2. 爬虫名称

爬虫是有名称的,常见的搜索爬虫的名称及对应的网站。

爬虫名称所属网站BaiduSpider百度www.baidu.comGooglebot谷歌www.google.com360Spider360搜索www.so.comYodaobot有道www.youdao.comia_archiverAlexawww.alexa.cnScooteraltavistawww.altavista.com

3. robotparse模块的使用

robotparse模块提供了一个RobotFileParser类,该类可以根据网站的robots.txt文件来判断一个爬虫是否有权限来爬取这个网页。该类使用简单,只需要在构造方法里传入robots.txt的链接即可。

 

url参数是可选的,如果在构造时没有传入url,最后通过set_url( )方法设置也是可以的。RobotFileParser类常用方法如下:

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

1)判断简书某些网页是否可以爬取。

 

在这里插入图片描述
2)使用parse( )方法执行读取和分析操作。

 

有些时候,判断是否可爬时返回False或者爬虫运行出现403拒绝服务现象,在发送请求时设置请求头中User-Agent和Host就可能返回True了。


版权声明


相关文章:

  • rapid程序是什么意思2024-12-02 12:30:00
  • 数据库表设计例子简单2024-12-02 12:30:00
  • 线程安全的类有哪些2024-12-02 12:30:00
  • 多目标优化定义2024-12-02 12:30:00
  • selenium自动化测试报告2024-12-02 12:30:00
  • 一句话木马的操作流程2024-12-02 12:30:00
  • 如何封装win10系统 详细图文教程2024-12-02 12:30:00
  • okhttps2024-12-02 12:30:00
  • arm架构cpu有哪些2024-12-02 12:30:00
  • opengl 教程2024-12-02 12:30:00