【Python3网络爬虫】 urllib库的使用

(一)使用urllib

1.库的作用,让我们在使用时不需要关心底层,不再需要关心怎么做,而是只需要关心做什么。

2.urllib is a package that collects several modules for working with URLs:

  • urllib.request for opening and reading URLs
  • urllib.error containing the exceptions(例外) raised by urllib.request
  • urllib.parse for parsing(解析) URLs
  • urllib.robotparser for parsing robots.txt files

1.request模块

The urllib.request module defines functions and classes which help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication(摘要式身份验证;主机), redirections(重导), cookies and more.

模拟浏览器的一个请求发起过程,同时还带有处理授权验证,重定向,浏览器Cookies及其他内容

import urllib.request
response = urllib.request.urlopen('http://www.baidu.com')
print(response.read().decode('utf-8')

print(type(response))——>   由此可见response是一个http.client.HTTPResponse。

对象——>方法:read() 、readinto()、getheader(name)  属性:msg,version,status 等会看一下文档

(1)urllib.requestr.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)方法

data参数表示数据,如果设置的话一定要转化成字节流编码格式,timeout的话是设置超时时间,可以用来捕捉获取服务器时间过久的异常,其他参数的话 context参数必须是ssl.SSLContext类型,用来指定SSL设置。至于这个SSL设置我也不知道是干什么的。 cafile和capath这两个参数 是指CA证书和CA证书的路径。这个在请求Https时是有用的。

(2)urllib.request.Request()  如果请求中需要加入Headers等信息,就可以利用更强大的Request类来构建

用法:

import urllib.request

request = urllib.request.Request('http://www.baidu.com')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8')

Class urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable = False.method = None)

第一个参数url用于请求url这是必传参数;第二个参数 data 如果要传必须是bytes类型,如果他是字典可以先用urllib.parse模块里的urlencode()编码;第三个参数headers是一个字典,就是请求头,我们可以用来伪装自己了,当然也可以用请求实例的add_headers()方法来添加。第四个参数origin_req_host指的是请求方的host名称或者IP地址;第五个参数 unverifiable表示这个请求是否是无法验证,默认是false,意思是有抓取权限。第六个参数method是一个字符串,用来指示请求使用的方法,比如GET POST 和PUT等。

from urllib import request,parse

url = 'http://httpbin.org/post'
headers = {
    'User-Agent':'pig browser'
    'Host':'httpbin.org'
}
dict = {
    'name':'Zen zhu'
}
data = bytes(parse.urlencode(dict),encoding='utf-8')
req = request.Request(url=url,data=data,headers=headers,method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
 

(3)高级用法  (都不是很懂,所以看之后实践过程中使用吧)

更强大的工具Handler登场  ,可以理解为各种处理器,有专门处理登陆验证的,有处理cookies的,有处理代理设置的。利用它们,我们几乎可以做到HTTP请求中的所有事。

首先介绍的BaseHandler类,它是所有Handler的父类,它提供了最基本的方法,例如default_open()、protocol_request()等

接下来,就有各种Handler子类继承这个BaseHandler类,举例如下:

HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常。

HTTPRedirectHandler:用于处理重定向(什么是重定向)

HTTPCookieProcessor:用于处理Cookies

ProxyHandler:用于设置代理,默认代理为空

HTTPPasswordMgr:用于管理密码,它维护 了用户名和密码的表

HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时

1.验证

from urllib import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler,build_opener
from urllib.error import URLError

username = '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_open()方法构建一个Opener,这个Opener在发送请求时就相当于验证成功了。

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

2.代理

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

from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener 

proxy_handler = ProxyHandler({
'http':'http://127.0.0.1:9743'
'https':'http://127.0.0.1:9743'
})

opener = build_opener(proxy_handler)
try:
    response = opener.open('http://www.baidu.com')
    print(response.read().decode('utf-8')
except URLError as e:
    print(e.reason)

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

这里使用了ProxyHandler,其参数是一个字典,键名是协议类型。简直是代理链接,可以添加多个代理。

3.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()函数即可

【Python3网络爬虫】 urllib库的使用_第1张图片

接下来,我们让他以文本形式保存下来:

import http.cookiejar,urllib.request
filename = 'cookie.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文件

【Python3网络爬虫】 urllib库的使用_第2张图片

另外LWPCookieJar同样可以读取和保存Cookies,但是保存的格式和MozillaCookieJar不一样。会保存成lwp格式的Cookies文件。

当然,也可以反过来去读取保存成的文件,这个就在之后实例玩的时候再多多训练吧。

(二)处理异常

异常处理是十分有必要的,如果不设置的话,可能目的还没达成,程序就出错跳出了。

urllib的error模块定义了由request模块产生的异常。如果出现了问题,request模块便会抛出error模块中定义的异常。(这个模块自己为自己做好了全部)

1.URLError类

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

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

2.HTTPError

它是URLEorror的子类,专门处理HTTP请求错误,比如认证请求失败等。由如下三个属性

1.code:返回HTTP状态码 2.reason同父类一样,用于返回错误原因。 3.headers返回请求头

(三)解析链接

parse模块,定义了处理URL的标准接口,例如如何实现URL各种部分的抽取合并以及链接转换 。支持的链接类型涉及大部分协议。

1.urlparse() 该方法实现了URL的识别和分段(useer-->user)

from urllib.parse import urlparse

result = urlparse('http://www.baidu.con/index.html;useer?id=5#comment')
print(type(result),result)

://前面的就是schem,代表协议;第一个/符号前的就是netloc,即域名,后面就是path,即访问路径;分号;后面params,代表参数;问号?后面是查询条件query,一般用作GET类型的URL;#后面是锚点,用于直接定位页面内部的下拉位置。

所以一个标准的链接格式:schem://netloc/path;params?query#fragment(这些也是属性)


urllib.parse.urlparse(urlstring,scheme=' ',allow_fragment=True)  -->(API用法)

urlstring:这是必填项,即待解析的URL。scheme :这个是默认协议,如果没有则会默认https

allow_fragment 默认是false 这样fagment部分为空。

2.urlunparse()

from urllib.parse import urlunparse

data = ['http','www.baidu.com','index.htm','user','a=6','comment']

print(urlunparse(data))这里data用了列表类型,当然可以选用其他类型,比如元组或者特定的数据结构。

3.urlsplit()

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

4.urlunsplit()

将链接连接起来。

5.urljoin()

有了urlunparse()与urlunsplit()两个方法,他们可以完成链接的拼合,不过前提是必须特定的长度,链接的每一部分都要分开。

生成链接的另一种方法urljoin()方法,特可以提供一个base_url作为第一个参数,将新的链接作为第二个参数,该方法会分析base_url的scheme、netloc、path这三个内容并对新链接缺失的部分进行补充,最后返回结果。

from urllib.parse import urljoin

print(urljoin('http://www.baidu.com','FAQ.html'))
print(urljoin('http://www.baidu.com','https;//cuiqingcai.com/FAQ.html'))

和书上讲的好像不一样哎。

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

通过urljoin()方法,可以实现链接的解析拼合和生成。

6.urlencode()

它在构造GET请求参数的时候非常有用

from urllib.parse import urlencode

params = {
'name':'Zen',
'age':20
}
base_url = 'http://www.baidu.com'
url = base_url+urlencode(params)
print(url)

7.parse_qs()

有了序列化就一定会反序列化。如果我们有一串GET请求参数,利用parse_qs()方法,就可以转化回字典。

8.parse_qsl()

这个方法可以用于将参数转换成元组组成的列表

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

from urllib.parse import quote

keyword = '壁纸'
url = 'https://wwww.baidu.com/s?wd'+quote(keyword) )
print(url)

10.unquote() 该方法用于解码。

(四)分析Robots协议

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

1.Robots协议

Robots协议也称作爬虫协议机器人协议,它的全名叫做网络爬虫排除标准,用来告诉爬虫和搜索引擎哪些页面可以抓取。它通常是一个robots.txt文件

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

User-agent:*

Disallow:/

Allow:/public/

User-agent 描述了爬虫的名称,设置为*表示都可以

Disallow指定了不允许抓取的目录,这里不允许抓取所有的

Allow 一般和Disallow一起使用,用来排除某些限制,这样我们表示所有的页面都不可以抓取。但是可以抓取public目录。

2.爬虫名称

搜索引擎里面基本上都是有一个爬虫名称

3.rbobotparser

了解Robots协议后,就可以使用robotsparser模块来解析robots.txt 。该模块还提供了一个类RobotFileParse,它可以根据某网站的robots.txt文件来判断一个爬虫爬取是否有权限来爬取这个网页。

用起来非常简单,只需要在构造方法中传入robots.txt的链接即可。urllib.robotparse.RobotFileParse(url=' ')

几个常用方法:

set-url():用来设置robots.txt文件的链接;

read()读取robots.txt文件并进行分析。这个方法不hi返回任何内容,但是执行了读取操作。

parse()用来解析robots.txt文件,传入的参数是robots.txt某些行的内容

can_fetch() 该方法传入两个参数,第一个是User-agent 第二个是要抓取的URL 返回的是该搜索引擎是否可以抓取。

mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,你可能需要定期检查来抓取最新的robots.txt

modified() 它同样对长时间分析和抓取的搜索爬虫有帮助,将当前时间设置为上次抓取和分析robots.txt的时间

from urllib.robotparser import RobotFileParser

rp = RobotFileParser()
rp.set_url('http://www.jianshu.com/robots.txt')
rp.read()
print(rp.can_fetch('*','http://jianshu,com/p/b67554025d7d'))

以简书为例,判断是否可以被抓取。


学习urllib库的过程中,感觉这个库很强大,基本上就可以进行很多爬取了。不过学的还不是很熟练,最近想做一个爬取学校教务在线学生照片的爬虫。去找一些教程看看吧。

【Python3网络爬虫】 urllib库的使用_第3张图片


【Python3网络爬虫】 urllib库的使用_第4张图片

等之后做好了就专门写一篇博客吧。

哈哈哈,爬虫慢慢的来。


你可能感兴趣的:(Python3网络爬虫)