(一)使用urllib
1.库的作用,让我们在使用时不需要关心底层,不再需要关心怎么做,而是只需要关心做什么。
2.urllib
is a package that collects several modules for working with URLs:
urllib.request
for opening and reading URLsurllib.error
containing the exceptions(例外) raised by urllib.request
urllib.parse
for parsing(解析) URLsurllib.robotparser
for parsing robots.txt
files1.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))——>
对象——>方法: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()函数即可
接下来,我们让他以文本形式保存下来:
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文件
另外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库的过程中,感觉这个库很强大,基本上就可以进行很多爬取了。不过学的还不是很熟练,最近想做一个爬取学校教务在线学生照片的爬虫。去找一些教程看看吧。
等之后做好了就专门写一篇博客吧。
哈哈哈,爬虫慢慢的来。