终于开始写爬虫代码我们先了解一下Urllib库,它是Python内置的HTTP请求库,也就是说我们不用额外安装就可以使用,它包含四个模块:第一个模块request,这是最基本的HTTP请求模块,我们可以用它来模拟发送请求,就像在浏览器中输入URL并回车一样,只需要给library的方法传入URL和额外的参数,这个过程可以被模拟。第二个错误模块是异常处理模块。如果有请求错误,我们可以捕获这些异常,然后进行重试或其他操作,以保证程序不会意外终止。第三个parse模块是一个工具模块,提供了很多的URL处理方法,比如拆分、解析、合并等等。第四个模块是robotparser,主要用来识别网站的robots.txt文件,进而判断哪些网站可以抓取,哪些网站不能抓取。它不太实用。这里我们重点介绍前三个模块。1.发送请求使用Urllib的request模块,我们可以很方便的发送一个Request,得到一个Response1,urlopen()。urllib.request模块提供了最基本的构造HTTP请求的方法,可以模拟浏览器发起请求的过程,同时还处理authenticaton(授权验证)、redirections(重定向)、cookies(浏览器Cookies)等内容。让我们感受一下它的力量。以Python官网为例。让我们抓取这个页面:importurllib.requestresponse=urllib.request.urlopen('https://www.python.org')print(response.read().decode('utf-8'))结果操作如下:接下来我们看它返回什么,使用type()方法输出Response的类型。importurllib.requestresponse=urllib.request.urlopen('https://www.python.org')print(type(response))输出结果如下:通过输出结果,可以发现是一个HTTPResposne类型的对象。主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法以及msg、version、status、reason、debuglevel、closed等属性。得到这个对象后,我们把它赋值给response变量,然后我们就可以调用这些方法和属性来获取返回结果的一系列信息。比如调用read()方法可以获得返回的网页内容,调用status属性可以获得返回结果的状态码,比如200表示请求成功,404表示没有找到网页,ETC。这里再举个例子感受下:getheader('Server'))结果如下:200[('Server','nginx'),('Content-Type','text/html;charset=utf-8'),('X-框架选项','SAMEORIGIN'),('X-Clacks-Overhead','GNUTerryPratchett'),('Content-Length','47397'),('Accept-Ranges','bytes'),('Date','Mon,01Aug201609:57:31GMT'),('Via','1.1varnish'),('Age','2473'),('Connection','close'),('X-Served-By','cache-lcy1125-LCY'),('X-Cache','HIT'),('X-Cache-Hits','23'),('Vary','Cookie'),('Strict-Transport-Security','max-age=63072000;includeSubDomains')]nginx可以看到三个输出分别输出响应的状态码,响应的头信息,通过A参数Server获取headers中的Server值,结果为nginx,表示服务器是nginx搭建的。使用上面最基本的urlopen()方法,我们就可以完成简单网页最基本的GET请求爬取。如果我们想给链接传递一些参数怎么办?我们先看urlopen()函数的API:urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=None)可以发现除了第一个可以作为参数传递的URL之外,我们还可以传递其他的内容,比如data(附加数据)、timeout(超时)等等。下面我们详细描述这些参数的用法:data参数data参数可选,如果要添加数据,如果是字节流编码格式的内容,也就是bytes类型,可以通过bytes()方法,另外如果传了data参数,那么它的请求方式就不再是GET请求,而是POST。下面用一个例子来感受一下:('http://httpbin.org/post',data=data)print(response.read())这里我们传递了一个参数word,值为hello。需要转码为bytes(字节流)类型。bytes()方法的第一个参数需要是str(字符串)类型,需要使用urllib.parse模块中的urlencode()方法将参数字典转成字符串。第二个参数指定编码格式,这里指定为utf8。timeout参数timeout参数可以设置超时时间,单位秒,意思是如果请求超过设置的时间还没有得到响应,就会抛出异常。如果未指定,将使用全局默认时间。它支持HTTP、HTTPS、FTP请求。因此,我们可以通过设置这个超时时间来控制一个网页如果长时间没有响应就跳过它的抓取。这个操作可以通过使用tryexcept语句来实现。代码如下:importsocketimporturllib.requestimporturllib.errortry:response=urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)excepturllib.error.URLErrorase:ifisinstance(e.reason,socket.timeout):print('TIMEOUT')其他参数包括context参数,必须是ssl.SSLContext类型,用于指定SSL设置。cafile和capath这两个参数是指定CA证书及其路径,在请求HTTPS链接时会有用。cadefault参数现已弃用,默认为False。以上解释了urlopen()方法的用法。这个基本功能可以用来完成简单的请求和网页爬取。更详细的信息可以参考官方文档:https://docs.python.org/3/lib....2.请求由上面我们知道,最基本的请求可以使用urlopen发起()方法,但这几个简单的参数不足以构造一个完整的请求。如果需要在请求中加入Headers等信息,我们可以使用更强大的Request类来构建请求。首先我们用一个例子来感受一下Request的用法:).decode('utf-8'))可以发现我们还是使用urlopen()方法来发送这个请求,只不过这次urlopen()方法的参数不再是一个URL,而是一个Request类型的对象.通过构建这个数据结构,一方面我们可以将请求分离成一个对象,另一方面可配置的参数更加丰富灵活。下面我们来看看可以构造什么样的参数Request。它的构造方法如下:classurllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)第一个url参数是请求URL,这是一个必须的参数,其他为可选参数。如果要传递第二个数据参数,则必须是字节类型(字节流)。如果是字典,可以先在urllib.parse模块中使用urlencode()进行编码。第三个headers参数是一个字典,就是RequestHeaders。可以直接通过headers参数构造Request,也可以调用Request实例的add_header()方法添加。RequestHeaders最常见的用法是修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,我们可以修改它来伪装浏览器。第四个origin_req_host参数是指请求者的主机名或IP地址。第五个unverifiable参数是指请求是否不可验证,默认为False。这意味着用户没有足够的权限来选择接收这个请求的结果。比如我们在HTML文档中请求一张图片,但是我们没有自动抓取图片的权限,那么unverifiable的值为True。第六个method参数是一个字符串,表示请求使用的方法,如GET、POST、PUT等。写个例子:fromurllibimportrequest,parseurl='http://httpbin.org/post'headers={'User-Agent':'Mozilla/4.0(compatible;MSIE5.5;WindowsNT)','Host':'httpbin.org'}dict={'name':'Germey'}data=bytes(parse.urlencode(dict),encoding='utf8')req=request.Request(url=url,data=data,headers=headers,method='POST')response=request.urlopen(req)print(response.read().decode('utf-8'))这里构造一个Request,有四个参数,url为请求URL,headers中指定User-Agent和Host,传入的参数数据使用urlencode()和bytes()方法转换为字节流,指定请求方式为POST。通过观察结果,我们可以发现我们已经成功设置了data、headers和method。此外,还可以使用add_header()方法添加标头。req=request.Request(url=url,data=data,method='POST')req.add_header('User-Agent','Mozilla/4.0(compatible;MSIE5.5;WindowsNT)')这样,我们构造一个Request来实现请求的发送是比较方便的。2.异常处理我们了解了Request的发送过程,但是在网络不好的情况下出现异常怎么办呢?这时,如果我们不处理这些异常,程序可能会报错并终止运行,所以异常处理还是很有必要的。urllib的错误模块定义了请求模块引发的异常。如果出现问题,请求模块将抛出错误模块中定义的异常。主要有两个处理异常类,URLError和HTTPError。下面写个例子:fromurllibimportrequest,errortry:response=request.urlopen('http://cuiqingcai.com/index.htm')excepterror.URLErrorase:print(e.reason)我们打开一个非-已存在的页面,按道理应该会报错,但是此时我们捕获到URLError异常,运行结果如下:NotFoundfromurllibimportrequest,errortry:response=request.urlopen('http://cuiqingcai.com/index.htm')excepterror.HTTPErrorase:print(e.reason,e.code,e.headers,seq='\n')运行结果:NotFound404Server:nginx/1.4.6(Ubuntu)Date:2016年8月3日星期三08:54:22GMTContent-Type:text/html;charset=UTF-8Transfer-Encoding:chunkedConnection:closeX-Powered-By:PHP/5.5.9-1ubuntu4。14Vary:CookieExpires:Wed,11Jan198405:00:00GMTCache-Control:no-cache,must-revalidate,max-age=0Pragma:no-cacheLink:;rel="https://api.w.org/"HTTPError,它有三个属性。code,返回HTTPStatusCode,即状态码,比如404网页不存在,500内部服务器错误等。reason,和父类一样,返回错误原因。标头,返回请求标头。因为URLError是HTTPError的父类,我们可以选择先捕获子类的错误,再捕获父类的错误,所以上面的代码最好写成这样:fromurllibimportrequest,errortry:response=request.urlopen('http://cuiqingcai.com/index.htm')excepterror.HTTPErrorase:print(e.reason,e.code,e.headers,sep='\n')excepterror.URLErrorase:print(e.reason)else:print('RequestSuccessfully')这样我们就可以先捕获HTTPError,得到它的错误状态码,原因,Headers等详细信息。如果不是HTTPError,则捕获URLError异常并输出错误原因。最后用else处理正常逻辑,是比较好的异常处理方式。3.实例抓取豆瓣电影排名importurllib.parseimporturllib.requesturl='https://movie.douban.com/'herders={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/85.0.4183.102Safari/537.36','Referer':'https://movie.douban.com/','Connection':'keep-alive'}req=urllib.request.Request(url,headers=herders)response=urllib.request.urlopen(req)html=response.read().decode('utf8')print(html)结果...豆瓣电影....以下省略。4.Robots协议分析利用urllib的robotparser模块,我们可以分析网站的Robots协议1Robots协议Robots协议又叫爬虫协议,机器人协议.(RobotsExclusionProtocol),用来告诉爬虫和搜索引擎哪些网页可以抓取,哪些不可以抓取,一般是robots.txt文本文件,一般放在网站的根目录下.搜索爬虫访问站点时,首先会检查站点根目录下是否有robots.txt文件。如果存在,则搜索爬虫会根据其中定义的范围进行爬取。如果没有找到,搜索爬虫会去访问所有可以直接访问的页面,我们看一下robots.txt的例子:User-agent:*Disallow:/Allow:/public/它实现了只允许的功能所有搜索爬虫爬取public目录,将以上内容保存为robots.txt文件,与网站入口文件(index.html)一起放在网站根目录下。User-agent描述搜索爬虫的名称。设置为*表示该协议对任何爬虫都有效。如果设置为Baiduspider,则表示该规则对百度爬虫有效。如果有多个规则,则限制多个爬虫,但至少必须指定一个常用的搜索爬虫名称:BaiduSpider 百度爬虫www.baidu.comGooglebot 谷歌爬虫www.google.com360Spider 360Crawlerwww.so.comYodaoBot YoudaoCrawlerwww.youdao.comia_archiver AlexaCrawlerwww.alexa.cnScooter altavistaCrawlerwww.altavista.comDisallow指定不允许爬取的目录,如上例,/意思是所有的页面都不允许被抓取。Allow通常与Disallow一起使用,以排除某些个别限制。比如上例中设置为/public/,表示所有页面不允许爬取,但是允许公共目录设置:#ForbidallcrawlersUser-agent:*Disallow:/#允许所有爬虫访问任意目录,也可以将文件留空User-agent:*Disallow:#禁止所有爬虫访问某些目录User-agent:*Disallow:/home/Disallow:/tmp/#只允许某个爬虫访问User-agent:BaiduSpiderDisallow:User-agent:*Disallow:/2robotparserrebotparser模块用于解析robots.txt,该模块提供了一个类RobotFileParser,可以根据某个爬虫的robots.txt文件进行判断某些网站当一个爬虫坏了,它就有权限爬这个网页urllib.robotparser.RobotFileParser(url='')robotparser类的常用方法:set_url():用来设置robots.txt文件的连接,如果你创建的是一个RobotFileParser对象,它是传入连接,所以这个方法中不需要设置read():读取reobts.txt文件并分析,不会返回任何内容,只是执行读取和分析操作parse():用来解析robots.txt文件,传入的参数是robots.txt的一些行的内容,安装语法规则来解析内容can_fetch():这个方法传入两个参数,第一个是User-agent,第二个是要抓取的url,返回的内容是搜索引擎是否可以抓取这个url,结果是True还是Falsemtime():返回robots.txt最后一次抓取分析的时间修改():设置当前时间为最后一次抓取分析robots.txt#!/usr/bin/envpython#coding:utf8fromurllib.robotparserimportRobotFileParserrp=RobotFileParser()#createobjectrp.set_url('https://www.cnblogs.com/robots.txt')#设置robots.txt连接,也可以指定rp.read()#读取并解析文件print(rp.can_fetch('*','https://i.cnblogs.com/EditPosts.aspx?postid=9170312&update=1'))希望各位同学以后在写爬虫的时候能够遵循Robot协议,为了自己的安全起步IT谢谢大家的关注|练习地址:www.520mg.com/it