版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
内容提内容提本书讲解了如何使用P川lOil来编写网络爬虫程序,内容包括网络爬虫简介,从页面中抓取数据的三种方法,提取缓存中的数据,使用多个线程和进程来进行并发抓取,如何抓取动态页面中的内容,与表单进行交互,处理页面中的验证码问题以及使ScarpyPortia来进行数据抓取,并在最后使用本书介绍的数据抓取技术对几个真实的网站进行了抓取,旨在帮助读者活学活用书中介绍的技术。本书适合有一定Python编程经验,而且对爬虫技术感兴趣的读者阅读关于作来自澳大利亚关于作来自澳大利亚毕业于墨尔本大学计算机科学专业。业后,他创办了一家专注于网络爬虫的公司,为超过50个国家的业务提供远程工作。他精通于世界语,可以使用汉语和韩语对话,并且积极投身于开源软件。他目前在牛津大学攻读研究生学位,并利用业余时间研发自主无人机我要感谢TimothyBaldwin教授将我引入这个令人兴奋的领域本书编写时在巴黎招待我的ηiara可Douc以关于审稿Bur咄是一名常驻纽约的数据记者,关于审稿Bur咄是一名常驻纽约的数据记者,其工作是为华尔街日报绘交互式图表。他在新墨西哥州立大学获得了新闻学和信息系统专业位,然后在纽约城市大学新闻学研究院获得了新闻学专业硕士学位我要感谢我的妻子isa鼓励我协助本书的创作,的叔叔Mica耐心解答我的编程问题, 以及我的父亲Richard激发了我对新闻学和写作的热爱WilliamSankey是一位数据专业人士,也是一位业余开发人员,生活在里兰州科利奇帕克市。他于2012年毕业于约翰·霍普金斯大学,获得了公政策硕士学位,专业方向为定量分析。他目前在 政策研究有限责任公&担任健康服务研究员,从事与美国医疗保险和医疗补助服务中心(CMS)相关的项目。这些项目包括责任医疗机构评估以及精神病院住院患者预统监测我要感谢我深爱的妻子Julia和顽皮的小猫Ruby,给予我全部的爱和AyushTiwari是一名Python开发者,本科就读AyushTiwari是一名Python开发者,本科就读于印度工学院罗克分校。发领域。对他而言,审阅本书是一个非常棒的经历。他不仅是一名审稿人,也是一名狂热的网络爬虫学习者。他向所有Python爱好者推荐本书,以便享他热衷于Python网络爬虫,曾参与体育直播订阅、通用P川lil电子商务网络爬虫(在Miran相关项目。Djo应用开发了就业门户,帮助改善印度工学院罗克分他还使用的就业流程除了后端开发之外,他还喜欢使用诸如u上访问到他的项目,他的用户名是tiwariayush。他喜欢徒步穿越喜马拉雅山谷,每年会参加多次徒步行走活动。此外,他还喜欢弹他的成就还包括参加国际知名Super30小组并在其中成为排名保持者。他在高中时,还参加了国际奥林匹克数学竞赛。b我的家庭成员(我的姐姐Aditi、我的父母以及Anand先生)、我在VI和IMG的朋友以及我的教授都为我提供了很大的帮助。我要感谢他们所有人对我的支持。最后,感谢尊敬的ackt出版社团队出版了这些非常好的技术我要对他们在编写2..a.&.刷..a.&.刷互联网包含了迄今为止最有用的数据集,并且大部分可以免费公开访问。但是,这些数据难以复用。它们被嵌入在网站的结构和样式当中,需要抽取出来才能使用。从网页中抽取数据的过程又被称为网络爬虫。随着越来越的信息被发布到网络上,网络爬虫也变得越来越有用第1章,网络爬虫简介,介绍了网络爬虫,并讲解了爬取网站的方法。第2章,数据抓取,展示了如何从网页中抽取数据。第3章,下载缓存,学习了如何通过缓存结果避免重复下载的问题。第4章,并发下载,通过并行下载加速数据抓取。第5章,动态内容示了如何从动态网站中抽取数第6章,表单交互,展示了如何与表单进行交互而访问你需要的数据。第7章,验证码处理,阐述了如何访问被验证码图像保护的数据。第8Scrapy学习了如何使用流行的高级cay第9章结,对我们介绍的这些网络爬虫技术进行总结前本书中所有的代码都己经在Python前本书中所有的代码都己经在Python环境中进行过测试,并且可以http//bitbucket.og/wspcode下载到这些源代码理想情况下本书未来的版本会将示例代码移植到Python3当中。不过,现在依赖的很多库(比如Scrapy/Twisted、Mechaize和Ghost)还只支持Python2。为了帮助阐明爬取示例我们创建了一个示例其http//xaple.webscraping.com。由于该网站限制了下载内容的速度,因此如果你希望网站源代码和安装说明。我们决定为本书中使用的大部分示例搭建一个定制网而不是抓取活跃网站,这样我们就对环境拥有了完全控制。这种方式为我们提供了稳定性,因为活跃网站要比书中的定制网站更新更加频繁,并且当你尝试运行爬虫示例时,代码可能已经无法工作。另外,定制网站允许我们自定义示例,用于阐释特定技巧并避免其他干扰。最后,活跃网站可能并不欢迎我们使用它作为学习网络爬虫的对象,并且可能会尝试封禁我们的爬虫。使用我们自己定制的网站可以规避这些风险,不过在这些例子中学到的技巧确实也可以应到这些活跃网站当中阅读本书需要有一定的编程经验,并且不适用于绝对的初学者。在实践中我们将会首先实现我们自己的网络爬虫技术版本,然后才会介绍现有的流行这样可以让你更好地理解这些技术是如何工作的。本书中的这些示例块假设你已经拥有Python语言以及使用pip安装模块的能力。如果你想复习一这些知识 有一本非常好的免费在线书籍可以使用,其作者为2前Pilri前Pilrim书籍网址是httpwwwdvetopythonnet。这本书也是我此外,这些例子还假设你己经了解网页是如何使用HTML进行构建并过Jvcipt更新的知识的既有知识也很有用,不过它们不是必需的,这些技术会在需要使用时进行介绍。上述很多主题的详细参考资料可以从http://.w3schols.获取到3第1网络网络爬虫是否合…………背景调 第1网络网络爬虫是否合…………背景调 检查网站地 估算网站大 识别网站所用技术寻找网站所有 …编写第一个网络爬虫………8下载网 I遍历爬虫链接爬 本章小结… 第2数据抓分析网 三种网页抓取方法正则表达 目BeautifuSoup·········………目BeautifuSoup·········………………………结论…………为链接爬虫添加抓取回 本章小 第3下载缓为链接爬虫添加缓存支持…·····················… 磁盘缓 实 缓存测 节省磁盘空间………………清理过期数 缺点…………·数据库缓 NQL是什 …·…………安装MongoD MongoDB缓存实 压 缓存测…·”…………本章小结………第4并发下100万个网 串行爬 多线程爬 2目线程和进程如何工 实 多进程爬 性 目线程和进程如何工 实 多进程爬 性 本章小结 第5动态内动态网页示 对动态网页进行逆向工程 渲染动态网 PyQt还是PySid 执行JavaScri 使用WebKit与网站交 本章小 第6表单交第7登录表 支持内容更新的登录脚本扩 使Mechanize模块实现自动化表单处 本章小结1验证码处注册账号 …·光学字符识别处理复杂验证 111使用验证码处理服 9kw入 3与注册功能集成本章小结 第8与注册功能集成本章小结 第8安 …··启动项目8.2.1定义模 l检查结 中断与恢复爬虫”…………8.38.3安装………标注优化爬虫 …·检查结果 使用Scrapeyl实现自动化抓 本章小结……………第9总’40O2章中,我们将章中,我们将会介绍如下主题解释合法性质疑对目标网站进行背景调研逐步完善一个高级网络爬虫1.设我有并且想要及时了解竞争对我可以每天访问他们的网站,与我店铺中鞋子的价格进行对比。但是,如果我店铺中的鞋类品种繁多或是希望能够更加频繁地查看价格变化的话,就需要花费大量的时间,甚至难以实现。再举一个例子,我看中了一双鞋,想等促销时再购买。我可能需要每天访问这家鞋店的网站来查看这双鞋是否价,也许需要等待几个月的时间,我才能如愿盼到这双鞋促销上述两个重复性的手工流程都可以利用本书介绍的网络爬虫技术实现自动处理1章网络爬虫简P,1章网络爬虫简P,P,但是它们通常会限制可以抓取的数据,以及访问这些数据的频率。另外对于网的开发者而言维护前端界面比维护后端API接口优先级更高。总我们不能仅仅依赖于API去访问我们所需的在线数据而是应该学习些网络爬虫技术的相关知识1网络爬虫目前还处于早期的蛮荒阶段,允许哪些行为”这种基本秩序还处于建设之中。从目前的实践来看,如果抓取数据的行为用于个人使用,则不存在问题而如果数据用于转载那么抓取的数据类型就非常关键了。世界各地法院的一些案件可以帮助我们确定哪些网络爬虫行为是允Co的案件中,在Feist的国联邦最高法院裁定抓取并转载真实数据(比如,电话清单〉是允许的。而在澳大TelstraCorporationLimited起诉PhoneDirectoriesCompanyLtd这一类似案件中,则裁定只有拥有明确作者的数据,才可以获得,是允许的最终裁定定期抓取和深度这些案件告诉我们,当抓取的数据是现实生活中的真实数据(比如电话清单)时,是允许转载的。但是,如果是原创数据(比如,意地址和评论),通常就会受到版权限制,而不能转载无论如何,当你抓取某个网站的数据时记住自己是该网站的访客,应当约束自己的抓取行为,否则他们可能会封禁你的IP甚至采取更进一步的这就要求下载请求的速度需要限定在一个合理值之内 并且还法律行要设定一个专属的用户代理来标识自己。在下面的小节中我们将会对这些践进行具体介绍21关于上述几个法律案件的更多信息可以参考下述地址•getcase.•http://www.bvhd.dk/uploads/tx/SogHandelsrettensafgrelseiOfir-1在深入讨论爬取一个网站之前,我们首先1关于上述几个法律案件的更多信息可以参考下述地址•getcase.•http://www.bvhd.dk/uploads/tx/SogHandelsrettensafgrelseiOfir-1在深入讨论爬取一个网站之前,我们首先需要对目标站点的规模和结构行一定程度的了解。网站自身的robots们提供一定的帮助,此外还有一些能提供更详细信息的外部工具,比如Goog1.3.1检查站t,站时存在哪些限制。这些限制虽然仅仅作为建议给出,但是良好的网络公民都应当遵守这些限制。在爬取之前,检查rob.txt文件这一宝贵资源可以最小站相关.们的示例文件robots.中的内容可以访问httpexampwebscraping.co/ots.获取#-,户--3aaBwoneq4tacasr·e1章网络爬虫#sectionU1章网络爬虫#sectionUser-agent:*Crawl-delay:5Disallow:/trap#sectionSitemap:http:///sitemap.Crl在sect爬虫爬取该网站,不过这种写法可能无法起到应有的作用,因为恶意爬虫本不会遵从robots.txt的要求。章后面的一个子将会展示如何让爬自动遵守robots的要求section2规定,无论使用哪种用户代理,都应该在两次下载请求之间给出5秒的抓取延迟,我们需要遵从该建议以避免服务器过载。这里还有一个trp链接用于封禁那些爬取了不允许链接的恶意爬虫。如果你访问了这个链接服务器就会封禁你的IP一分钟!一个真实的网能会对你的IP封禁更长时间至是永久封禁不过如果这样设置的话我们就无法section3义了一个Sitemap文我们将在下一节中了解如何检1.3.2检查网站地图网站提供的Stemap文件(即网站地图)可以帮助爬虫定位网站最新的内容而无须爬取每一个网页。如果想要了解更多信息可以从http:wwwsitemapsorprtocol.htl获取网图标的St<?xmlversion=1encoding=UTF8<urlsetxmlns=”httpwwwsitemapsorgschemassitemap/0.9<url><loc>http://example.webscraping.com/view/Afghanistan-</loc><<url><loc>http://example.webscraping.com/view/Aland-Islands-41</loc></url><url><loc>http:///view/Albania-3</1</loc></url><url><loc>http:///view/Albania-3</loc></urlset>网站地图提供了所有网页的链接,我们会在后面的小节中使用这些信息,用于创建我们的第一个爬虫。虽然Siemap文件提供了一种爬取网站的有效方式但是我们仍需对其谨慎处理因为该文件经常存在缺失整的问题1.3.3估算网站大小目标网大小会影响我们如何进行爬取如果是像我们的示这样只有几百个URL的网站,效率并没有那么重要:但如果是拥有数百万个网页的站点,使用串行下载可能需要持续数月才能完成,这时就需要使用第4章站可能已经爬取过我们感兴趣的网。我们可以通过Goole搜索的site词过滤域名结果,从而获取该信息我们可以从http/w.search了解到该接口及其他高级搜索参数的用法com/adva口图1.1所示为使用sie关键词对我们的示例网站进行搜索的结果Google中搜site:example.webscraping.即从图1.1中可以看出此时Google估算该网拥有个网页,这和不过对于更大型的网站,我会发现Google的估算并不在域名后面添加URL路径,可以对结果进行过滤仅显示网某些部分。1.2所示为搜siteexamplewebscrapingcomview的结果该搜索条件会限制Google只搜索国家页面51第章网络爬虫简介Aboul202re田JltS伺45蕃AF•ExampleExam阱嗣b阳叩ing\¥盹脚.Ar目,闻geria·Angela·senin·Sotswana·刷刷1第章网络爬虫简介Aboul202re田JltS伺45蕃AF•ExampleExam阱嗣b阳叩ing\¥盹脚.Ar目,闻geria·Angela·senin·Sotswana·刷刷Fa回·6田undlC副陌roonca阳Verde·C田11ra1Ari国nR邱刷lc·Chwebs挂NA-εxa『npleex翻F瑞E翼田胃pieweb缸万冒pir咱w雹』画捶.IJ。曲ArAn窜山l国Anti凯iaar晴B酣budaSaintEus恒屈JSNE姐 scrapingNalklnalFl咽’M回:1,267,00S嗯且惜据阳elli剧,问pula如n:10,676,27专lso:Country:IJ胁,.Cai就醋’Nlam町C曲睛酣吐AF.Tlcl:J班CurCode:NG-Examplewebsαapinge刷脚.wet刷刷lisol闸NationalFl啕:岛国:923,768squa阳闹。metres.Pcψul硝or应154,00口,00.1聪C咀Jntry:N精制a巳apl国EAlli!由acon剧团提:AFTld:.ngcurrencyC时居图1.1About117明ults(0.52seamExampleweb部rapingNatio捕’F陆g:A,回:76squ町ekllom钝国.Population:65,22苗,i四:GG.Cou晴y.G佳emse于“CapitalStPeterp。她Con伽entEU.Tld:.gg.CurrencyCode:GBP.Examplewebscraping回am树e.w唾民臼撞倒fv梅w/Je陀曹y-113Nat阳nalF句:阳明:116呵U脚扭llornet阳.P句“la切罚;阂,612.lso:JE.Country:Jerse沪PK-scrapingFl句:A陌a:8部,S铅squa用kfm悦s.Population:184,404,791.国C由mtry:Pak陆;tan.Cap幅:1时ama缸ad.Cont加剧1l:AS“lld:.pkCurrencyCodewebsite-C皿miry:Ma姐ysia.Ca回国:KualaL四npur.Con11nentAS.Tld:.my.C町rency町图1这种附加的过滤条件非常有用,因为在理想情况下,你只希望爬取网站包含有用数据的部分,而不是爬取网站的每个页面611识别网站所用构建网站所使用的技术类型也会对我们如何爬取11识别网站所用构建网站所使用的技术类型也会对我们如何爬取产生影响。有一个十分有用的工具可以检查网构建的技术类型一-lwith模块。该模块的安装pipinstallbuiltwi该模块将URL为参数下载该URL并对其进行分析,然后返回该网站使用的技术。下面是使用该模块的一个例子。》>imp。rtbuiltwi》>builtwith.parse(’http://example.webscraping.c。m’{ujavascriptfre。rks:[ujQl且ery,uM。dernizr,u’jQl且eryUI][u’Pyth。n’]u’pr。graming-languages’u’web-f。rks’ [u’Web2py’,u’TwitterB。。tstrap’]u’web-servers’:[u’Nginx’]从上面的返回结果中可以看出示例网用了Python的W2py框架,另外还使用了一些通用的Jvcript库,因此该网内容很有可能是嵌在HML中的,相对而言比较容易抓取。而如果改用AngularJS构建该网,此时的网站内容就很可能是动态加载的。另外,如果网站使用了A.NET么在爬取网页时,就必须要用到会话管理和表单提交了。的情况,我们会在第5章和第6章中进行介绍。对于这些更加复1.3.5对于一些网站我们可能会关心其所有者是谁。比如我们已知网站的络爬虫,那么我们最好把下载速度控制得更加保守一些为有者会封禁网找到网站的所有者我们可以使用O协议查询域名的注册者是谁。Pywhos7第l网络爬虫简pipinstallpyth。n-wh。下面是使用该模块a第l网络爬虫简pipinstallpyth。n-wh。下面是使用该模块ap.om这个域名进行WHOIS查询时的返回》>ip。rtwh。》>printwhois.wh。is(’appsp。t.[:、四”NSlG。。GLECOM”NS2.G。。COMNS4G。。GLE”ns4.q。。qle.com”,”ns2.q。。qle.com”,”nsl.q。。qle.GLE]”。rq”:”G。。Inc”e啤ails”:[useclaints。nit。r.com”,”dnsad皿in@q。。glecom”从结果中可以看出该域名归属于Goog实际上也确实如此该域名用于GoogleppEngine服务的当我们爬取该域名时就需要分小因Google经常会阻断网络爬虫,尽管实际上其自身就是一个网络爬虫业务1编写第一个网络爬为了抓取网,我们首先需要下载包含有感兴趣数据的网页该过程一般被称为爬取(rawlng)爬取一个网站有很多种方法,而选用哪种方法更加合适则取决于目标网结构中首先会探讨如何安全地下载网页然后会介绍如下3种爬取网站的常见方法814编写第一个网络爬虫爬取网站地图遍历每个网页的数据库D跟踪网14编写第一个网络爬虫爬取网站地图遍历每个网页的数据库D跟踪网页链接。下载网页···1.4.要想爬取网页,我们首先需要将其下载下来。下面的示例脚本使用模块下载URLllbimporturllib2defdownload(url)returnurllib2url。pen(urlread当传入URL参数时该函数将会下载网页并返回其HTML。不过,这个代码片段存在一个问题,即当下载网页时,我们可能会遇到一些无法控制错误会抛出异常,然后比如请求的页面可能不存在此时urlli脚本。安全起见,下面再给出一个更健壮的本,可以捕获这些异常importurldefdownload(url)printD。wnl。adingurltryhtml=urllib2.urlopen(url).read()excepturllib2.URLErrorase:printDownladerrrereasnhtml=Nonereturn现在,当出现下载错误时该函数能够捕获到异常然后返回None1. 下载时遇到的错误经常是临时性的,比如服务器过载时返回的ServiceUnavailable错误。对于此类错误,我们可以尝试重新下载,因为这个服务器问题现在可能己解决。不过,我们不需要对所有错误都尝试9wwwsimple00wwwsimple00.om电子书分享第1网络爬虫简新下载如果服务器返回的是404otFound种错误则该网页目前并不存在,再次尝试同样的请求一般也不会出现不同的结果。teretnT完整列表,详情可参考https://oos.ietf.org/html/rfc7231#函数发生Sxx错误时重试下载即可。下面是支持重试下载功能的新本代码defdownload(url,numretries=2printD。wnloadingurltry:html=urllib2.urlopen(url).read()excepturllib2.URLErrorase:print’Downloaderror:’,e.reasonhtml=Noneifnumretries>ifhasattr(e,’code’)and500<=e.code<600:#recursivelyretrySxxHTTPerrorsreturndownload(url,numretries-1)return现在,当download函数遇到Sxx错误码时将会递归调用函数自身进行重试。此外函数增加了一个参数用于设定重试下载的次数其默认值为两次我们在这里限网页下载的尝试次数是因为服务器错误时还没有解决。想要测试函数,可以尝试下载http://httpsat.us/500,该网址会始终返回500错误码》>d。wnl。ad(’http://httpstatus500’Downl。adinghttp://httpstat.us/500D。wnloaderr。r:InternalServerErr。rD。wnl。ading:htp://httpstat.us/500Downloaderr。r:InternalServerErr。zD。wnl。ading: http://httpstat.us/500D。wnloaderr。r:InternalServerErr。r10wwwsimple00.om电子书分享wwwsimple000co机电子书分享14编写第一个网络爬虫wwwsimple000co机电子书分享14编写第一个网络爬虫从上面的返回结果可以看出,downoad函数的行为和预期一致,先尝试下载网页,在接收到500错误后,又进行了两次重试才放弃。2.设置用户代默认情况下,7作为用户代理下使用Pythonurllib2.llb页内容其27是Python的版本号。如果能使用可辨识的用户代理则此外,也许是因为这样可以避免我们的网络爬虫碰到一些问题更好历过质量不佳的Python网爬虫造成的服器过载,一些网站还会封默认的用户代理。 比如,在使用P同il默认用户代理的情况下,访问http/wwwetupcom,前会返回如1.3所示的访问拒绝提示Accessη1eownerofthiswebsite()hasbannedyouraccessbasedon(•RayID:Tim臼饱mp:Mon.06心ct-1418:55:48Yo咀rIPaddres:62Reques撞edURL:www.mee灿/E.π·orreferencenumber:I0IOerID:FL33Fser-••••图.3因此,为了下载更加可靠,我们需要控制用户代理的设定下面的代码download函数进行了修改,设定了一个默认的用户代理wsw”(即WebScrapingwithPython的首字母缩写)defd。wnload(urluseragent=wsnumretries=2printDownloadingurlheaders={’User-agent’:useragentrequest=urllib2.Request(url,headers=headerstry:=urllib2.urlopen(request)•readexcepturllib2.URLErrorasprint’Downloaderror:’,e.reasonhtml=11wwwsimple000co机电子书分享wwwsimple000co机电子书分享第l网络爬虫wwwsimple000co机电子书分享第l网络爬虫简ifnumretries>ifhasattr(e, ’code’)and500<=e.code<600:#retry5XXHTTPerrorsreturndownl。ad(url,user agent,numretries-return现在,我们拥有了一个灵活函数,可以在后续示例中得到复用该函数能够捕获异常重试下载并设用户代理1.网站地图爬在第一个简单的爬虫中,我们将使用示例网站robots.txt文件中发现的网站地图来下载所有网页。为了解析网站地图,我们将会使用一个简单正则表达式,从<loc>标签中提取出URL而在下一章中,我们将会介绍种更加健壮的解析方法一-css选择器 下面是该示例爬虫的代码defcrawlsitemap(url)#downloadthesitemapfilesitemap=downl。adurl#extractthesitemaplinkslinks=re.findall(’<loc>(.*?)</loc>’,sitemap#downloadeachforlinkinlinkshtml=download(link)#scrapehtml#现在,运行网站地图爬虫,从示例网站中下载所有国家页面》crawl_sitemap(’http://example.webscraping.com/sitemap.xml’Dwnloading:http://example.webscraping.com/sit阻碍.mlhtp:/example.webscrapingc。/vinisn-D。loadn:D。wnl。ading:D。wnloading:http://example.webscraping.com/view/Aland-Islands-2htp://example.webscraping.com/view/Albania-3可以看出,上述运行结果和我们的预期一致,不过正如前文所述,我们无法依靠Siemap文件提供每个网页的链接。下一节中,我们将会介绍另-简单的爬虫,该爬虫不再依赖于iemap文件12wwwsimple000co机电子书分享www.simple000co算机电子书分享l.4编写第一个网络爬虫1ID遍历本节中,www.simple000co算机电子书分享l.4编写第一个网络爬虫1ID遍历本节中,我们将利用网站结构的弱点,更加轻松地访问所有内容。下面是一些示例国家的URL。http:IIexample.webscrapi口/view/Afghanista口-1http:IIexample.webscrapiηg.com/view/Australia http:IIexample.webscrapi口g.com/view/Brazil•••可以看出,这些URL只在结尾处有所区别,包括国家名(作为页面别名和ID。在URL中包含页面别名是非常普遍的做法可以对搜索引擎优化起帮助作用。一般情况下,Web服务器会忽略这个字符串,只使用D来匹配据库中的相关记录。加载http://example.webscrapi呵.com/view/,测试示例网站中的链接是否仍然可用。测结果如图所示NationalCo「647,500squa『eCu「rencyName:PostalCodeFormatfa”-AF,ps,uz-TMCNIRTJPKwww.simple000co算机电子书分享1章网络爬虫简从图中可以看出,网页依然可以加载成功,也就是说该方法是有1章网络爬虫简从图中可以看出,网页依然可以加载成功,也就是说该方法是有用的现在,我们就可以忽略页面别名,只遍历D来下载所有国家的页面。下面importitertoolsforpageinitertoolscou口t1url=httpexample.webscrapingcom/view/-宅d屯html=download(url)ifhtmlisNone:breakelse:#success-ca口scrapetheresultpasD设此时已到达最后一个国家的页面不过,这种实现方式存在一个缺陷,D到某个间隔点,爬虫就会立即退出。下面是这段代码的改进版本中连续发生多次下载错误后才会退出程序在该版#maximumnumberofconsecutivedownloaderrorsallowedmaxerrors=#currentnumberofconsecutivedownloaderrorsnumerrors=forpageiitertoolscountlurl=http/examplewebscrapingcom/view/-宅d屯html=download(url)ifhtmlisNone:#receivedannumerrors+=ifnumerrors#errortryingtodownloadthis1==maxerrorsmaximumnumber#consecutiveerrorssoexitbreakelse#success-canscrapetheresult#numerrors=wwwsimple00.om电子书分享14编写第一个网络爬虫上面代码中实现的爬虫需要连续5wwwsimple00.om电子书分享14编写第一个网络爬虫上面代码中实现的爬虫需要连续5次下载错误才会停止遍历,这样就很大站D,这种方法也无法保证始终可用。比如,一些网站会检查页面别名是否满足预期果不是返回404NtFound错误而另一些网站则会使用连续大数作为ID,或是不使用数值作为ID,此时遍历就难以发挥其作用了。例如Amazon使用SN作为图书ID这种编码包含至10位数字。使用D对Amazon的图书进行遍历需要测试数十亿次,因此这种方法肯定不是取该站内容最高效的方法1链接爬到目前为止,我们已经利用示例网站的结构特点实现了两个简单爬虫,用于下载所有的国家页只要这两种技术可用,就应当使用其进行爬因为这两种方法最小化了需要下载的网页数量。不过,对于另一些网站,我们让爬更像普,感兴内。通过跟踪所有链接的方式,我们可以很容易地下载整个网站页面但是,这种方法会下载大量我们并不需要的网页。例如,我们想要从一个在线论坛中抓取用户账号详情页,那么此时我们只需要下载账号页,而不需要下载讨论贴的页面。本节中的链接爬虫将使用正则表达式来确定需要下载哪些页面。下面是这段代码的初始版本importdeflink_crawler(seed_url,link_regex)”””CrawlfromthegivenseedURLfollowinglinksmatchedbylinkregex]。)-15wwwsimple00.om电子书分享eeaueelonesueww rqCeulewuweu4wwwsimple000.c算m机电子书分第1章网络wwwsimple000.c算m机电子书分第1章网络爬虫简#filterforlinksmatchingourregularexpressionforlinkingetlinks(html):ifre.match(linkregexlikcrawl_queue.append(link)defgetlinks(html)Retur口alistoflinksfrom#aregularexpressionextractalllinksfromthewebpageregex=pile(<a>]+href=[\]()[\re.#listofalllinksfromthewebpageretur口webpageregex.findall(html)’只需要调用licrawler函数,并传入两个参数要运行这段代码要爬取的网站URL和用于跟踪链接的正则表达式。对于示例网我们想爬取的是国家列表索引页和国家页面。其中,索引页链接格式如下•http:IIxaple.webscraping.com/x/1http:IIxaple.webscraping.com土口dex/•国家页链接格式如下http:I/xaple.webscraping.com//Afhaitan-httpI/examplewebscrapingcomview/Aland-Is口ds••因此,我们可以用/(index[view)/这个简单的正则表达式来匹配这两类网页 当爬虫使用这些输入参数运行时会发生什么呢?你会发现我们得到如下的下载错误》>linkcrawler(http/’,’I(indexIview)’)Downloading:http://Downloading:/index/1Traceback(mostrecentcalllast)ValueError:unknownurltypeIidex/1wwwsimple000.c算m机电子书分www.simple000co算机电子书分享网.4编写第一个网络爬虫可看出,出在下载/ndex/1时,该链接只有的路径部分正在浏览哪个网页,所以在浏览器浏览时,相对链接是能够正常工作的但是llib2无法获知上下文的为了让需要www.simple000co算机电子书分享网.4编写第一个网络爬虫可看出,出在下载/ndex/1时,该链接只有的路径部分正在浏览哪个网页,所以在浏览器浏览时,相对链接是能够正常工作的但是llib2无法获知上下文的为了让需要将链接转换为绝对链接的形式,以便包含定位2能够定位网页,我页的所有细节。如你Pyton中确实有用来实现一功能的模块该模块称为urparse面是licraler的改进版本使用urlparse模块来创建绝对路径importurlparsedeflink_crawler(seedurl,linkregex)”””CrawlfromthegivenseedURLfollowinglinksmatchedbylink---html=download(urlforlinkingetlinks(html)ifre.match(link_regex,link)lik=urlparseurljoinseedurllink)crawl_queue.append(link)当你运行这段代码时,会发现虽然网页下载没有出现错误,但是同样的点总是会被不断下载到这是因为这些地点相互之间存在链接。比如,澳大利亚链接到了南极洲,而南极洲也存在到澳大利亚的链接,此时爬虫就会要想避免重复爬取相同的链接它们之间不断循环下去我们需现URL的功能,可以避免重复下载rwler函数,己具备存储己deflinkcrawler(seedurl,linkregex)crawlqueue=[seedurl#keeptrackwhichURL’shaveseenbefore)口-)-)口www.simple000co算机电子书分享网14sppleueetaeuueeqoeSzurLeWoErereWacC1414eulErhcwewwwsimple00om电子书分享第wwwsimple00om电子书分享第l网络爬虫#checkiflinkmatchesexpectedregexifre.match(linkregex,link):#formabsolutelinklink=urlparseurljoin(seed_url,link)#checkifhavealreadyseenthislinkiflinknotiseenseen.crawlqueue.append(l当运行该脚本时,它会爬取所有地点,并且能够如期停止。最终,我们得高级功现在,让我们为链接爬虫添加一些功能,使其在爬取其他网站时更用。解robot.txt首先,我们需要解析robots.txt文件,以避免下载禁止爬取的URL用Python自带的robotparser模块,就可以轻松完成这项工作,如下的代码所示》>imp。rtz。b。》>rp=r。b。tparserRob。tFileParser()》>rp.set_urlhttp://ex四1plewebscraping.comrob。ts.txt’》>rpread()》》》url=’=’BadCrawlerrp.can_fetch(use�二agent url》》=G。。dCrawlerrpcan_fetch(user_agentlft函数确指定的用户代理是否允许访问网页在本例中当用户代理设为’BadCrawler’时,robotparser模块会返回结果表明无法获取网页这和示例网robotstxt的定义一样。18wwwsimple00om电子书分享wwwsimple00om电子书分享14编写第一个网络爬虫为了将该功能wwwsimple00om电子书分享14编写第一个网络爬虫为了将该功能集成到爬虫中,我们需要在crawl循环中添加该检查。whilecrawlqueuecrawl_queuep。purl#checkurlpassesrobots.txtrestrictionsifrp.can_fetch(user_agent,url):elseprintBl。ckedbyrobotstx支持代有时我们需要使用代理访问某个网比如,Netflix屏蔽了美国以外大多数国家。使用ib支持代理并没有想象中那么容易(可以尝试使用更友好PythonHTTP模块requests来实现该其文档地址为http//)下面是使用ib支持代理的代码proxyopener=urllib2.build_opener(pr。xyparams={urlparse.urlparse(url).scheme:proxy}。peneraddhandlerurllib2ProxyHandlerpr。xy_paramsresponse=openerpenrequestdefdownload(url,user_agent=’wswp’,proxy=None,num_retries=2)print’Downloading:’,urlheaders={’User-agent’user_agent}request=urllib2.Request(url,headers=headersopener=urllib2build一。penerifproxyproxyparams{urlparse.urlparse(url).scheme:proxy}openeraddhandlerurllib2Pr。xyHandler(proxyparams))tryhtml=openerpenrequestreadexcepturllib2URLErrorase:printDownladerrorereason19wwwsimple00om电子书分享算机电子书分享网1章网络爬虫简介html=ifnumretries算机电子书分享网1章网络爬虫简介html=ifnumretries>ifhasattr(e,’code’)and500<=e.code<#retrySXXHTTPerrorshtml=download(url,useragent,proxy,numretries-1)return下载F险。为了降低这些风险,我们可以在两次下载之间添加延时,从而对爬虫速下面是实现了该功能类的代码classThrottle”””Addadelaybetweendownloadstothesamedef一_init一_(selfdelay)#amountofdelaybetweendownloadsforeachdomainself.delay=delay#timestampofwhenadomainwaslastaccess=self.{}defwait(self,url)domain=urlparseurlparseurl).netl。last_accessed=selfd。mainsget(domainifselfdelay>0andlastaccessedisn。tNonesleepsecs=self.delay-(datetime.datetime.now()lastaccessed).secondsifsleepsecs>#domainhasbeenaccessedrecently#soneedtosleeptime.sleep(sleepsecs)#updatethelastaccessedtimeselfd。mainsd。main=datetimedatetime-Trtte类记录了每个域名上访问的时间,如果当前时间距离上访问时间小指定延时,则执行睡眠操作。我们可以在每次下载之Throttle对爬虫进行限速算机电子书分享网算机电子书分享网1编写第一个网络爬虫thr。ttle=Throttledelay)throttle.wait(urlresult=download(url,headers,proxy=proxy,numretries=numretries)避免爬虫陷目前,我们的爬虫会跟踪所算机电子书分享网1编写第一个网络爬虫thr。ttle=Throttledelay)throttle.wait(urlresult=download(url,headers,proxy=proxy,numretries=numretries)避免爬虫陷目前,我们的爬虫会跟踪所有之前没有访问过的链接。但是,一些网站会动态生成页面内容,这样就会出现无限多的网页比如网有一个在线日历功能,提供了可以访问下个月和下一年的链接,那么下个月的页面中同样会包含访问再下个月的链接,这样页面就会无止境地链接下去。这种情况被想要避免陷入爬虫陷阱,一个简单的方法是记录到达当前网页经过了多少个链接,也就是深度。当到达最大深度时,爬虫就不再向队列中添加该网页中的链接了。要实现这一功能,我们需要修改seen变量。该变量原先只录访问过的网页链接,现在修改为一个字典,增加了页面深度的记录deflinkcrawler(...,maxdepth=2):maxdepth=2口=电=--、。iflinknotinseen『+()该功能,只需将max_depth设为一个负数即可,此时当前深度永远不会与最终版这个高级链接爬虫的完整源代码可以在https:bitbucket.or/li_w3算机电子书分享网1htpeeknupnilLnenersneeeshefd第1章网络爬虫试这段代码,我们可以将用户代理设置为BCrw也就是章第1章网络爬虫试这段代码,我们可以将用户代理设置为BCrw也就是章前文从下面的运行结果中可以述的被robts.屏蔽了的那个用户代理爬虫果然被屏蔽了,代码启动后马上就会结束》》=’http://ex四iplewebscrapingc。lirgex=’/(ivie)》>link_crawler(seed_urlliregexuser_agent=’BadCrawler’Blockedbyrobots.txt:http://example.webscraping.现在,让我们使用默认的用户代理,并将最大深度设置为1,这样只有主》>li」crawlerseed_urlliregexD。wnl。ading:http/examplewebscrapingcomindexDownl。adinghttp/examplewebscrapingc。m/index/lDownl。ading:D。wnl。ading:D。wnloading:Downloading:Downloading:D。wnloading:D。wnloading:D。wnlading:http://example.webscraping.cov-and-Barbuda-10http://exa皿l.webscraping.c。m/view/Antarctica-9http://example.webscraping.c。皿/iewuilla-ht://example.webscraping.com/view/Ang。la7http://example.webscraping.com/view/Andorra-http://ex皿1ple.webscraping.c。m/view/阳.erican-Sa5http://ex四ple.w,由scraping.com/view/Algeria-4http://example.webscraping.com/view/Albania-http:/examplewebscrapingcom/view/Aland-工sl2http://example.webscraping.c。m/view/Afghanistan-1和预期一样,爬虫在下载完国家列表的第一页之后就停止了1.本章小结本章介绍了网络爬虫,然后开发了一个能够在后章节中用的成熟虫。此外,我们还介绍了一些外部工具和模块的使用方法,用于了解网站网站地图爬取延时以及各种爬取策略用户代理我们将讨论如何从己爬取到的网页中获取数据数据抓在上一章中,我们构建了一数据抓在上一章中,我们构建了一个爬虫,可以通过跟踪链接的方式下载我们所需的网页。虽然这个例子很有意思, 却不够实用, 因为爬虫在下载网页之后又将结果丢弃掉了。现在,我们需要让这个爬虫从每个网页中抽取一些数据然后实现某些事情这种做法也被称为抓取 首先,我们会介绍一FirebugLite的浏览器扩展,用于检查网页内容,如果你有一些网络开发背景的话,可能己经对该扩展十分熟悉了。然后,BeautiSoup们会介绍三种抽取网页数据的方法,分别是正则表达式lxml。最后,我们将对比这数据抓取方法2.分析网想要了解一个网页的结构如何 可以使用查看源代码的方法。在大多数览器中,都可以在页面上右键单击选择源代码,如图21所示pagesource选工页,获取网页我们可以在H刊伍的下述代码中找到我们感兴趣的数据<table><trid=”places_national_flag_row”><tdclass=”w2p_fl”><labefor=”places_national_flag2id=”placesnationallabel”>National</label></td><tdclass=”w2pfw”><imgsrc=”/ <trid=”places口eighboursfor=”placesid=”placesrow"><tdclass=”w2plabel”>Neighbours:' 2id=”placesnationallabel”>National</label></td><tdclass=”w2pfw”><imgsrc=”/ <trid=”places口eighboursfor=”placesid=”placesrow"><tdclass=”w2plabel”>Neighbours:' class=”w2pLc;i.:ir1器244,820squarekilorne甘NationalCurrencyC创eCurrencyNamePostalCodeFo『SaveTranslatetons因ctw1ll1Firebug•en-GB,cy-GIuser-AgentInspect对于浏览器解析而言,缺失空白符和格式并无大碍,但在我们阅读时则会造一定困难。要想更好地理解该表格,我们将使用FirebugLite扩展。该扩展适用于所有浏览器,我们可以通过https://getfirebugcomfirebuglite页面获取到该扩展。如果愿意的话,Firefox用户可以安装完整版的扩展,不过Lite版本己经包含了我们在本章和第6章中所用到的功能Firebug安装完成后可以右键单击我们在抓取中感兴扩展,不过Lite版本己经包含了我们在本章和第6章中所用到的功能Firebug安装完成后可以右键单击我们在抓取中感兴趣的网页部分e然后在菜单中选择Inspect如图2.2所示Cu厅encyCurrencySaveTranslatetoViewpageVi四'/pageNeighbou「Inspect并显示选中元素周此时,浏览器就会打开如图2.3所示的Firebug面板,围的HTML层次结构。如图2.3所示 当选择国家面积这一属性时 我们可以从Firebug面板清晰地看到,该值包含在class为w2pfw的td>元素中,而<td>元素又ID为places arearowtr元素的子元素。现在我们就获取到需要抓取的面积数据的所有信息了e计算机电子书第2数据抓取Script臼bodydata计算机电子书第2数据抓取Script臼bodydatady-mini;"sectionid=可nain"class=阴阳inrow与日divclass=·pn旦、国<fomaction=”#”enctype=飞ultipart/fonndata”mεthod=’'post”〉<tridplaces_nationaflag_rowtrid="lacsa_><tdclass="1"2p_fl”<td三种网页抓取方现在我们已经了解了该网页的结构,下面将要介绍三种抓取其中数据的方法。首先是正则表达式,然后是流行的BeautifulSoup模块,最后是强的lxml模块正则表达式还不熟悉,或是需要一些提示时httpsdocs.pytho日org/2/howtoregexhtml获得完整介绍首先需要尝试匹配<td>元素当我们使用正则表达式抓取面积数据时,的内容,如下所示。》〉工mport》>url=’httpelewebscrapi口gcom/view/Un工-Kingdom239》>html=download(url>>>re.findall(’<tdclass=”w2pw”(.*?)</td>’[’<imgsrc=”/places/stat工c/images/flags/gb.pnghtml/〉’计算机电子书2.2三种网页抓取方法’244,820squarekilometres’’62.2三种网页抓取方法’244,820squarekilometres’’62,348,7’,’G’UnitedKingd。m'L。ndonahref=letinent/EUEU/a>’,’.uk’,’GBP’,’Pound’,’@#@@I@##@@I自由##@日I@@##@@I@@@@I@@#自@@IGIRO"(([AZd2}[AZ2)I(AZ\d3}[AZ]2)([A-Z{2}\\d{2[A-Z]{2})I([A-Z]{2}\\d{3[-Z]{2}IAZd[AZdA』Z]2I([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})I(GIROA))$’’en-GB,cy-GB,gd’<divahref=isoEIEadiv从上述结果中可以看出,多个国家属性都使用了<tdclassw2fw标签。要想分离出面积属性,我们可以只选择其中的第二个元素,如下所示[lre.findall(’<tdclass=”w2pfw”>(.•?)</td>html244820squarekilmetres虽然现在可以使用这个方案,但是如果网页发生变化,该方案很可能就会失效。比如表格发生了变化,去除了第二行中的国土面积数据。如果我们只在现在抓取数据,就可以忽略这种未来可能发生的变化。但是,如果我们希望未来还能再次抓取该数据,就需要给出更加健壮的解决方案,从而尽可能避免这种布局变化所带来的影响。想要该正则表达式更加健壮,我们可以将其父元素tr>也加入进来。由于该元素具有ID属性,所以应该是唯一的》refindall(<trid=placesareaclass=”w2pfl”><labelfor=”placesareai”placesarealabel”>Area:</label><class=w2pfw()td,html[244820squarekilometreswwwsimple000om机电子书分wwwsimple000om机电子书分享网2章数据抓取这个迭代版本看起来更好一些,但是网页更新还有很多其他方式,同样可以让该正则表达式无法满足。比如,将双引号变为单引号,<td>标签之间添加多余的空格,或是变更area label等。下面是尝试支持这些可能性的改进版本》>refindall(<trid="places r。w>.•?<td\sclass=[\’]w2pfw[\’]〉(</td’,html[’244,820squarekilometres’虽然该正则表达式更容易适应未来变化,但又存在难以构造、可读性差的问题 此外 还有一些微小的布局变化也会使该正则表达式无法满足在td>标签里添加title属性。比如从本例中可以看出,正则表达式为我们提供了抓取数据的快捷方式,但该方法过于脆弱,容易在网页更新后出现问题。幸好,还有一些更好的解决方案,我们会在接下来的小节中继续介绍。2.2.2BeautifulBeautifulSoup是一个非常流行Python模块。该模块可以解析网提供定位内容的便捷接口。如果你还没有安装该模块,可以使用下面的命令安装其最新版本pipinstallils。BeautifulSoup的第一步是将己下载的内容解析为soup文档使由于大多数网页都不具备良好的HTML格式,因此BeautifulSoup需要对其实际格式进行确定。例如,在下面这个简单网页的列表中,存在属性值两侧引号缺失和标签未闭含的问题<ulclass=country><li>Area<li>P。pulation</wwwsimple000om机电子书分享网算机电子书分享网2.2方法如果Population列表项被解析为Area列表项的子元素,而不是并的两算机电子书分享网2.2方法如果Population列表项被解析为Area列表项的子元素,而不是并的两个列表项的话,我们在抓取时就会得到错误的结果。下面让我们看一BeautifulSoup是如何处理的①。》>frombs4importBeautifulSoup》》》》》br。kenhtml=<ulclass=country><li>Areali>Populationul#parsethesoup=BeautifulSoup(broken_html,’html.parser’fixedhtml=soup.prettifyprintfixed<ulclass=country<li>Area</工<li>Population</li></ul></body></Soup从上面的执行结果中可以看出Beauti能够正确解析缺失的引号并闭合标签,此外还添加了<html>和<body>标签使其成为完整findall()方法来定位我们需要的HTML文档。现在可以使用元素了find()》>ul=soupfind(ul’,attrs={class’coutry})ulfind(li)#returnsjustthefirst<li>Area</li>ulfindall(l)#returnsallmatche[¢除了…倒叫……档li>ArealiliPopulatili其网址为:httpwww.crummycomsoftwareBeautifu1Soup/bs4doc/①译者注2此处使用的是时也on内置库,由于不同版本的容错能力有所区别,读者在实践中可能无法得到正确结果。相关内容可参考zhttpswwwcrummy.comsoftware/Beautifu1Soup/bs4doc/installingaparser.算机电子书分享网2章数据抓取下面是使用该方法抽取示例国家面积数据的完整代码》》frombs4importBeautifulSoup2章数据抓取下面是使用该方法抽取示例国家面积数据的完整代码》》frombs4importBeautifulSoupurl=’http:///places/view/UnitedKingdom239’html=download(urlsoup=BeautifulSoup(html#1catethearea》》》》》》trtdareasoup.find(attrs={’id’:’places_area_row’})tr.find(attrs={’class’:’w2p_f’))#locate=td.text#extractthetextfromthisarea》>print244,820squarekilometres这段代码虽然比正则表达式的代码更加复杂,但更容易构造和理解。而且,像多余的空格和标签属性这种布局上的小变化,我们也无须再担心了2.2.3Lxml是基于libxml2这一XML解析库的Python封装。该模块使用语言编写,解析速度比BeautifulSoup更快,不过安装过程也更为复杂。最的安装说明可以参考http://Lxmlde/installationhtml和Soup一样,使lxml模块的第一步也是将有可能不合法的HTML解析为统一格式。下面是使用该模块解析同一个不完整HTML的例子》>importlxml》>brokenhtml=<ulclass=country><li>Area<li>Population<ul》》》tree=lxml.html.fromstring(broken_html)#parsethefixedhtml=lxml.html.tostring(tree,pretty_print=True)printfixed_htmlclass=”country"><li>Area</li><li>Population</li></lxml也可以正确解析属性两侧缺失的引号,并闭合标签不同样地,该模块没有额外添加<html>和<body>标签www.simple000co算机电子书分享网2.2三种网页抓取方法解析完输入内容之后, 进入选择元www.s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024货物进口合同(范本)
- 2024年广西路分公司一级干线运输合同
- 2024年度数据处理与分析合作协议
- 2024个人房产抵押合同
- 2024年基因治疗技术开发合同
- 2024年度智能医疗系统开发合同
- 2024年度建筑施工安全环保技术创新与应用合同
- 2024年废料交易合同标准版
- 2024年建筑基坑钻探检测合同
- 2024年度F公司太阳能发电设备安装合同
- 全国高职高专英语写作大赛
- 微机原理与接口技术8259A练习题及答案
- 正方体的11种展开图
- 第15章《分式》教材分析课件(32张)
- 商铺装修工程施工方案.
- 西门子RWD68说明书
- 形式发票样本(Proforma Invoice)
- 医院车辆加油卡管理制度
- 数独题目高级50题(后附答案)【最新】
- 问题线索办理呈批表
- 学、练、评一体化课堂模式下赛的两个问题与对策
评论
0/150
提交评论