python爬虫.doc

上传人:一*** 文档编号:2742113 上传时间:2020-05-02 格式:DOC 页数:86 大小:5.96MB
返回 下载 相关 举报
python爬虫.doc_第1页
第1页 / 共86页
python爬虫.doc_第2页
第2页 / 共86页
点击查看更多>>
资源描述

《python爬虫.doc》由会员分享,可在线阅读,更多相关《python爬虫.doc(86页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、.*第一章 零基础入门000 介绍爬虫技术是数据挖掘,测试技术的重要的组成部分,是搜索引擎技术的核心。但是作为一项普通的技术,普通人同样可以用爬虫技术做很多很多的事情,比如:你想了解一下FreeBuf所有关于爬虫技术的文章,你就可以编写爬虫去对FreeBuf的文章进行搜索,解析。比如你想获得淘宝某类商品的价格,你可以编写爬虫自动搜索某类商品,然后获取信息,得到自己想要的结果,每天定时爬一下自己就可以决定在什么时候低价的时候买下心仪的商品了。或者说自己想收集某类信息集合成自己的数据库,但是手动复制粘贴特别的麻烦,这时候爬虫技术就可以帮上大忙了对不对?001 要求那么本系列文章旨在普及爬虫技术,当

2、然不是那种直接拿来爬虫框架来说明的。在本系列文章中,笔者尽力从简到难,简明地介绍爬虫的各种要素,怎么样快速编写对自己有用的代码。但是对读者有一定小小的要求:看得懂python代码,然后自己能动手实践一些,除此之外,还要对html元素有一定的了解。002 你能学到什么?当然爬虫的文章在网上很容易找到,但是精致,系统地讲解的文章还是比较少,笔者在本文和今后的文章将介绍关于爬虫的各种各样的知识:大致上,本文的写作顺序是单机爬虫到分布式爬虫,功能实现到整体设计,从微观到宏观。1.简单模块编写简单爬虫2.相对优雅的爬虫3.爬虫基本理论以及一般方法4.简单Web数据挖掘5.动态web爬虫(可以处理js的爬

3、虫)6.爬虫的数据存储7.多线程与分布式爬虫设计如果有读者想找一些爬虫的入门书籍来看,我推荐web scraping with python,这本书是英文版目前没有中文译本,但是网上有爱好者在翻译,有兴趣的读者可以了解一下。003 知识补充在这里的知识补充我其实是要简单介绍目前主流的几种爬虫编写用的模块:Htmllib(sgmllib),这个模块是非常古老的一个模块,偏底层,实际就是简单解析html文档而已,不支持搜索标签,容错性也比较差,这里指的提醒的是,如果传入的html文档没有正确结束的话,这个模块是不会解析的,直到正确的数据传入或者说强行关闭。BeautifulSoup,这个模块解析h

4、tml非常专业,具有很好的容错性,可以搜索任意标签,自带编码处理方案。Selenium,自动化web测试方案解决者,类似BeautifulSoup,但是不一样的是,selenium自带了js解释器,也就是说selenium配合浏览器可以用来做动态网页的爬取,分析,挖掘。Scrapy框架:一个专业的爬虫框架(单机),有相对完整的解决方案。API爬虫:这里大概都是需要付费的爬虫API,比如google,twitter的解决方案,就不在介绍。笔者在文章中只会出现前三种方式来做爬虫编写。004 最简单的开始最开始的一个例子,我将会先介绍最简单的模块,编写最简单的单页爬虫:Urllib这个模块我们这里用

5、来获取一个页面的html文档,具体的使用是,Web = urllib.urlopen(url)Data = Web.read()要注意的是,这是py2的写法,py3是不一样的。Smgllib这个库是htmllib的底层,但是也可以提供一个对html文本的解析方案,具体的使用方法是:1.自定义一个类,继承sgmllib的SGMLParser;2.复写SGMLParser的方法,添加自己自定义的标签处理函数3.通过自定义的类的对象的.feed(data)把要解析的数据传入解析器,然后自定义的方法自动生效。import urllibimport sgmllibclass handle_html(sg

6、mllib.SGMLParser): #unknown_starttag这个方法在任意的标签开始被解析时调用 #tag为标签名 #attrs表示标签的参赛 def unknown_starttag(self, tag, attrs): print -+tag+ start- print attrs #unknown_endtag这个方法在任意标签结束被解析时被调用 def unknown_endtag(self, tag): print -+tag+ end-web =urllib.urlopen(http:/ = handle_html()#数据传入解析器web_handler.feed(w

7、eb.read()短短十几行代码,最简单的单页面爬虫就完成了,以下是输出的效果。我们可以看到标签开始和结束都被标记了。然后同时打印出了每一个参数。接下来我们可以使用这种底层的解析方式来做个基础的小例子:下面这个小例子在标签开始的时候检查标签中的attrs属性,解析出所有的参数的href属性,知道的读者都知道这基本是被一个爬虫的必经之路。import urllibimport sgmllibclass handle_html(sgmllib.SGMLParser):defunknown_starttag(self, tag, attrs): #这里利用try与except来避免报错。 #但是并不

8、推荐这样做, #对于这种小脚本虽然无伤大雅,但是在实际的项目处理中,#这种做法存在很大的隐患 try: for attr in attrs: if attr0 = href: printattr0+:+attr1.encode(utf-8) except: passweb =urllib.urlopen(http:/ = handle_html()web_handler.feed(web.read()解析结果为:我们发现在解析出的href种,存在一些不和谐的因素,比如JavaScript的出现,比如其他域名的出现,或者有些读者说的,url有重复。实际上,这是对于我们的FreeBuf站来说,但是

9、对于互联网上的各种复杂环境来说,上面的考虑是完全不够的。关于这一点我们稍后再做讨论。但是笔者并不计划就用这个方法来把我们的问题处理完全。因为我们有更优雅的解决方案。005 更优雅的解决方案当然我说的时BeautifulSoup,为什么选用这个模块呢?笔者私认为这个模块解析html非常专业,这里简称bs4,读过bs4的读者都很清楚。实际上beautifulsoup并不只是简单的解析html文档,实际上里面大有玄机:五种解析器自动选择或者手动指定,每个解析器的偏重方向都不一样,有的偏重速度,有的偏重正确率。自动识别html文档的编码,并且给出非常完美的解决方案,支持css筛选,各种参数的方便使用。

10、BeautifulSoup的一般使用步骤:1.导入beatifulsoup库 :from bs4 import BeautifulSoup2.传入数据,建立对象: soup = BeautifulSoup(data),3.操作soup,完成需求解析。下面我们来看具体的代码实例:from bs4 import BeautifulSoupimport urllibimport reweb =urllib.urlopen(http:/ = BeautifulSoup(web.read()tags_a =soup.findAll(name=a,attrs=href:pile(https?:/)for

11、tag_a in tags_a:printtag_ahref这一段与sgmllib的第二短代码相同功能,但写起来就更加的优雅。然后还引入了正则表达式,稍微过滤下链接的表达式,过滤掉了JavaScript字样,显然看起来简炼多了:简单解释一下上面的warning:UserWarning: No parser was explicitlyspecified, so Im using the best available HTML parser for this system(“html.parser”). This usually isnt a problem, but if you run th

12、iscode on another system, or in a different virtual environment, it may use adifferent parser and behave differently.To get rid of this warning, change this:BeautifulSoup(your markup)to this:BeautifulSoup(your markup,”html.parser”)上面的内容是说:没有特别指明解析器,bs4使用了它认为最好的解析器html.parser,这一般不会出问题,但是如果你在不同的环境下运行,

13、可能解析器是不一样的。要移除这个warning可以修改你的beautifulsoup选项改成BeautifulSoup(data, “html.parser”)这个warning表明了bs4的自动选择解析器来解析的特性。006 url和合法性判断url与uri其实是一个东西,如果但是我们更多的不提uri,那么我们来说一下关于url的处理:如果说像我们一开始那样做的话,我们手动,或者通过正则去分析每一个url,我们要考虑url的各种结构,比如下面这些例子:path?ss=1#archhttp:/ urlparseurl = set()url.add(javascript:void(0)url.a

14、dd(http:/ item in url:print item o= urlparse.urlparse(item)print oprint然后执行代码,我们可以看一下具体的解析结果:import urlparseurl = set()url.add(javascript:void(0)url.add(http:/ item in url: print item o= urlparse.urlparse(item) print o printpath?ss=1#archParseResult(scheme=, netloc=,path=path, params=, query=ss=1, f

15、ragment=arch)http:/ path=/geek, params=, query=, fragment=)?ss=1ParseResult(scheme=, netloc=, path=,params=, query=ss=1, fragment=)path/meParseResult(scheme=, netloc=,path=path/me, params=, query=, fragment=)javascript:void(0)ParseResult(scheme=javascript, netloc=,path=void(0), params=, query=, frag

16、ment=)/ netloc=, path=/ query=, fragment=)sssfadea:/ssss.ssParseResult(scheme=sssfadea,netloc=ssss.ss, path=, params=, query=, fragment=)path?ss=1&s=1ParseResult(scheme=, netloc=,path=path, params=, query=ss=1&s=1, fragment=)ftp:/ path=/ss/s/s, params=, query=, fragment=)path?ss=1ParseResult(scheme=

17、, netloc=,path=path, params=, query=ss=1, fragment=)#archParseResult(scheme=, netloc=, path=,params=, query=, fragment=arch)/ path=/s/s/s/, params=, query=, fragment=)https:/:443/geek?id=1#sidParseResult(scheme=https,netloc=:443, path=/geek, params=, query=id=1,fragment=sid)/ path=/s/s/s, params=, q

18、uery=, fragment=)在urlparser返回的对象中我们可以直接以索引的方式拿到每一个参数的值。那么我们这里就有索引表了:这张表的用法,o = urlparse.urlparse(url)o0表示schemeo1表示netloc以此类推。我们发现:如果scheme和netloc都同时为空的话,该url可能是当前url+path如果scheme不为空但是netloc为空的话,该url不合法如果scheme为空但是netloc不为空的话,不一定不合法,要具体分析,一般情况下是http如果只存在fragment或者query的话,该url为当前的url+query+fragment那么

19、根据上面的规则,我们基本可以把无关的url或者不是url排除掉,或者恢复完整的url007 总结与预告本章中我们一起探究了一个简单爬虫的实现,然后稍微讨论了一下如何处理页面的url。相信读者读完本文的时候已经有了一定的对爬虫的基础认识,但是要知道,只了解到这种程度还不能说了解爬虫,这只是冰山一角。在下一节中,我们将学到下面的知识:1、爬虫道德与爬虫的理论知识2、sitemap爬虫3、简单web数据处理000 介绍001 协议002 原则003 确立目标与分析过程004 动手005 sitemap爬虫006 web元素处理007 总结与预告第二章 整站爬虫与Web挖掘000 介绍在互联网这个复杂

20、的环境中,搜索引擎本身的爬虫,出于个人目的的爬虫,商业爬虫肆意横行,肆意掠夺网上的或者公共或者私人的资源。显然数据的收集并不是为所欲为,有一些协议或者原则还是需要每一个人注意。本文主要介绍关于爬虫的一些理论和约定协议,然后相对完整完成一个爬虫的基本功能。001 协议一般情况下网站的根目录下存在着一个robots.txt的文件,用于告诉爬虫那些文件夹或者哪些文件是网站的拥有者或者管理员不希望被搜索引擎和爬虫浏览的,或者是不希望被非人类的东西查看的。但是不仅仅如此,在这个文件中,有时候还会指明sitemap的位置,爬虫可以直接寻找sitemap而不用费力去爬取网站,制作自己的sitemap。那么最

21、好我们看个具体的例子吧,这样更有助于理解robots协议:-以下时freebuf的robots.txt-User-agent: *Disallow: /*?*Disallow: /trackbackDisallow: /wp-*/Disallow: */comment-page-*Disallow: /*?replytocom=*Disallow: */trackbackDisallow: /?randomDisallow: */feedDisallow: /*.css$Disallow: /*.js$Sitemap: http:/ 原则如果协议不存在的话,我们仍然不能为所欲为,上网随意搜索一

22、下源于爬虫协议的官司,国内外都有。爬虫的协议规则建立在如下的基础上:1.搜索技术应该服务于人类,尊重信息提供者的意愿,并维护其隐私权;2.网站也有义务保护其使用者的个人信息和隐私不被侵犯。简单来说,就是构建的爬虫以信息收集为目的是没错的,但是不能侵犯别人的隐私,比如你扫描并且进入了网站的robots中的disallow字段,你就可能涉及侵犯别人隐私的问题。当然作为一般人来讲,我们使用爬虫技术无非是学习,或者是搜集想要的信息,并没有想那么多的侵权,或者是商业的问题。003 确立目标与分析过程这里我提供一个爬虫诞生要经历的一般过程:1 确立需求在,sitemap中挑选出需要挖掘的页面;2 依次分析

23、挑选出的页面;3 存储分析结果。但是有时候问题就是,我们的目标网站没有提供sitemap,那么这就得麻烦我们自己去获取自己定制的sitemap。目标:制作一个网站的sitemap:分析:我们要完成这个过程,但是不存在现成sitemap,笔者建议大家把这个网站想象成一个图的结构,网站的url之间纵横交错,我们可以通过主页面进行深度优先或者广度优先搜索从而遍历整个网站拿到sitemap。显然我们发现,我们首先要做的第一步就是完整的获取整个页面的url。但是我们首先得想清楚一个问题:我们获取到的url是应该是要限制域名的,如果爬虫从目标网站跳走了,也就意味着将无限陷入整个网络进行挖掘。这么庞大的数据

24、量,我想不是一般人的电脑硬盘可以承受的吧!那么我们的第一步就是编写代码去获取整个页面的url。其实这个例子在上一篇文章中已经讲到过。004 动手我们的第一个小目标就是获取当前页面所有的url:首先必须说明的是,这个脚本并不具有普遍性(只针对),并且效率低下,可以优化的地方很多:只是为了方便,简单实现了功能,有兴趣的朋友可以任意重构达到高效优雅的目的import urllibfrom bs4 import BeautifulSoupimport redef get_all_url(url):urls = web = urllib.urlopen(url)soup =BeautifulSoup(w

25、eb.read()#通过正则过滤合理的url(针对与来讲)tags_a =soup.findAll(name=a,attrs=href:pile(https?:/) try :for tag_a in tags_a:urls.append(tag_ahref)#return urlsexcept:passreturn urls#得到所有下的urldef get_local_urls(url):local_urls = urls = get_all_url(url)for _url in urls:ret = _urlif in ret.replace(/,).split(/)0:local_

26、urls.append(_url)return local_urls#得到所有的不是域名的urldef get_remote_urls(url):remote_urls = urls = get_all_url(url)for _url in urls:ret = _urlif not in ret.replace(/,).split(/)0:remote_urls.append(_url)return remote_urlsdef _main_():url = http:/ = get_remote_urls(url)print -remote urls-for ret in rurls:

27、print retprint -localurls-lurls = get_local_urls(url)for ret in lurls:print retif _name_ = _main_:_main_()这样我们就得到了该页面的url,本域名和其他域名下:当然图中所示的结果为部分截图,至少证明了我们上面的代码比较好的解决的url获取的问题,由于这里我们的判断规则简单,还有很多情况没有考虑到,所以建议大家如果有时间,可以把上面代码重构成更佳普适,更加完整的脚本,再投入真正的实际使用。005 sitemap爬虫所谓的sitemap,我们在上面的例子中又讲到sitemap记录了整个网站的网站

28、拥有者允许你爬取内容的链接。但是很多情况下,sitemap没有写出,那么问题就来了,我们面对一个陌生的网站如何进行爬取(在不存在sitemap的情况下).当然我们首先要获取sitemap,没有现成的我们就自己动手获取整个网站的sitemap。再开始之前我们需要整理一下思路:我们可以把整站当成一个错综复杂的图结构,有一些算法基础的读者都会知道图的简单遍历方法:dfs和bfs(深度优先和广度优先)。如果这里读者有问题的话建议先去学习一下这两种算法。大体的算法结构我们清楚了,但是在实现中我们显然需要特殊处理url,需要可以区分当前目标站点域名下的网站和其他域名的网站,除此之外,在href的值中经常会

29、出现相对url,这里也要特别处理。import urllibfrom bs4 import BeautifulSoupimport urlparseimport timeimport urllib2url = http:/xxxx.xx/domain = xxxx.xxdeep = 0tmp = sites = set()visited = set()#local = set()def get_local_pages(url,domain):global deepglobal sitesglobal tmprepeat_time = 0pages = set() #防止url读取卡住while

30、 True:try:print Ready to Open the web!time.sleep(1)print Opening the web, urlweb = urllib2.urlopen(url=url,timeout=3)print Success to Open the webbreakexcept:print Open Url Failed ! Repeattime.sleep(1)repeat_time = repeat_time+1if repeat_time = 5: returnprint Readint the web .soup = BeautifulSoup(we

31、b.read()print .tags = soup.findAll(name=a)for tag in tags:#避免参数传递异常try:ret = taghrefexcept:print Maybe not the attr : hrefcontinueo = urlparse.urlparse(ret)#Debug I/Ofor _ret in o:if _ret = : passelse: print _ret#处理相对路径urlif o0 is and o1 is :print Fix Page: +returl_obj = urlparse.urlparse(web.geturl

32、()ret = url_obj0 + :/ + url_obj1 + url_obj2 + ret#保持url的干净ret = ret:8 + ret8:.replace(/,/)o = urlparse.urlparse(ret) #这里不是太完善,但是可以应付一般情况if ./ in o2: paths = o2.split(/)for i inrange(len(paths): if pathsi = .: pathsi = if pathsi-1: pathsi-1 = tmp_path = for path in paths: if path = : continue tmp_pat

33、h = tmp_path + / +path ret =ret.replace(o2,ret_path)print FixedPage: + ret#协议处理if http not in o0:print Bad Page: + ret.encode(ascii)continue#url合理性检验if o0 is and o1 is not :print Bad Page: +retcontinue#域名检验if domain not in o1:print Bad Page: +retcontinue#整理,输出newpage = retif newpage not in sites:print Add New Page: + newpagepages.add(newpage)return pages#dfs算法遍历全站def dfs(pages): #无法获取新的url说明便利完成,即可结束dfsif pages is set():returnglobal urlglobal domainglobal sitesglobal visited

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com