《python-网络爬虫.docx》由会员分享,可在线阅读,更多相关《python-网络爬虫.docx(66页珍藏版)》请在课桌文档上搜索。
1、抓取网页的含义和UR1.基本构成1、网络爬虫的定义网络爬虫,即WebSpider,是一个很形象的名字。把互联网比方成一个蜘蛛网,那么SPider就是在网上爬来爬去的蜘蛛.网络蜘蛛是通过网页的链接地址来找寻网页的。从网站某一个页面(通常是首页)起先,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址找寻下一个网页,这样始终循环下去,直到把这个网站全部的网页都抓取完为止。假如把整个互联网当成一个网站,那么网络蜘蛛就可以用这个原理把互联网上全部的网页都抓取下来。这样看来,网络爬虫就是一个爬行程序,一个抓取网页的程序.网络爬虫的基本操作是抓取网页。那么如何才能为所欲为地获得自己想要的页面
2、?我们先从UR1.起先。2、阅读网页的过程抓取网页的过程其实和读者平常运用IE阅读器阅读网页的道理是一样的。比如说你在阅读器的地址栏中输入baidu这个地址。打开网页的过程其实就是阅读器作为一个阅读的“客户端,向服务器端发送了一次恳求,把服务器端的文件抓”到本地,再进行说明、呈现。HTM1.是一种标记语言,用标签标记内容并加以解析和区分。阅读器的功能是将获得到的HTM1.代码进行解析,然后将原始的代码咕变成我们干脆看到的网站页面.3、URl的概念和举例简洁的来讲,UR1.就是在阅读器端输入的baid这个字符串。在理解UR1.之前,首先要理解URI的概念。什么是URI?Web上每种可用的资源,如
3、HTM1.文档、图像、视频片段、程序等都由一个通用资源标记符(UniVerSalResourceIdentifier,URI)进行定位。URl通常由三部分组成:访问资源的命名机制;存放资源的主机名;资源自身的名称,由路径表示。如下面的URI:我们可以这样说明它:这是一个可以通过协议访问的资源,位于主机webmonkey上,通过路径7htmlhtml40访问.4、UR1.的理解和举例UR1.是URl的一个子集。它是UniformResource1.ocator的缩写,译为统T源定位符.通俗地说,UR1.是Intemet上描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上。采纳UR1.
4、可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和书目等.UR1.的格式由三部分组成:第一部分是协议(或称为服务方式)。其次部分是存有该资源的主机IP地址(有时也包括端口号)。第三部分是主机资源的具体地址,如书目和文件名等.第一部分和其次部分用符号隔开,其次部分和第三部分用7符号隔开。第一部分和其次部分是不行缺少的,第三部分有时可以省略。下面来看看两个UR1.的小例子。1 .协议的UR1.示例:运用超级文本传输协议,供应超级文本信息服务的资源.例:/peopledailychannelwelcome.htm其计算机域名为peopledaily超级文本文件(文件类型为html)是在
5、书目/channel下的welcome.htm.这是中国人民日报的一台计算机。例::/talktalkl.htm其计算机域名为o超级文本文件(文件类型为html)是在书目/talk下的talkl.htm这是瑞得闲聊室的地址,可由此进入瑞得闲聊室的第1室。2 .文件的UR1.用UR1.表示文件时,服务器方式用file表示,后面要有主机IP地址、文件的存取路径(即书目)和文件名等信息。有时可以省略书目和文件名,但7符号不能省略.例:fileftp.yoyodynepubfilesfoobar.tt上面这个UR1.代表存放在主机ftp.yoyodyne上的PUb/files/书目下的T文件,文件名是
6、foobar.tto例:file:ftp.yoyodyne/pub代表主机ftp.yoyodyne上的书gpubo例:fileftp.yoyodyne/代表主机ftp.yoyodyne的根书目爬虫最主要的处理对象就是UR1.,它依据UR1.地址取得所须要的文件内容,然后对它进行进一步的处理。因此,精确地理解UR1.对理解网络爬虫至关重要。利用urllib2通过指定的UR1.抓取网页内容所谓网页抓取,就是把UR1.地址中指定的网络资源从网络流中读取出来,保存到本地.类似于运用程序模拟IE阅读器的功能,把UR1.作为恳求的内容发送到服务器端,然后读取服务器端的响应资源。在Python中,我们运用u
7、rllib2这个组件来抓取网页。urllib2是Python的一个获得UR1.s(UniformResource1.oCatOrS)的组件。它以urlopen函数的形式供应了一个特别简洁的接口。最简洁的urllib2的应用代码只须要四行。我们新建一个文件urllib2.testl.py来感受一下urllib2的作用::/baidu2response=urllib2.urloen(3htnl-response.read()4. printhtnl按下F5可以看到运行的结果:_7iPythonSheillefdiShelebgQptionsWindowsyelwimu=+p;img.src=ttp
8、:/nsclck.babds.coran.user;funccioIn_addTJ(obj)(addEV(obJrmousedownfunction(e)vare=e11window.event;varItargete.targete.SrcElenient;ns_c(fm,:,behslr,cab,:target.na11etj-user,Ir,unSencodeURICoaponent(un););for(var1=0;1for(var三0;nv.length;*)(nv(i).name,tj_,tj_nv(i;)for(vari三0;1Ik.length;i+)(lki.na11e三tj
9、-tjlJci;)();(functlon()3:(key*,hccp:/I/music.baidu.consearc7frps6ieucf-8,ttjiJ11g:wordtrhttp:/image.baidu.Icom2cr三201326592&cl=24nc三141m=-i4st三-lfctn=baduiEage4i3cype三2ifm=pv=iz=04ie=uItf-8)ztjvideol:wordrhttp:/video.b:?*)+wd+,encodeURICo11ponent(key);target.href-url;)else(target.href-targeIz.ref.ma
10、tch(newRegExp(*hctp:/.+)0;neie&ns_c(rm:bIehs,r,cab,:name,query1:encodeURICoraponent(key)z,un:encodeURICo11onent(bds.cIorra.user);)();addEV(wrloadfunction()Jc.focus();w.onunload=funcIton();age-response.read()5. printthe_page可以看到输出的内容和testl是一样的.urllib2运用相同的接口处理全部的UR1.头。例如你可以像下面S瞭创建一个ftp恳求.pythonv*sewR
11、mAnCOPY1.requrllib2.Request(ftpzeanple,)在恳求时,允许你做额外的两件事。1 .发送data表单数据这个内容信任做过Web端的都不会生疏,有时候你希望发送一些数据到UR1.(通常UR1.与CGI通用网关接口脚本,或其他WEB应用程序挂接)。在中,这个常常运用熟知的POST恳求发送.这个通常在彳朋是交一个HTM1.表单时由你的阅读器来做。并不是全部的POSTs都来源于表单,你能够运用POST提交随意的数据到你自己的程序。一般的HTM1.表单,data须要编码成标准形式。然后做为data参数传到ReqUeSt对象。编码工作运用urllib的函数而非urllib
12、2我们新建一个文件urllib2jest03.py来感受一下:1. uporturllib3.url*,:/soneserver/register.cgivalues(,nae:,WHY,l,location:,SDU,language:,Python*)10. data=urllib.urlencode(values)#漏用f11. requrllib2.Request(url,data)*及E昱求,J时传da衣依12. response-urllib2.urlope11(req)#按2IrN的J13. thejage-response.read()#i:取反愦的内部假如没有传送data参数
13、,urllib2运用GET方式的恳求。GET和POST恳求的不同之处是POST恳求通常有副作用,它们会由于某种途径变更系统状态(例如提交成堆垃圾到你的门口)。Data同样可以通过在Get恳求的UR1.本身上面编码来传送。1. importurllib22. importurllib3.4. data三5.6. dataa11e,),hHY,7. data(,location,三,SDU,8. datalanguage*-,Python*9.10. url-values-urllib.urlencode(data)11. printur】_values12.13. na11e-Sonebody*
14、Herelanguage-Pytbon8ilocation-Northampton14. url,:/earrpleeafrple.cgi,15. fullJrI=url,url-vales16.17. data-urllib2.op11(full-url)这样就实现了Data数据的Get传送。2.设置Headers到恳求有一些站点不喜爰被程序(非人为访问)访问,或者发送不同版本的内容到不同的阅读器.默认的UHlib2把自己作为Python-Urllibx.y仅和y是PythOn主版本和次版本号,例如Python-urllib/2.7),这个身份可能会让站点迷惑,或者干脆不工作。阅读器确认自己
15、身份是通过USer-Agent头当你创建了一个恳求对象,你可以给他一个包含头数据的字典。下面的例子发送跟上面一样的内容,但把自身模拟成IntemetExplorere1. importurllib2. importurllib23.4. url-,:/so11eservercgibin/register.cgi,5.6. USeJagent三,Kozilla4.(compatible;MSIE5.5;WindowsNT)7. values-,ne,:,WHY8. ,location*:,SDU,9. ,language*:*Python,)10.11. headersNtUser-Agenf:
16、user-agent)12. dataurllib.urlencode(values)13. req-urllib2.Request(url,datajheaders)14. response=urllib2.urlopen(req)15. the-age三response.read()异样的处理和状态码的分类先来说一说的异样处理问题.当urlopen不能够处理一个response时,产生UrIErroro不过通常的PythonAPIs异样如VaIueErrorlTypeError等也会同时产生。Error是UrIError的子类,通常在特定UR1.s中产生.1.UR1.Error通常,UR1
17、.Error在没有网络连接(没有路由到特定服务器),或者服务器不存在的状况下产生.这种状况下,异样同样会带有reason属性,它是tuple(可以理解为不行变的数组),包含了一个错误号和一个错误信息。我们建urllib2jest06.py来感受一下异样的处理:importurllib2baibai,)req-urllib2.Request(,:/try:urllib2.urlopen(req)excepturllib2.UR1.Error,e:printe.reason按下F5,可以看到打印出来的内容是:Errno11001getaddrinfofailed也就是说,错误号是IlOOl,内容是
18、getaddrinfofailed2.Error服务器上每一个应答对象response包含一个数字状态码有时状态码指出服务器无法完成恳求。默认的处理器会为你处理一部分这种应答。例如:假如response是一个重定向须要客户端从别的地址获得文档,urllib2将为你处理。其他不能处理的,urlopen会产生一个Error.典型的错误包含404(页面无法找到),403”(恳求禁止),和40(带验证恳求)。状态码表示协议所返回的响应的状态。比如客户端向服务器发送恳求,假如胜利地获得恳求的资源,则返回的状态码为200,表示响应胜利。假如恳求的资源不存在,则通常返回404错误。状态码通常分为5种类型,分
19、别以15五个数字开头,由3位整数组成:200:恳求胜利处理方式:获得响应的内容,进行处理201:恳求完成,结果是创建了新资源。新创建资源的URl可在响应的实体中得到处理方式:爬虫中不会遇到202:恳求被接受,但处理尚未完成处理方式:堵塞等待204:服务器端已经实现了恳求,但是没有返回新的信息.假如客户是用户代理,则无须为此更新自身的文档视图。处理方式:丢弃300:该状态码不被/1.0的应用程序干脆运用,只是作为3XX类型回应的默认说明。存在多个可用的被恳求资源。处理方式:若程序中能够处理,则进行进一步处理,假如程序中不能处理,则丢弃301:恳求到的资源都会安排一个永久的UR1.,这样就可以在将
20、来通过该UR1.来访问此资源处理方式:重定向到安排的UR1.302:恳求到的资源在一个不同的UR1.处临时保存处理方式:重定向到临时的UR1.304恳求的资源未更新处理方式:丢弃400非法恳求处理方式:丢弃401未授权处理方式:丢弃403禁止处理方式:丢弃404没有找到处理方式:丢弃5XX回应代码以5开头的状态码表示服务器端发觉自己出现错误,不能接着执行恳求处理方式:去弃Error实例产生后会有一个整型code属性,是服务器发送的相关错误号。ErrorCodes错误码因为默认的处理器处理了重定向(300以外号码),并且100-299范围的号码指示胜利,所以你只能看到400-599的错误号码。B
21、aseServer.BaseRequestHandIenresponse是一个很有用的应答号码字典,显示了协议运用的全部的应答号。当一个错误号产生后,服务器返回一个错误号,和一个错误页面.你可以运用Error实例作为页面返回的应答对象response这表示和错误属性一样,它同样包含了read,geturl,和info方法。我们建furllib2jest07.py来感受一下:1. importurllib22. requrllib2.Request(,call11ewhy,)3.4. try:5. urllib2.urlopen(req)6.九excepturllib2.UR1.Error,e:
22、8.9printe.code10. Wprinte.read()按下F5可以望见输出了404的错误码,也就说没有找到这个页面。3.Wrapping所以假如你想为Error或UR1.Error做打算招有两个基本的方法。举荐运用其次种.我们建Turllib2jest08.py来示范一下第一种异样处理的方案:1.fromurllib2iwportRequest,urlopen,UR1.Error,Error2.3.req三Request(,:7. responseurloen(req)8.9exceptError,e:l,11. printTheservercouldntfulfilltherequ
23、est.12.13. print,Errorcode:,e.code14.15. exceptUR1.Error,e:16.17. printWefailedtoreachaserver.,18.19. print,Rea&on:,e.reason28.29. else:30. printNoexceptionwasraised.,31. 幼everythingisfine和其他语言相像,try之后做异样并且将其内容打印出来。这里要留意的一点,exceptError必需在第一个,否则exceptUR1.Error将同样接受到Error.因为Error是UR1.Error的子类,假如UR1.Er
24、ror在前面它会捕获到全部的UR1.Error(包括Error).我们建一个urllib2.test09.py来示范一下其次种异样处理的方案:fromurllib2inportRequest,UrIOPen,UR1.Error,ErrorreqRequest(,:try:responseNurlopen(req)exceptURlError,e:10.11. ifhasattr(e,reason):12.13. printWefailedtoreachaserver.,14.15. printReason:,ie.reason16.17. elifhasattr(e,code,):18.19.
25、 printTheservercould*tfulfilltherequest.,20.21. printeSrrorcode:,e.code22.23. else:24. print,Noexceptionwasraised.,25. 出everythingisfineOpener与Handler的介绍和实例应用在起先后面的内容之前,先来说明一下urllib2中的两个个方法:infoandgeturlurlopen返回的应答对象response(或者Error实例)有两个很有用的方法info()和geturl()l.geturl():这个返回获得的真实的UR1.1这个很有用,因为UriOPe
26、n(或者OPener对象运用的)或许会有重定向.获得的UR1.或许跟恳求UR1.不同。以人人中的一个超级链接为例,我们建一个urllib2.testl0.py来比较一下原始UR1.和重定向的链接:345678Errorfromurllib2inportRequest,urlopen,URlError,old_url三,:/rrurlblUZuP,reqNRequest(old-url)response-urlopen(req)print*01durl:old-,urlprintRealurl:,+response.geturl()运行之后可以看到真正的链接指向的Oldurl:hcrp:/Rea
27、lurl:http:/ww.polyu-eduhk/polyuchallenge/best_of_the_besc_elevator_pitch_award/bbca_voting_process.php?voted_tearr._icl=6704section=14bbcaeyear_id=3I2.info():这个返回对象的字典对象,该字典描述了获得的页面状况。通常是服务器发送的特定头headers,目前是lib.Message实例。经典的headersContent-length,Content-type,和其他内容。我们建一urllib2jestll.py来测试一下info的应用:1.
28、fromurlllb2IwportRequest,urloen,UR1.Error,Error2.3. Ole1.Url,:/baidu,4. reqReqUeSt(OIdjrI)5. response三urloen(req)6. printInfo():,7printresponse.info()运行的结果如下,可以看到页面的相关信息:Info():Date:Tuer14May201306:10:01GMTServer:SWS/1.0Concent-1.ength:10450Content-Type:texttml:carset三utf-8Cache-Control:privateSet-C
29、ookie:BDSVRTM-4;path-/Sec-Cookie:H-PS-PSSID=242823621466-1945-178S-2249-22602251;pat三;domain=,Set-Cookie:BAIDUID-5B39D8D917E85C3DEA80DAF96B7A3E9A:FG-l;Cxpires-Tuer14-May-4306:10:01GMT;path=/;domain=Expires:TuerWMay201306:10:01GMTP3P:CP=OTIDSPCORIVOURINDCOMConnection:Close下面来说一说Urllib2中的两个重要概念:OPener
30、S和Handlers.1.Openers:当彳够得一UR1.你ffi一个opener(-Zurllib2.OpenerDirector的实例).正常状况下,我们运用默认opener:通过urlopen但你能够创建特性的openers.2.Handles:Openers运用处理器handlers,全部的繁重工作由handlers处理.每个handlers知道如何通过特定协议打开UR1.s,或者如何处理UR1.打开时的各个方面.例如重定向或者cookies.假如你希望用特定处理器获得UR1.s你会想创建一个OPenerS,例如获得一个能处理cookie的opener,或者获得一个不重定向的open
31、er.要创建一个opener,可以实例化一个OpenerDirector,然后调用addjandler(Some-handlejinstance)。同样,可以运用build,opener,这是一个更加便利的函数,用来创建opener对象,他只须要一次函数调用。buHd_OPener默认添加几个处理器,但供应快捷的方法来添加或更新默认处理器。其他的处理器handlers你或许会希望处理代理,验证,和其他常用但有点特殊的状况。install.opener用来创建(全局)默认openero这个表示调用urlopen将运用你安装的opener。Opener对象有一个open方法。该方法可以像urlop
32、en函獭瞭干脆用来获得urls:通常不必调用install.opener,除了为了便利.说完了上面两个内容,下面我们来看一下基本认证的内容,这里会用到上面提及的C)Pener和Handler.BasicAuthentication基本验证为了展示创建和安装一个handler,我们将运用BasicAuthHandIer.当须要兽出验证时,服务器发送一个header(401错误码)恳求验证。这个指定了scheme和一realm,看起来像这样:Www-authenticate:SCHEMErealm=REA1.M.例如Www-authenticate:Basicrealm=cPanelUsers客户
33、端必需运用新的恳求,并在恳求头里包含正确的姓名和密码.这是郸出验证,为了简化这个过程,我们可以创建一个BaSiCAUthHandler的实例并让OPener运用这个handler就可以啦.BasicAuthHandIer运用一个密码管理的对象来处理UR1.s和realms来映射用户名和密码.假如你知道realm(从服务器发送来的头里)是什么,你就能运用PasswordMgre通常人们不关切realm是什么。那样的话,就能用便利的PasswordMgrWithDefauItReaIm.这个将在你为UR1.指定一个默认的用户名和密码。这将在你为特定realm供应一个其他组合时得到供应。我们通过给r
34、ealm参数指定None供应应add_password来指示这种状况。最高层次的UR1.是第一个要求验证的UR1.o你传给.adc1.paSSWordo更深层次的UR1.S将同样合适。说了这么多废话,下面来用一个例子演示一下上面说到的内容。我们建urllib2.testl2.py来测试一下info的应用:Acoding:utf-8-Importurllib2A创建一个密犯瞥理者6789passuord-fgrNurllib2.PasswordMgrithDefaultRealf()Wr加用户名和密码to-level-url”:examplefoowl.11. #假如如ittrealm,我们可以
35、运用他代件None12. 再password_mgr.add_password(NoneJtop-levelurl,usernamejpassword)13. password_ngr.addjassord(Noneitop_level_url,wy,*1223,)14.15. #创建了个新的handler16. handler-urllib2.asicAuthHandler(password-mgr)17.18. U创也opener(OpenerOirector实例)19. openerurllib2.build-oener(hadler)2.21. aJrl三:/bidu22.23. #运
36、MOPene获得-个URl24. opener.open(a-ur1)25.26. H安装opener.27. W现在全部调用urllib2.urlopen将用我们的opener.28. urllib2.install-,opner(opener)29.30.留意:以上的例子我们仅仅供应我们的HHTPBaSiCAUthHandIer给build-opener默认的openers有正常状;handlers:ProxyHandIer,UnknownHandIer,Handler,DefauItErrorHandIer,RedirectHandIer,FTPHandIer,FiIeHandIer,E
37、rrorProcessore代码中的topjevel_url事实上可以是完整UR1.(包含:,以及主机名及可选的端口号)。例如:7/example/.也可以是一个authOrity(即主机名和可选的包含端口号)。例如:exampleor,example:8080后者包含了端口号。urllib2的运用细微环节与抓站技巧前面说到了urllib2的简洁入门,下面整理了一部分urllib2的运用细微环节。I-Proxy的设置urllib2默认会运用环境变量_proxy来设置Proxy.假如想在程序中明确限制Proxy而不受环境变量的影响,可以运用代理。新建testl4来实现一个简洁的代理Demo:(pytov*vp3*)copy1.importurllib22